This is a creation in Article, where the information may have evolved or changed.
original articles, reproduced please specify the Source: Server non-amateur research http://blog.csdn.net/erlib author Sunface
Objective
In the previous Go1.3 changes mentioned that the implementation of the stack from the segmented implementation (segment stack) into a continuous stack implementation (contiguous STATCK), this change is not very small, it will give us any impact? Please see below
Continuous stack
Each goroutine is allocated a piece of memory as a continuous stack, which is increased by redistribution/replication.
why a continuous stack is required
There is a big problem with the current stack splitting technique: "Hot split"--if the stack is almost full, an additional call will force the allocation of a new stack (stack chunk), and when the call returns, the newly allocated stack will be released for recycling, in which case If the same call executes continuously, excessive alloc/free can result in a significant decrease in system performance.
With stack splitting, the allocation and release of stacks will never be completed--each time the stack reaches a critical value, additional work is required.
However, these problems can be avoided when using continuous stack technology. The stack size will grow to the desired size, that's all, no extra action (except memory shrinkage shrinking, see below)
How do we do that?
How do you move a stack? Our compiler's escape analysis provides an important invariant: a pointer to a piece of data in the stack can only be passed in the call tree in order, with any other form of escape (written into the global variable, returned to the parent call, written to the heap) Will prevent the data from being allocated on that stack. This invariant means that when there is a pointer pointing to this piece of data in the stack, the pointer is present in the stack (and there are exceptions, see below), so that it is easy to find and update when the stack needs to be copied.
Overflow detection
Stack overflow detection is very similar to the stack segment overflow detection, the main difference is that we no longer need to know the size of the parameter, because it is no longer necessary to copy the parameters to the new stack segment.
Even we do not need to know the size of the stack frame, just to enlarge the stack size to twice times before, and then try on the line, if the stack size is still not enough to meet our overflow detection needs to size, then expand to twice times, so repeat until the stack size is enough.
CopyWhen a stack overflow is detected: First allocate a new stack that is larger than the previous stack, the stack size should grow exponentially (2^n), or it may grow in multiples of a certain size (so memory allocation is more efficient), the current plan: each allocation is Press 2^n to grow. The old stack is then copied to the new stack, because the stack is an array of *byte, so each *byte is copied from the old stack to the new stack.
We need to be careful when copying the integers that look like pointers, so we need a data structure to tell us: is the integer with each pointer size on the stack a pointer or a different data type? Fortunately, This data structure already has, so that we can make our GC more accurate. any pointer that enters the stack from outside (outside the callee) needs to be adjusted, although there are some slip-through analysis, including: the Function object in the defer call parameters in the defer call
- Closure parameters for function objects in the defer call (closure)
- A function object that has been passed to the overflow stack
- Closure parameters for function objects that have been passed to the overflow stack