Line data Source code
1 : // Copyright 2024 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 : package manual 6 : 7 : import ( 8 : "fmt" 9 : "sync/atomic" 10 : 11 : "github.com/cockroachdb/pebble/internal/invariants" 12 : ) 13 : 14 : // Purpose identifies the use-case for an allocation. 15 : type Purpose uint8 16 : 17 : const ( 18 : _ Purpose = iota 19 : 20 : BlockCacheMap 21 : BlockCacheEntry 22 : BlockCacheData 23 : MemTable 24 : 25 : NumPurposes 26 : ) 27 : 28 : // Metrics contains memory statistics by purpose. 29 : type Metrics [NumPurposes]struct { 30 : // InUseBytes is the total number of bytes currently allocated. This is just 31 : // the sum of the lengths of the allocations and does not include any overhead 32 : // or fragmentation. 33 : InUseBytes uint64 34 : } 35 : 36 : var counters [NumPurposes]struct { 37 : InUseBytes atomic.Int64 38 : // Pad to separate counters into cache lines. This reduces the overhead when 39 : // multiple purposes are used frequently. We assume 64 byte cache line size 40 : // which is the case for ARM64 servers and AMD64. 41 : _ [7]uint64 42 : } 43 : 44 1 : func recordAlloc(purpose Purpose, n int) { 45 1 : counters[purpose].InUseBytes.Add(int64(n)) 46 1 : } 47 : 48 1 : func recordFree(purpose Purpose, n int) { 49 1 : newVal := counters[purpose].InUseBytes.Add(-int64(n)) 50 1 : if invariants.Enabled && newVal < 0 { 51 0 : panic(fmt.Sprintf("negative counter value %d", newVal)) 52 : } 53 : } 54 : 55 : // GetMetrics returns manual memory usage statistics. 56 1 : func GetMetrics() Metrics { 57 1 : var res Metrics 58 1 : for i := range res { 59 1 : // We load the freed count first to avoid a negative value, since we don't load both counters atomically. 60 1 : res[i].InUseBytes = uint64(counters[i].InUseBytes.Load()) 61 1 : } 62 1 : return res 63 : }