77package manual
88
99import (
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.
3334func 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