mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: make ReadMemStats STW for < 25µs
Currently ReadMemStats stops the world for ~1.7 ms/GB of heap because it collects statistics from every single span. For large heaps, this can be quite costly. This is particularly unfortunate because many production infrastructures call this function regularly to collect and report statistics. Fix this by tracking the necessary cumulative statistics in the mcaches. ReadMemStats still has to stop the world to stabilize these statistics, but there are only O(GOMAXPROCS) mcaches to collect statistics from, so this pause is only 25µs even at GOMAXPROCS=100. Fixes #13613. Change-Id: I3c0a4e14833f4760dab675efc1916e73b4c0032a Reviewed-on: https://go-review.googlesource.com/34937 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
parent
3399fd254d
commit
4a7cf960c3
5 changed files with 158 additions and 26 deletions
|
|
@ -82,9 +82,11 @@ type mheap struct {
|
|||
// compiler can't 8-byte align fields.
|
||||
|
||||
// Malloc stats.
|
||||
largefree uint64 // bytes freed for large objects (>maxsmallsize)
|
||||
nlargefree uint64 // number of frees for large objects (>maxsmallsize)
|
||||
nsmallfree [_NumSizeClasses]uint64 // number of frees for small objects (<=maxsmallsize)
|
||||
largealloc uint64 // bytes allocated for large objects
|
||||
nlargealloc uint64 // number of large object allocations
|
||||
largefree uint64 // bytes freed for large objects (>maxsmallsize)
|
||||
nlargefree uint64 // number of frees for large objects (>maxsmallsize)
|
||||
nsmallfree [_NumSizeClasses]uint64 // number of frees for small objects (<=maxsmallsize)
|
||||
|
||||
// range of addresses we might see in the heap
|
||||
bitmap uintptr // Points to one byte past the end of the bitmap
|
||||
|
|
@ -236,7 +238,7 @@ type mspan struct {
|
|||
sweepgen uint32
|
||||
divMul uint16 // for divide by elemsize - divMagic.mul
|
||||
baseMask uint16 // if non-0, elemsize is a power of 2, & this will get object allocation base
|
||||
allocCount uint16 // capacity - number of objects in freelist
|
||||
allocCount uint16 // number of allocated objects
|
||||
sizeclass uint8 // size class
|
||||
incache bool // being used by an mcache
|
||||
state mSpanState // mspaninuse etc
|
||||
|
|
@ -587,6 +589,8 @@ func (h *mheap) alloc_m(npage uintptr, sizeclass int32, large bool) *mspan {
|
|||
h.pagesInUse += uint64(npage)
|
||||
if large {
|
||||
memstats.heap_objects++
|
||||
mheap_.largealloc += uint64(s.elemsize)
|
||||
mheap_.nlargealloc++
|
||||
atomic.Xadd64(&memstats.heap_live, int64(npage<<_PageShift))
|
||||
// Swept spans are at the end of lists.
|
||||
if s.npages < uintptr(len(h.busy)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue