diff options
author | Michael Anthony Knyszek <mknyszek@google.com> | 2022-06-09 18:25:01 +0000 |
---|---|---|
committer | Heschi Kreinick <heschi@google.com> | 2022-07-06 18:37:56 +0000 |
commit | b1be664d64750bccd5081d51b585036c931b5cf0 (patch) | |
tree | 7b498af84a47647c6c750b13cad1c17b3ead0521 /src/runtime/mstats.go | |
parent | 77cc1c0defaf4cd6c38221504b29ad125aae9ac7 (diff) | |
download | go-b1be664d64750bccd5081d51b585036c931b5cf0.tar.gz go-b1be664d64750bccd5081d51b585036c931b5cf0.zip |
[release-branch.go1.17] runtime: store consistent total allocation stats as uint64
Currently the consistent total allocation stats are managed as uintptrs,
which means they can easily overflow on 32-bit systems. Fix this by
storing these stats as uint64s. This will cause some minor performance
degradation on 32-bit systems, but there really isn't a way around this,
and it affects the correctness of the metrics we export.
For #52680.
Fixes #52688.
Change-Id: I8b1926116e899ae9f03d58e0320bcb9264945b3e
Reviewed-on: https://go-review.googlesource.com/c/go/+/411496
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/mstats.go')
-rw-r--r-- | src/runtime/mstats.go | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go index eeb2a7b4bc..94c507b45f 100644 --- a/src/runtime/mstats.go +++ b/src/runtime/mstats.go @@ -8,7 +8,6 @@ package runtime import ( "runtime/internal/atomic" - "runtime/internal/sys" "unsafe" ) @@ -565,29 +564,29 @@ func updatememstats() { memstats.heapStats.unsafeRead(&consStats) // Collect large allocation stats. - totalAlloc := uint64(consStats.largeAlloc) - memstats.nmalloc += uint64(consStats.largeAllocCount) - totalFree := uint64(consStats.largeFree) - memstats.nfree += uint64(consStats.largeFreeCount) + totalAlloc := consStats.largeAlloc + memstats.nmalloc += consStats.largeAllocCount + totalFree := consStats.largeFree + memstats.nfree += consStats.largeFreeCount // Collect per-sizeclass stats. for i := 0; i < _NumSizeClasses; i++ { // Malloc stats. - a := uint64(consStats.smallAllocCount[i]) + a := consStats.smallAllocCount[i] totalAlloc += a * uint64(class_to_size[i]) memstats.nmalloc += a memstats.by_size[i].nmalloc = a // Free stats. - f := uint64(consStats.smallFreeCount[i]) + f := consStats.smallFreeCount[i] totalFree += f * uint64(class_to_size[i]) memstats.nfree += f memstats.by_size[i].nfree = f } // Account for tiny allocations. - memstats.nfree += uint64(consStats.tinyAllocCount) - memstats.nmalloc += uint64(consStats.tinyAllocCount) + memstats.nfree += consStats.tinyAllocCount + memstats.nmalloc += consStats.tinyAllocCount // Calculate derived stats. memstats.total_alloc = totalAlloc @@ -703,17 +702,20 @@ type heapStatsDelta struct { inPtrScalarBits int64 // byte delta of memory reserved for unrolled GC prog bits // Allocator stats. - tinyAllocCount uintptr // number of tiny allocations - largeAlloc uintptr // bytes allocated for large objects - largeAllocCount uintptr // number of large object allocations - smallAllocCount [_NumSizeClasses]uintptr // number of allocs for small objects - largeFree uintptr // bytes freed for large objects (>maxSmallSize) - largeFreeCount uintptr // number of frees for large objects (>maxSmallSize) - smallFreeCount [_NumSizeClasses]uintptr // number of frees for small objects (<=maxSmallSize) - - // Add a uint32 to ensure this struct is a multiple of 8 bytes in size. - // Only necessary on 32-bit platforms. - _ [(sys.PtrSize / 4) % 2]uint32 + // + // These are all uint64 because they're cumulative, and could quickly wrap + // around otherwise. + tinyAllocCount uint64 // number of tiny allocations + largeAlloc uint64 // bytes allocated for large objects + largeAllocCount uint64 // number of large object allocations + smallAllocCount [_NumSizeClasses]uint64 // number of allocs for small objects + largeFree uint64 // bytes freed for large objects (>maxSmallSize) + largeFreeCount uint64 // number of frees for large objects (>maxSmallSize) + smallFreeCount [_NumSizeClasses]uint64 // number of frees for small objects (<=maxSmallSize) + + // NOTE: This struct must be a multiple of 8 bytes in size because it + // is stored in an array. If it's not, atomic accesses to the above + // fields may be unaligned and fail on 32-bit platforms. } // merge adds in the deltas from b into a. |