From 5937800f05317d18f14de94dc8163c54dc516410 Mon Sep 17 00:00:00 2001 From: MastahSenpai <26342994+ii64@users.noreply.github.com> Date: Wed, 26 Jan 2022 01:20:07 +0700 Subject: [PATCH] fix(perf): direct field access Signed-off-by: MastahSenpai <26342994+ii64@users.noreply.github.com> --- core.go | 8 ++--- core_test.go | 21 +++++------ mem_util.go | 46 ++++++++++++++++-------- ring.go | 100 ++++++++------------------------------------------- 4 files changed, 60 insertions(+), 115 deletions(-) diff --git a/core.go b/core.go index 6735081..924aaed 100644 --- a/core.go +++ b/core.go @@ -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 } diff --git a/core_test.go b/core_test.go index 8205090..43fe1a6 100644 --- a/core_test.go +++ b/core_test.go @@ -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) } diff --git a/mem_util.go b/mem_util.go index 1ca0a28..0459cb5 100644 --- a/mem_util.go +++ b/mem_util.go @@ -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 } diff --git a/ring.go b/ring.go index 4ad7e3b..e9b0f03 100644 --- a/ring.go +++ b/ring.go @@ -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 }