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
}
func (r *Ring) SQ() *SQRing {
return &r.sq
func (r *Ring) SQ() SQRing {
return r.sq
}
func (r *Ring) CQ() *CQRing {
return &r.cq
func (r *Ring) CQ() CQRing {
return r.cq
}

View file

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

View file

@ -1,6 +1,8 @@
package gouring
import (
"fmt"
"reflect"
"syscall"
"unsafe"
@ -68,15 +70,14 @@ func setup(r *Ring, entries uint, parmas *IOUringParams) (ringFd int, err error)
r.sqRingPtr = sqRingPtr
r.cqRingPtr = cqRingPtr
//
// SQ
// address Go's ring with base+offset allocated
sq.head = sqRingPtr + uintptr(p.SQOff.Head)
sq.tail = sqRingPtr + uintptr(p.SQOff.Tail)
sq.ringMask = sqRingPtr + uintptr(p.SQOff.RingMask)
sq.ringEntries = sqRingPtr + uintptr(p.SQOff.RingEntries)
sq.flags = sqRingPtr + uintptr(p.SQOff.Flags)
sq.array = uint32Array(sqRingPtr + uintptr(p.SQOff.Array))
sq.Head = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.Head)))
sq.Tail = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.Tail)))
sq.RingMask = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.RingMask)))
sq.RingEntries = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.RingEntries)))
sq.Flags = (*uint32)(unsafe.Pointer(sqRingPtr + uintptr(p.SQOff.Flags)))
sq.Array = uint32Array(sqRingPtr + uintptr(p.SQOff.Array)) // non fixed array size, controlled by ring mask
r.sqesPtr, err = mmap(0, uintptr(p.SQEntries*uint32(_sz_sqe)),
syscall.PROT_READ|syscall.PROT_WRITE,
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")
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)
cq.tail = cqRingPtr + uintptr(p.CQOff.Tail)
cq.ringMask = cqRingPtr + uintptr(p.CQOff.RingMask)
cq.ringEntries = cqRingPtr + uintptr(p.CQOff.RingEntries)
cq.cqes = cqeArray(cqRingPtr + uintptr(p.CQOff.CQEs))
fmt.Printf("insp %+#v %+#v\n", len(sq.Event), cap(sq.Event))
// CQ
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
}

100
ring.go
View file

@ -20,48 +20,20 @@ type Ring struct {
//-- SQ
type SQRing struct {
head uintptr
tail uintptr
ringMask uintptr
ringEntries uintptr
flags uintptr
array uint32Array
sqes sqeArray
}
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
Head *uint32
Tail *uint32
RingMask *uint32
RingEntries *uint32
Flags *uint32
Array uint32Array
Event []SQEntry
}
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 {
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)
}
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
type CQRing struct {
head uintptr
tail uintptr
ringMask uintptr
ringEntries uintptr
cqes cqeArray
}
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
Head *uint32
Tail *uint32
RingMask *uint32
RingEntries *uint32
Event []CQEntry
}