Commit 2098e5d3 authored by Austin Clements's avatar Austin Clements

runtime: eliminate memstats.heap_reachable

We used to compute an estimate of the reachable heap size that was
different from the marked heap size. This ultimately caused more
problems than it solved, so we pulled it out, but memstats still has
both heap_reachable and heap_marked, and there are some leftover TODOs
about the problems with this estimate.

Clean this up by eliminating heap_reachable in favor of heap_marked
and deleting the stale TODOs.

Change-Id: I713bc20a7c90683d2b43ff63c0b21a440269cc4d
Reviewed-on: https://go-review.googlesource.com/29271
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRick Hudson <rlh@golang.org>
parent ec9c84c8
...@@ -429,12 +429,11 @@ func (c *gcControllerState) startCycle() { ...@@ -429,12 +429,11 @@ func (c *gcControllerState) startCycle() {
// error response). // error response).
if memstats.gc_trigger <= heapminimum { if memstats.gc_trigger <= heapminimum {
memstats.heap_marked = uint64(float64(memstats.gc_trigger) / (1 + c.triggerRatio)) memstats.heap_marked = uint64(float64(memstats.gc_trigger) / (1 + c.triggerRatio))
memstats.heap_reachable = memstats.heap_marked
} }
// Re-compute the heap goal for this cycle in case something // Re-compute the heap goal for this cycle in case something
// changed. This is the same calculation we use elsewhere. // changed. This is the same calculation we use elsewhere.
memstats.next_gc = memstats.heap_reachable + memstats.heap_reachable*uint64(gcpercent)/100 memstats.next_gc = memstats.heap_marked + memstats.heap_marked*uint64(gcpercent)/100
// Ensure that the heap goal is at least a little larger than // Ensure that the heap goal is at least a little larger than
// the current live heap size. This may not be the case if GC // the current live heap size. This may not be the case if GC
...@@ -558,10 +557,6 @@ func (c *gcControllerState) endCycle() { ...@@ -558,10 +557,6 @@ func (c *gcControllerState) endCycle() {
// growth if we had the desired CPU utilization). The // growth if we had the desired CPU utilization). The
// difference between this estimate and the GOGC-based goal // difference between this estimate and the GOGC-based goal
// heap growth is the error. // heap growth is the error.
//
// TODO(austin): gc_trigger is based on heap_reachable, not
// heap_marked, which means the actual growth ratio
// technically isn't comparable to the trigger ratio.
goalGrowthRatio := float64(gcpercent) / 100 goalGrowthRatio := float64(gcpercent) / 100
actualGrowthRatio := float64(memstats.heap_live)/float64(memstats.heap_marked) - 1 actualGrowthRatio := float64(memstats.heap_live)/float64(memstats.heap_marked) - 1
assistDuration := nanotime() - c.markStartTime assistDuration := nanotime() - c.markStartTime
...@@ -1624,14 +1619,14 @@ func gcMark(start_time int64) { ...@@ -1624,14 +1619,14 @@ func gcMark(start_time int64) {
cachestats() cachestats()
// Update the reachable heap stat. // Update the marked heap stat.
memstats.heap_reachable = work.bytesMarked memstats.heap_marked = work.bytesMarked
// Trigger the next GC cycle when the allocated heap has grown // Trigger the next GC cycle when the allocated heap has grown
// by triggerRatio over the reachable heap size. Assume that // by triggerRatio over the marked heap size. Assume that
// we're in steady state, so the reachable heap size is the // we're in steady state, so the marked heap size is the
// same now as it was at the beginning of the GC cycle. // same now as it was at the beginning of the GC cycle.
memstats.gc_trigger = uint64(float64(memstats.heap_reachable) * (1 + gcController.triggerRatio)) memstats.gc_trigger = uint64(float64(memstats.heap_marked) * (1 + gcController.triggerRatio))
if memstats.gc_trigger < heapminimum { if memstats.gc_trigger < heapminimum {
memstats.gc_trigger = heapminimum memstats.gc_trigger = heapminimum
} }
...@@ -1644,15 +1639,13 @@ func gcMark(start_time int64) { ...@@ -1644,15 +1639,13 @@ func gcMark(start_time int64) {
// cachestats (which flushes local statistics to these) and // cachestats (which flushes local statistics to these) and
// flushallmcaches (which modifies heap_live). // flushallmcaches (which modifies heap_live).
memstats.heap_live = work.bytesMarked memstats.heap_live = work.bytesMarked
memstats.heap_marked = work.bytesMarked
memstats.heap_scan = uint64(gcController.scanWork) memstats.heap_scan = uint64(gcController.scanWork)
minTrigger := memstats.heap_live + sweepMinHeapDistance*uint64(gcpercent)/100 minTrigger := memstats.heap_live + sweepMinHeapDistance*uint64(gcpercent)/100
if memstats.gc_trigger < minTrigger { if memstats.gc_trigger < minTrigger {
// The allocated heap is already past the trigger. // The allocated heap is already past the trigger.
// This can happen if the triggerRatio is very low and // This can happen if the triggerRatio is very low and
// the reachable heap estimate is less than the live // the marked heap is less than the live heap size.
// heap size.
// //
// Concurrent sweep happens in the heap growth from // Concurrent sweep happens in the heap growth from
// heap_live to gc_trigger, so bump gc_trigger up to ensure // heap_live to gc_trigger, so bump gc_trigger up to ensure
...@@ -1664,7 +1657,7 @@ func gcMark(start_time int64) { ...@@ -1664,7 +1657,7 @@ func gcMark(start_time int64) {
// The next GC cycle should finish before the allocated heap // The next GC cycle should finish before the allocated heap
// has grown by GOGC/100. // has grown by GOGC/100.
memstats.next_gc = memstats.heap_reachable + memstats.heap_reachable*uint64(gcpercent)/100 memstats.next_gc = memstats.heap_marked + memstats.heap_marked*uint64(gcpercent)/100
if memstats.next_gc < memstats.gc_trigger { if memstats.next_gc < memstats.gc_trigger {
memstats.next_gc = memstats.gc_trigger memstats.next_gc = memstats.gc_trigger
} }
......
...@@ -111,10 +111,6 @@ type mstats struct { ...@@ -111,10 +111,6 @@ type mstats struct {
// unlike heap_live, heap_marked does not change until the // unlike heap_live, heap_marked does not change until the
// next mark termination. // next mark termination.
heap_marked uint64 heap_marked uint64
// heap_reachable is an estimate of the reachable heap bytes
// at the end of the previous GC.
heap_reachable uint64
} }
var memstats mstats var memstats mstats
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment