aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/stack.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/stack.go')
-rw-r--r--src/runtime/stack.go46
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)))
+}