github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/cache/value_normal.go (about) 1 // Copyright 2020 The LevelDB-Go and Pebble Authors. All rights reserved. Use 2 // of this source code is governed by a BSD-style license that can be found in 3 // the LICENSE file. 4 5 //go:build (!invariants && !tracing) || race 6 // +build !invariants,!tracing race 7 8 package cache 9 10 import ( 11 "unsafe" 12 13 "github.com/cockroachdb/pebble/internal/manual" 14 ) 15 16 const valueSize = int(unsafe.Sizeof(Value{})) 17 18 func newValue(n int) *Value { 19 if n == 0 { 20 return nil 21 } 22 23 if !cgoEnabled { 24 // If Cgo is disabled then all memory is allocated from the Go heap and we 25 // can't play the trick below to combine the Value and buffer allocation. 26 v := &Value{buf: make([]byte, n)} 27 v.ref.init(1) 28 return v 29 } 30 31 // When we're not performing leak detection, the lifetime of the returned 32 // Value is exactly the lifetime of the backing buffer and we can manually 33 // allocate both. 34 // 35 // TODO(peter): It may be better to separate the allocation of the value and 36 // the buffer in order to reduce internal fragmentation in malloc. If the 37 // buffer is right at a power of 2, adding valueSize might push the 38 // allocation over into the next larger size. 39 b := manual.New(valueSize + n) 40 v := (*Value)(unsafe.Pointer(&b[0])) 41 v.buf = b[valueSize:] 42 v.ref.init(1) 43 return v 44 } 45 46 func (v *Value) free() { 47 if !cgoEnabled { 48 return 49 } 50 51 // When we're not performing leak detection, the Value and buffer were 52 // allocated contiguously. 53 n := valueSize + cap(v.buf) 54 buf := (*[manual.MaxArrayLen]byte)(unsafe.Pointer(v))[:n:n] 55 v.buf = nil 56 manual.Free(buf) 57 }