Skip to content

Commit 6e11586

Browse files
elliotnunnRaduBerinde
authored andcommitted
manual: use sync.Pool to help the GC when CGo is off
1 parent 4bce934 commit 6e11586

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

internal/manual/manual_nocgo.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
package manual
88

99
import (
10+
"math/bits"
11+
"sync"
1012
"unsafe"
1113

1214
"github.com/cockroachdb/pebble/internal/invariants"
@@ -21,9 +23,8 @@ func New(purpose Purpose, n uintptr) Buf {
2123
return Buf{}
2224
}
2325
recordAlloc(purpose, n)
24-
slice := make([]byte, n)
2526
return Buf{
26-
data: unsafe.Pointer(unsafe.SliceData(slice)),
27+
data: pools[sizeClass(n)].Get().(unsafe.Pointer),
2728
n: n,
2829
}
2930
}
@@ -32,5 +33,33 @@ func New(purpose Purpose, n uintptr) Buf {
3233
// returned by New.
3334
func Free(purpose Purpose, b Buf) {
3435
invariants.MaybeMangle(b.Slice())
36+
if b.data == nil {
37+
return
38+
}
39+
40+
// Clear the block for consistency with the cgo implementation (which uses calloc)
41+
clear(unsafe.Slice((*byte)(b.data), b.n))
42+
3543
recordFree(purpose, b.n)
44+
pools[sizeClass(b.n)].Put(b.data)
45+
}
46+
47+
var pools [bits.UintSize]sync.Pool // pools[n] is for allocs of size 1 << n
48+
49+
func init() {
50+
for i := range pools {
51+
allocSize := 1 << i
52+
pools[i].New = func() any {
53+
// Boxing an unsafe.Pointer into an interface does not require an allocation
54+
return unsafe.Pointer(unsafe.SliceData(make([]byte, allocSize)))
55+
}
56+
}
57+
}
58+
59+
// sizeClass determines the smallest n such that 1 << n >= size
60+
func sizeClass(size uintptr) int {
61+
if invariants.Enabled && size == 0 {
62+
panic("zero size should never get through New")
63+
}
64+
return bits.Len(uint(size - 1))
3665
}

0 commit comments

Comments
 (0)