DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

Goroutine Stack Size Evolve

原文链接

Go provides a light and smart goroutines management. Light because the goroutine stack starts at 2Kb only, and smart since goroutines can grow / shrink automatically according to our needs.

Regarding the size of the stack, we can find it in runtime/stack.go :

1
2
// The minimum size of stack used by Go code
_StackMin = 2048
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func main() {
a := 1
b := 2

r := max(a, b)
println(`max: `+strconv.Itoa(r))
}

func max(a int, b int) int {
if a >= b {
return a
}

return b
}
1
2
3
4
5
6
7
8
go build -gcflags -S main.go

"".main STEXT size=186 args=0x0 locals=0x70
0x0000 00000 (/go/src/main.go:5) TEXT "".main(SB), ABIInternal, $112-0
[...]
0x00b0 00176 (/go/src/main.go:5) CALL runtime.morestack_noctxt(SB)
[...]
0x0000 00000 (/go/src/main.go:13) TEXT "".max(SB), NOSPLIT|ABIInternal, $0-24

There are two instructions that involves the stack changes:

  • CALL runtime.morestack_noctxt: this method will increase the size of the stack if it needs more.
  • NOSPLIT: this instruction means that the stack overflow check is not needed. It is similar to the compiler directive //go:nosplit.
1
2
3
4
5
6
7
8
runtime: newstack sp=0xc00002e6d8 stack=[0xc00002e000, 0xc00002e800]
copystack gp=0xc000000300 [0xc00002e000 0xc00002e6e0 0xc00002e800] -> [0xc000076000 0xc000076ee0 0xc000077000]/4096
stackfree 0xc00002e000 2048
stack grow done
runtime: newstack sp=0xc000076888 stack=[0xc000076000, 0xc000077000]
copystack gp=0xc000000300 [0xc000076000 0xc000076890 0xc000077000] -> [0xc00003e000 0xc00003f890 0xc000040000]/8192
stackfree 0xc000076000 4096
stack grow done

The strategy to copy the stack into a bigger space is called contiguous stack as opposed to segmented stack

类似于普通操作系统的segment stacks管理?

rust部分,不采用这种方式,

  • stack thrashing的问题,需要事先分配
  • FFI,外部code往往都需要large stacks
  • LLVM libc optimizations and intrinsic fallbacks

Instead of segmented stacks we’re going to rely on the OS and MMU to help us map pages lazily