Commit c136f72a authored by Steven Allen's avatar Steven Allen

pool pointers to pointers

So, creating interfaces *allocates*. That means `pool.Put([]byte)` allocates,
that's obviously bad. This was, unfortunately, showing up in go-ipfs after
switching to a pool-backed yamux.

What's the solution to too many allocations? More object pools!
parent 8adc4b47
......@@ -41,6 +41,11 @@ const MaxLength = math.MaxInt32
// You MUST NOT copy Pool after using.
type BufferPool struct {
pools [32]sync.Pool // a list of singlePools
ptrs sync.Pool
}
type bufp struct {
buf []byte
}
// Get retrieves a buffer of the appropriate length from the buffer pool or
......@@ -57,8 +62,12 @@ func (p *BufferPool) Get(length int) []byte {
return make([]byte, length)
}
idx := nextLogBase2(uint32(length))
if buf := p.pools[idx].Get(); buf != nil {
return buf.([]byte)[:uint32(length)]
if ptr := p.pools[idx].Get(); ptr != nil {
bp := ptr.(*bufp)
buf := bp.buf[:uint32(length)]
bp.buf = nil
p.ptrs.Put(ptr)
return buf
}
return make([]byte, 1<<idx)[:uint32(length)]
}
......@@ -70,7 +79,14 @@ func (p *BufferPool) Put(buf []byte) {
return // drop it
}
idx := prevLogBase2(uint32(capacity))
p.pools[idx].Put(buf)
var bp *bufp
if ptr := p.ptrs.Get(); ptr != nil {
bp = ptr.(*bufp)
} else {
bp = new(bufp)
}
bp.buf = buf
p.pools[idx].Put(bp)
}
// Get retrieves a buffer of the appropriate length from the global buffer pool
......
......@@ -16,6 +16,22 @@ import (
"testing"
)
func TestAllocations(t *testing.T) {
var m1, m2 runtime.MemStats
runtime.ReadMemStats(&m1)
runtime.GC()
for i := 0; i < 10000; i++ {
b := Get(1010)
Put(b)
}
runtime.GC()
runtime.ReadMemStats(&m2)
frees := m2.Frees - m1.Frees
if frees > 100 {
t.Fatalf("expected less than 100 frees after GC, got %d", frees)
}
}
func TestPool(t *testing.T) {
// disable GC so we can control when it happens.
defer debug.SetGCPercent(debug.SetGCPercent(-1))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment