1
0
mirror of https://github.com/golang/go synced 2024-11-18 15:14:44 -07:00

runtime: make gcDrainN in terms of scan work

Currently, the "n" in gcDrainN is in terms of objects to scan. This is
used by gchelpwork to perform a limited amount of work on allocation,
but is a pretty arbitrary way to bound this amount of work since the
number of objects has little relation to how long they take to scan.

Modify gcDrainN to perform a fixed amount of scan work instead. For
now, gchelpwork still performs a fairly arbitrary amount of scan work,
but at least this is much more closely related to how long the work
will take. Shortly, we'll use this to precisely control the scan work
performed by mutator assists during allocation to achieve the heap
size goal.

Change-Id: I3cd07fe0516304298a0af188d0ccdf621d4651cc
Reviewed-on: https://go-review.googlesource.com/8835
Reviewed-by: Rick Hudson <rlh@golang.org>
This commit is contained in:
Austin Clements 2015-03-13 14:01:16 -04:00
parent 8e24283a28
commit 028f972847

View File

@ -190,8 +190,8 @@ func gchelpwork() {
// be more cache friendly. // be more cache friendly.
var gcw gcWork var gcw gcWork
gcw.initFromCache() gcw.initFromCache()
const n = len(workbuf{}.obj) const helpScanWork = 500 // pointers to trace
gcDrainN(&gcw, n) // drain upto one buffer's worth of objects gcDrainN(&gcw, helpScanWork)
// TODO(austin): This is the vast majority of our // TODO(austin): This is the vast majority of our
// disposes. Instead of constantly disposing, keep a // disposes. Instead of constantly disposing, keep a
// per-P gcWork cache (probably combined with the // per-P gcWork cache (probably combined with the
@ -407,11 +407,16 @@ func gcDrain(gcw *gcWork, flushScanCredit int64) {
checknocurrentwbuf() checknocurrentwbuf()
} }
// gcDrainN scans n objects, blackening grey objects. // gcDrainN blackens grey objects until it has performed roughly
// scanWork units of scan work. This is best-effort, so it may perform
// less work if it fails to get a work buffer. Otherwise, it will
// perform at least n units of work, but may perform more because
// scanning is always done in whole object increments.
//go:nowritebarrier //go:nowritebarrier
func gcDrainN(gcw *gcWork, n int) { func gcDrainN(gcw *gcWork, scanWork int64) {
checknocurrentwbuf() checknocurrentwbuf()
for i := 0; i < n; i++ { targetScanWork := gcw.scanWork + scanWork
for gcw.scanWork < targetScanWork {
// This might be a good place to add prefetch code... // This might be a good place to add prefetch code...
// if(wbuf.nobj > 4) { // if(wbuf.nobj > 4) {
// PREFETCH(wbuf->obj[wbuf.nobj - 3]; // PREFETCH(wbuf->obj[wbuf.nobj - 3];