Line data Source code
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 1 : func (a A) reserve(n int) A { 32 1 : allocSize := cap(a) * 2 33 1 : if allocSize < chunkAllocMinSize { 34 1 : allocSize = chunkAllocMinSize 35 1 : } else if allocSize > chunkAllocMaxSize { 36 0 : allocSize = chunkAllocMaxSize 37 0 : } 38 1 : if allocSize < n { 39 0 : allocSize = n 40 0 : } 41 1 : return rawalloc.New(0, allocSize) 42 : } 43 : 44 : // Alloc allocates a new chunk of memory with the specified length. 45 1 : func (a A) Alloc(n int) (A, []byte) { 46 1 : if cap(a)-len(a) < n { 47 1 : a = a.reserve(n) 48 1 : } 49 1 : p := len(a) 50 1 : r := a[p : p+n : p+n] 51 1 : a = a[:p+n] 52 1 : return a, r 53 : } 54 : 55 : // Copy allocates a new chunk of memory, initializing it from src. 56 1 : func (a A) Copy(src []byte) (A, []byte) { 57 1 : var alloc []byte 58 1 : a, alloc = a.Alloc(len(src)) 59 1 : copy(alloc, src) 60 1 : return a, alloc 61 1 : } 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 1 : func (a A) Reset() A { 68 1 : return a[:0] 69 1 : }