aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mcentral.go
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2017-01-03 10:15:55 -0700
committerAustin Clements <austin@google.com>2017-03-04 02:56:37 +0000
commit4a7cf960c38d72e9f0c6f00e46e013be2a35d56e (patch)
tree1e47293cf8e12313d8ea713ed7b35ee8b157a787 /src/runtime/mcentral.go
parent3399fd254dcdf4e8a9be8c327076de5f9efe1b3a (diff)
downloadgo-4a7cf960c38d72e9f0c6f00e46e013be2a35d56e.tar.xz
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>
Diffstat (limited to 'src/runtime/mcentral.go')
-rw-r--r--src/runtime/mcentral.go12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/runtime/mcentral.go b/src/runtime/mcentral.go
index ddcf81ebb1..be3820a9a5 100644
--- a/src/runtime/mcentral.go
+++ b/src/runtime/mcentral.go
@@ -22,6 +22,11 @@ type mcentral struct {
sizeclass int32
nonempty mSpanList // list of spans with a free object, ie a nonempty free list
empty mSpanList // list of spans with no free objects (or cached in an mcache)
+
+ // nmalloc is the cumulative count of objects allocated from
+ // this mcentral, assuming all spans in mcaches are
+ // fully-allocated. Written atomically, read under STW.
+ nmalloc uint64
}
// Initialize a single central free list.
@@ -106,6 +111,9 @@ havespan:
if n == 0 || s.freeindex == s.nelems || uintptr(s.allocCount) == s.nelems {
throw("span has no free objects")
}
+ // Assume all objects from this span will be allocated in the
+ // mcache. If it gets uncached, we'll adjust this.
+ atomic.Xadd64(&c.nmalloc, int64(n))
usedBytes := uintptr(s.allocCount) * s.elemsize
if usedBytes > 0 {
reimburseSweepCredit(usedBytes)
@@ -150,6 +158,10 @@ func (c *mcentral) uncacheSpan(s *mspan) {
// mCentral_CacheSpan conservatively counted
// unallocated slots in heap_live. Undo this.
atomic.Xadd64(&memstats.heap_live, -int64(n)*int64(s.elemsize))
+ // cacheSpan updated alloc assuming all objects on s
+ // were going to be allocated. Adjust for any that
+ // weren't.
+ atomic.Xadd64(&c.nmalloc, -int64(n))
}
unlock(&c.lock)
}