3 ms·
tl;dr The stack is grown in chunks. Previously, Go maintained a linked list of chunks, but repeated allocation/deallocation of chunks within loop was bad for pe
by norswap 12y ago
tl;dr The stack is grown in chunks. Previously, Go maintained a linked list of chunks, but repeated allocation/deallocation of chunks within loop was bad for performance. They switched to a "realloc-type" of stack growth (allocate a bigger region and copy the old stack over).
Now my question: why didn't they simply keep a pool of available stack chunks to reuse instead of constantly allocating/freeing them?
- rsc 12y agoThere is (was) a pool. It's not the alloc/free that is the problem. It's all the bookkeeping that is pure overhead compared to a simple CALL or RET instruction.
- norswap 12y agoAm I missing something or is it strange to speak about "a single CALL instruction"? It implies you'll have to execute some function, so it can't be really considered as a single instruction. If there was a pool, then the article is at least misleading on that point because it seems to imply that in loops, you repeatedly allocate and free, which would not be necessary with a pool. But yes, in the end it comes down to see whether pool/linked-list bookkeeping is better or worse to data copy + pointer bookkeeping.
- rsc 12y agoA single CALL instruction on the x86 does a very limited amount: it pushes the address of the next instruction onto the stack, and then it sets the instruction pointer to the thing that was called. What happens next is up to the function and not part of the CALL instruction. Allocate and free are perfectly reasonable terms to describe the use of a pool too.
- bsdetector 12y ago> They switched to a "realloc-type" of stack growth (allocate a bigger region and copy the old stack over). This literally hurts my brain. They are moving pointers in memory for no reason, because they cling to the notion that tightly packed stacks are needed, because they want to support 32-bit processors as first class, because they want to have billions of threads at once. But every step of that thought process is wrong. You don't want to have billions or even millions of threads at once because then your latency is large and scheduling and order of operations are unpredictable and unstable. You don't want to support 32-bit processors as first-class because even new phones are 64-bit nowadays. You don't want tightly packed stacks because it's a complicated waste to move them and grow them and virtual memory does the same job better. I just don't get it, there's just so much wasted time and talent wrapped up in this language. I mean they created an entire toolchain just for something that should be a few k of runtime, and all it does in the end is create inefficiencies and problems with interop with everything else.