github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/bytealloc/bytealloc.go (about) 1 // Copyright 2016 The Cockroach Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 // implied. See the License for the specific language governing 13 // permissions and limitations under the License. 14 15 package bytealloc 16 17 import "github.com/cockroachdb/pebble/internal/rawalloc" 18 19 // An A provides chunk allocation of []byte, amortizing the overhead of each 20 // allocation. Because the underlying storage for the slices is shared, they 21 // should share a similar lifetime in order to avoid pinning large amounts of 22 // memory unnecessarily. The allocator itself is a []byte where cap() indicates 23 // the total amount of memory and len() is the amount already allocated. The 24 // size of the buffer to allocate from is grown exponentially when it runs out 25 // of room up to a maximum size (chunkAllocMaxSize). 26 type A []byte 27 28 const chunkAllocMinSize = 512 29 const chunkAllocMaxSize = 512 << 10 // 512 KB 30 31 func (a A) reserve(n int) A { 32 allocSize := cap(a) * 2 33 if allocSize < chunkAllocMinSize { 34 allocSize = chunkAllocMinSize 35 } else if allocSize > chunkAllocMaxSize { 36 allocSize = chunkAllocMaxSize 37 } 38 if allocSize < n { 39 allocSize = n 40 } 41 return rawalloc.New(0, allocSize) 42 } 43 44 // Alloc allocates a new chunk of memory with the specified length. 45 func (a A) Alloc(n int) (A, []byte) { 46 if cap(a)-len(a) < n { 47 a = a.reserve(n) 48 } 49 p := len(a) 50 r := a[p : p+n : p+n] 51 a = a[:p+n] 52 return a, r 53 } 54 55 // Copy allocates a new chunk of memory, initializing it from src. 56 func (a A) Copy(src []byte) (A, []byte) { 57 var alloc []byte 58 a, alloc = a.Alloc(len(src)) 59 copy(alloc, src) 60 return a, alloc 61 } 62 63 // Reset returns the current chunk, resetting allocated memory back to none. 64 // Future allocations will use memory previously allocated by previous calls to 65 // Alloc or Copy, so the caller must know know that none of the previously 66 // allocated byte slices are still in use. 67 func (a A) Reset() A { 68 return a[:0] 69 }