diff options
Diffstat (limited to 'src/runtime/stack.go')
| -rw-r--r-- | src/runtime/stack.go | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/runtime/stack.go b/src/runtime/stack.go index 3a22dcd552..2a7f0bd1c3 100644 --- a/src/runtime/stack.go +++ b/src/runtime/stack.go @@ -1436,3 +1436,49 @@ func (r *stackObjectRecord) gcdata() *byte { func morestackc() { throw("attempt to execute system stack code on user stack") } + +// startingStackSize is the amount of stack that new goroutines start with. +// It is a power of 2, and between _FixedStack and maxstacksize, inclusive. +// startingStackSize is updated every GC by tracking the average size of +// stacks scanned during the GC. +var startingStackSize uint32 = _FixedStack + +func gcComputeStartingStackSize() { + if debug.adaptivestackstart == 0 { + return + } + // For details, see the design doc at + // https://docs.google.com/document/d/1YDlGIdVTPnmUiTAavlZxBI1d9pwGQgZT7IKFKlIXohQ/edit?usp=sharing + // The basic algorithm is to track the average size of stacks + // and start goroutines with stack equal to that average size. + // Starting at the average size uses at most 2x the space that + // an ideal algorithm would have used. + // This is just a heuristic to avoid excessive stack growth work + // early in a goroutine's lifetime. See issue 18138. Stacks that + // are allocated too small can still grow, and stacks allocated + // too large can still shrink. + var scannedStackSize uint64 + var scannedStacks uint64 + for _, p := range allp { + scannedStackSize += p.scannedStackSize + scannedStacks += p.scannedStacks + // Reset for next time + p.scannedStackSize = 0 + p.scannedStacks = 0 + } + if scannedStacks == 0 { + startingStackSize = _FixedStack + return + } + avg := scannedStackSize/scannedStacks + _StackGuard + // Note: we add _StackGuard to ensure that a goroutine that + // uses the average space will not trigger a growth. + if avg > uint64(maxstacksize) { + avg = uint64(maxstacksize) + } + if avg < _FixedStack { + avg = _FixedStack + } + // Note: maxstacksize fits in 30 bits, so avg also does. + startingStackSize = uint32(round2(int32(avg))) +} |
