fix(perf): direct field access

Signed-off-by: MastahSenpai <26342994+ii64@users.noreply.github.com>
This commit is contained in:
MastahSenpai 2022-01-26 01:20:07 +07:00
parent 6fb11e879d
commit 5937800f05
Signed by untrusted user who does not match committer: Xeffy
GPG key ID: E41C08AD390E7C49
4 changed files with 60 additions and 115 deletions

View file

@ -61,10 +61,10 @@ func (r *Ring) Fd() int {
return r.fd return r.fd
} }
func (r *Ring) SQ() *SQRing { func (r *Ring) SQ() SQRing {
return &r.sq return r.sq
} }
func (r *Ring) CQ() *CQRing { func (r *Ring) CQ() CQRing {
return &r.cq return r.cq
} }

View file

@ -23,10 +23,11 @@ func TestCore(t *testing.T) {
sq := ring.SQ() sq := ring.SQ()
n := 5 n := 5
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
sqTail := *sq.Tail() sqTail := *sq.Tail
sqIdx := sqTail & *sq.RingMask() sqIdx := sqTail & *sq.RingMask
sqe := sq.Get(sqIdx) sqe := &sq.Event[sqIdx]
sqe.Reset()
m := mkdata(i) m := mkdata(i)
@ -37,8 +38,8 @@ func TestCore(t *testing.T) {
sqe.SetOffset(0) sqe.SetOffset(0)
sqe.SetAddr(&m[0]) sqe.SetAddr(&m[0])
*sq.Array().Get(sqIdx) = *sq.Head() & *sq.RingMask() *sq.Array.Get(sqIdx) = *sq.Head & *sq.RingMask
*sq.Tail()++ *sq.Tail++
done, err := ring.Enter(1, 1, IORING_ENTER_GETEVENTS, nil) done, err := ring.Enter(1, 1, IORING_ENTER_GETEVENTS, nil)
assert.NoError(t, err, "ring enter") assert.NoError(t, err, "ring enter")
@ -47,13 +48,13 @@ func TestCore(t *testing.T) {
// get cq // get cq
cq := ring.CQ() cq := ring.CQ()
for i := 0; i < int(*cq.Tail()); i++ { for i := 0; i < int(*cq.Tail); i++ {
cqHead := *cq.Head() cqHead := *cq.Head
cqIdx := cqHead & *cq.RingMask() cqIdx := cqHead & *cq.RingMask
cqe := cq.Get(cqIdx) cqe := cq.Event[cqIdx]
*cq.Head()++ *cq.Head++
t.Logf("CQE %+#v", cqe) t.Logf("CQE %+#v", cqe)
} }

View file

@ -1,6 +1,8 @@
package gouring package gouring
import ( import (
"fmt"
"reflect"
"syscall" "syscall"
"unsafe" "unsafe"
@ -68,15 +70,14 @@ func setup(r *Ring, entries uint, parmas *IOUringParams) (ringFd int, err error)
r.sqRingPtr = sqRingPtr r.sqRingPtr = sqRingPtr
r.cqRingPtr = cqRingPtr r.cqRingPtr = cqRingPtr
// // SQ
// address Go's ring with base+offset allocated sq.Head = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.Head)))
sq.head = sqRingPtr + uintptr(p.SQOff.Head) sq.Tail = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.Tail)))
sq.tail = sqRingPtr + uintptr(p.SQOff.Tail) sq.RingMask = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.RingMask)))
sq.ringMask = sqRingPtr + uintptr(p.SQOff.RingMask) sq.RingEntries = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.RingEntries)))
sq.ringEntries = sqRingPtr + uintptr(p.SQOff.RingEntries) sq.Flags = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.Flags)))
sq.flags = sqRingPtr + uintptr(p.SQOff.Flags) sq.Array = uint32Array(sqRingPtr + uintptr(p.SQOff.Array)) // non fixed array size, controlled by ring mask
sq.array = uint32Array(sqRingPtr + uintptr(p.SQOff.Array))
r.sqesPtr, err = mmap(0, uintptr(p.SQEntries*uint32(_sz_sqe)), r.sqesPtr, err = mmap(0, uintptr(p.SQEntries*uint32(_sz_sqe)),
syscall.PROT_READ|syscall.PROT_WRITE, syscall.PROT_READ|syscall.PROT_WRITE,
syscall.MAP_SHARED|syscall.MAP_POPULATE, syscall.MAP_SHARED|syscall.MAP_POPULATE,
@ -85,15 +86,30 @@ func setup(r *Ring, entries uint, parmas *IOUringParams) (ringFd int, err error)
err = errors.Wrap(err, "mmap sqes") err = errors.Wrap(err, "mmap sqes")
return return
} }
sq.sqes = sqeArray(r.sqesPtr)
// sq.Event = *(*[]SQEntry)(unsafe.Pointer(&reflect.SliceHeader{
Data: r.sqesPtr,
Len: int(p.SQEntries),
Cap: int(p.SQEntries),
}))
cq.head = cqRingPtr + uintptr(p.CQOff.Head) fmt.Printf("insp %+#v %+#v\n", len(sq.Event), cap(sq.Event))
cq.tail = cqRingPtr + uintptr(p.CQOff.Tail)
cq.ringMask = cqRingPtr + uintptr(p.CQOff.RingMask) // CQ
cq.ringEntries = cqRingPtr + uintptr(p.CQOff.RingEntries)
cq.cqes = cqeArray(cqRingPtr + uintptr(p.CQOff.CQEs)) cq.Head = (*uint32)(unsafe.Pointer(cqRingPtr + uintptr(p.CQOff.Head)))
cq.Tail = (*uint32)(unsafe.Pointer(cqRingPtr + uintptr(p.CQOff.Tail)))
cq.RingMask = (*uint32)(unsafe.Pointer(cqRingPtr + uintptr(p.CQOff.RingMask)))
cq.RingEntries = (*uint32)(unsafe.Pointer(cqRingPtr + uintptr(p.CQOff.RingEntries)))
cqesPtr := cqRingPtr + uintptr(p.CQOff.CQEs)
cq.Event = *(*[]CQEntry)(unsafe.Pointer(&reflect.SliceHeader{
Data: cqesPtr,
Len: int(p.CQEntries),
Cap: int(p.CQEntries),
}))
fmt.Printf("insp %+#v %+#v\n", len(cq.Event), cap(cq.Event))
return return
} }

100
ring.go
View file

@ -20,48 +20,20 @@ type Ring struct {
//-- SQ //-- SQ
type SQRing struct { type SQRing struct {
head uintptr Head *uint32
tail uintptr Tail *uint32
ringMask uintptr RingMask *uint32
ringEntries uintptr RingEntries *uint32
flags uintptr Flags *uint32
array uint32Array Array uint32Array
sqes sqeArray Event []SQEntry
}
func (sq SQRing) Get(idx uint32) *SQEntry {
if uintptr(idx) >= uintptr(*sq.RingEntries()) {
return nil
}
return sq.sqes.Get(uintptr(idx))
}
func (sq SQRing) Head() *uint32 {
return (*uint32)(unsafe.Pointer(sq.head))
}
func (sq SQRing) Tail() *uint32 {
return (*uint32)(unsafe.Pointer(sq.tail))
}
func (sq SQRing) RingMask() *uint32 {
return (*uint32)(unsafe.Pointer(sq.ringMask))
}
func (sq SQRing) RingEntries() *uint32 {
return (*uint32)(unsafe.Pointer(sq.ringEntries))
}
func (sq SQRing) Flags() *uint32 {
return (*uint32)(unsafe.Pointer(sq.flags))
}
func (sq SQRing) Array() uint32Array {
return sq.array
}
func (sq SQRing) Event() sqeArray {
return sq.sqes
} }
func (sq SQRing) IsCQOverflow() bool { func (sq SQRing) IsCQOverflow() bool {
return atomic.LoadUint32(sq.Flags())&IORING_SQ_CQ_OVERFLOW > 0 return atomic.LoadUint32(sq.Flags)&IORING_SQ_CQ_OVERFLOW > 0
} }
func (sq SQRing) IsNeedWakeup() bool { func (sq SQRing) IsNeedWakeup() bool {
return atomic.LoadUint32(sq.Flags())&IORING_SQ_NEED_WAKEUP > 0 return atomic.LoadUint32(sq.Flags)&IORING_SQ_NEED_WAKEUP > 0
} }
// //
@ -75,57 +47,13 @@ func (a uint32Array) Set(idx uint32, v uint32) {
atomic.StoreUint32(a.Get(idx), v) atomic.StoreUint32(a.Get(idx), v)
} }
type sqeArray uintptr
func (sa sqeArray) Get(idx uintptr) *SQEntry {
return (*SQEntry)(unsafe.Pointer(uintptr(sa) + idx*_sz_sqe))
}
func (sa sqeArray) Set(idx uintptr, v SQEntry) {
*sa.Get(idx) = v
}
// //
//-- CQ //-- CQ
type CQRing struct { type CQRing struct {
head uintptr Head *uint32
tail uintptr Tail *uint32
ringMask uintptr RingMask *uint32
ringEntries uintptr RingEntries *uint32
cqes cqeArray Event []CQEntry
}
func (cq CQRing) Get(idx uint32) *CQEntry {
if uintptr(idx) >= uintptr(*cq.RingEntries()) { // avoid lookup overflow
return nil
}
return cq.cqes.Get(uintptr(idx))
}
func (cq CQRing) Head() *uint32 {
return (*uint32)(unsafe.Pointer(cq.head))
}
func (cq CQRing) Tail() *uint32 {
return (*uint32)(unsafe.Pointer(cq.tail))
}
func (cq CQRing) RingMask() *uint32 {
return (*uint32)(unsafe.Pointer(cq.ringMask))
}
func (cq CQRing) RingEntries() *uint32 {
return (*uint32)(unsafe.Pointer(cq.ringEntries))
}
func (cq CQRing) Event() cqeArray {
return cq.cqes
}
//
type cqeArray uintptr
func (ca cqeArray) Get(idx uintptr) *CQEntry {
return (*CQEntry)(unsafe.Pointer(uintptr(ca) + idx*_sz_cqe))
}
func (ca cqeArray) Set(idx uintptr, v CQEntry) {
*ca.Get(idx) = v
} }