The documentation related to stack memory in MemStats says:
// StackInuse is bytes in stack spans.
// In-use stack spans have at least one stack in them. These
// spans can only be used for other stacks of the same size.
// There is no StackIdle because unused stack spans are
// returned to the heap (and hence counted toward HeapIdle).
// StackSys is bytes of stack memory obtained from the OS.
// StackSys is StackInuse, plus any memory obtained directly
// from the OS for OS thread stacks (which should be minimal).
And, in runtime/metrics, there is also:
Memory allocated from the heap that is reserved for stack
space, whether or not it is currently in-use.
Stack memory allocated by the underlying operating system.
But this is at best confusing and at worst incorrect. Quoting @mknyszek from a recent conversation:
if a program is pure Go, we use newosproc0 to allocate the first stack. this accounts to stacks_sys, which funnels into StackSys. all other system stacks are allocated from the same pool as goroutine stacks (basically, StackInuse). 8192 bytes.
if a program is cgo, then we use _cgo_sys_thread_create for the first thread which is the platform C library thread creation. we use this for every new stack, too. we don't control the size of those stacks at all, and we also don't account for them AFAICT. this is how we ensure that calls into C are fine: all system stacks are basically provided by pthreads.
The behaviour is different between pure Go and cgo programs, which should be mentioned.
Even for pure Go programs, stacks for syscalls are generally allocated from stack_inuse (in cgo programs this is not tracked at all).
This different behaviour should be called out in the docs.
The text was updated successfully, but these errors were encountered: