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