1
0
mirror of https://github.com/fumiama/orbyte.git synced 2026-06-28 07:50:32 +08:00

optimize: change Destroy -> ManualDestroy

This commit is contained in:
源文雨
2025-02-25 19:35:43 +09:00
parent 343a5d57be
commit 4a462a1437
6 changed files with 41 additions and 25 deletions

View File

@@ -104,8 +104,11 @@ func (b *Item[T]) destroybystat(stat status) {
b.pool.put(b) b.pool.put(b)
} }
// Destroy item and put it back to pool. // ManualDestroy item and put it back to pool.
func (b *Item[T]) Destroy() { //
// Calling this method without setting pool.SetManualDestroy(true)
// can probably cause panic.
func (b *Item[T]) ManualDestroy() {
b.destroybystat(status(atomic.SwapUintptr( b.destroybystat(status(atomic.SwapUintptr(
(*uintptr)(&b.stat), uintptr(destroyedstatus), (*uintptr)(&b.stat), uintptr(destroyedstatus),
))) )))

View File

@@ -42,7 +42,7 @@ func testBuffer(buf *orbyte.Item[bytes.Buffer], t *testing.T) {
if !bytes.Equal(bufr.Pointer().Bytes(), buf.Pointer().Bytes()) { if !bytes.Equal(bufr.Pointer().Bytes(), buf.Pointer().Bytes()) {
t.Fatal("unexpected") t.Fatal("unexpected")
} }
bufr.Destroy() bufr.ManualDestroy()
bufcp = bufcp.Trans() bufcp = bufcp.Trans()
if bufcp.Pointer().Len() != 4096 { if bufcp.Pointer().Len() != 4096 {
@@ -51,7 +51,7 @@ func testBuffer(buf *orbyte.Item[bytes.Buffer], t *testing.T) {
if !bytes.Equal(bufcp.Pointer().Bytes(), buf.Pointer().Bytes()) { if !bytes.Equal(bufcp.Pointer().Bytes(), buf.Pointer().Bytes()) {
t.Fatal("unexpected") t.Fatal("unexpected")
} }
bufcp.Destroy() bufcp.ManualDestroy()
runtime.GC() runtime.GC()
runtime.Gosched() runtime.Gosched()

View File

@@ -117,8 +117,3 @@ func (b Bytes) Slice(from, to int) Bytes {
nb.dat = b.dat[from:to] nb.dat = b.dat[from:to]
return nb return nb
} }
// Destroy please refer to Item.Destroy().
func (b Bytes) Destroy() {
b.buf.Destroy()
}

View File

@@ -11,6 +11,13 @@ import (
"time" "time"
) )
// manualDestroy please refer to Item.manualDestroy().
//
// Only for test purposes.
func (b Bytes) manualDestroy() {
b.buf.ManualDestroy()
}
// TestBytesSlice sometimes fails at first run because // TestBytesSlice sometimes fails at first run because
// GC not collecting all unused items. // GC not collecting all unused items.
func TestBytesSlice(t *testing.T) { func TestBytesSlice(t *testing.T) {
@@ -29,7 +36,7 @@ func TestBytesSlice(t *testing.T) {
t.Log("got:", hex.EncodeToString(x.Bytes())) t.Log("got:", hex.EncodeToString(x.Bytes()))
t.Fatal("index", i, "unexpected") t.Fatal("index", i, "unexpected")
} }
x.Destroy() x.manualDestroy()
// test trans slice // test trans slice
b = b.Trans().SliceFrom(5).SliceTo(i - 5 - 5) b = b.Trans().SliceFrom(5).SliceTo(i - 5 - 5)
if !bytes.Equal(buf[5:i-5], b.Bytes()) { if !bytes.Equal(buf[5:i-5], b.Bytes()) {
@@ -37,7 +44,7 @@ func TestBytesSlice(t *testing.T) {
t.Log("got:", hex.EncodeToString(b.Bytes())) t.Log("got:", hex.EncodeToString(b.Bytes()))
t.Fatal("index", i, "unexpected") t.Fatal("index", i, "unexpected")
} }
b.Destroy() b.manualDestroy()
} }
runtime.GC() runtime.GC()
runtime.Gosched() runtime.Gosched()
@@ -61,7 +68,7 @@ func TestBytesInvolve(t *testing.T) {
if !bytes.Equal(b.Bytes(), buf[:i]) { if !bytes.Equal(b.Bytes(), buf[:i]) {
t.Fatal("index", i, "unexpected") t.Fatal("index", i, "unexpected")
} }
b.Destroy() b.manualDestroy()
} }
runtime.GC() runtime.GC()
out, in := bufferPool.p.CountItems() out, in := bufferPool.p.CountItems()
@@ -82,7 +89,7 @@ func TestBytesParse(t *testing.T) {
if !bytes.Equal(b.Bytes(), buf[:i]) { if !bytes.Equal(b.Bytes(), buf[:i]) {
t.Fatal("index", i, "unexpected") t.Fatal("index", i, "unexpected")
} }
b.Destroy() b.manualDestroy()
} }
runtime.GC() runtime.GC()
out, in := bufferPool.p.CountItems() out, in := bufferPool.p.CountItems()
@@ -106,7 +113,7 @@ func TestBytesCopy(t *testing.T) {
if bytes.Equal(b.Bytes(), buf[:i]) { if bytes.Equal(b.Bytes(), buf[:i]) {
t.Fatal("index", i, "unexpected") t.Fatal("index", i, "unexpected")
} }
b.Destroy() b.manualDestroy()
} }
runtime.GC() runtime.GC()
out, in := bufferPool.p.CountItems() out, in := bufferPool.p.CountItems()
@@ -134,7 +141,7 @@ func TestBytesTransMultithread(t *testing.T) {
if !bytes.Equal(refer, buf.Bytes()) { if !bytes.Equal(refer, buf.Bytes()) {
panic("unexpected") panic("unexpected")
} }
buf.Destroy() buf.manualDestroy()
}(buf.Trans()) }(buf.Trans())
}() }()
} }

25
pool.go
View File

@@ -13,7 +13,8 @@ type Pool[T any] struct {
pool sync.Pool pool sync.Pool
countin int32 countin int32
countout int32 countout int32
isstrict bool noputbak bool
manudstr bool
} }
// NewPool make a new pool from custom pooler. // NewPool make a new pool from custom pooler.
@@ -26,11 +27,17 @@ func NewPool[T any](pooler Pooler[T]) *Pool[T] {
return p return p
} }
// SetStrictMode panic on every misuse. // SetNoPutBack make it panic on every use-after-destroy.
// //
// Enable this to detect coding errors. // Enable this to detect coding errors.
func (pool *Pool[T]) SetStrictMode(on bool) { func (pool *Pool[T]) SetNoPutBack(on bool) {
pool.isstrict = on pool.noputbak = on
}
// SetManualDestroy mark that user must manually
// run Item.Destroy().
func (pool *Pool[T]) SetManualDestroy(on bool) {
pool.manudstr = on
} }
func (pool *Pool[T]) incin() { func (pool *Pool[T]) incin() {
@@ -56,17 +63,21 @@ func (pool *Pool[T]) newempty() *Item[T] {
} }
item.stat = status(0) item.stat = status(0)
pool.incout() pool.incout()
item.setautodestroy() if !pool.manudstr {
item.setautodestroy()
}
return item return item
} }
func (pool *Pool[T]) put(item *Item[T]) { func (pool *Pool[T]) put(item *Item[T]) {
runtime.SetFinalizer(item, nil) if !pool.manudstr {
runtime.SetFinalizer(item, nil)
}
item.stat.setdestroyed(true) item.stat.setdestroyed(true)
item.cfg = nil item.cfg = nil
if pool.isstrict { if pool.noputbak {
return return
} }
pool.pool.Put(item) pool.pool.Put(item)

View File

@@ -10,7 +10,7 @@ import (
func TestPool(t *testing.T) { func TestPool(t *testing.T) {
p := NewPool[[]byte](simplepooler{}) p := NewPool[[]byte](simplepooler{})
x := p.New(200) x := p.New(200)
x.Destroy() x.ManualDestroy()
out, in := p.CountItems() out, in := p.CountItems()
t.Log("out", out, "in", in) t.Log("out", out, "in", in)
if out != 0 || in != 1 { if out != 0 || in != 1 {
@@ -22,7 +22,7 @@ func TestPool(t *testing.T) {
if out != 1 || in != 0 { if out != 1 || in != 0 {
t.Fatal("unexpected behavior") t.Fatal("unexpected behavior")
} }
item.Destroy() item.ManualDestroy()
} }
out, in = p.CountItems() out, in = p.CountItems()
t.Log("out", out, "in", in) t.Log("out", out, "in", in)
@@ -53,7 +53,7 @@ func TestPool(t *testing.T) {
func user(item *Item[[]byte], wg *sync.WaitGroup) { func user(item *Item[[]byte], wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
rand.Read(item.Unwrap()) rand.Read(item.Unwrap())
item.Destroy() item.ManualDestroy()
} }
func usernodestroy(item *Item[[]byte], wg *sync.WaitGroup) { func usernodestroy(item *Item[[]byte], wg *sync.WaitGroup) {