3 ms·
> Call stacks are just a data structure like any other. Call stacks are a part of the system API/ABI; your fancy ersatz stacks not so much. This is kind of a
by zozbot234 3y ago
> Call stacks are just a data structure like any other.
Call stacks are a part of the system API/ABI; your fancy ersatz stacks not so much. This is kind of a key consideration in the above analysis. The whole point of having Windows API support for fibers was to try and obviate that basic pain point, but ultimately this has been shown not to be very successful.
> Rust async functions and C++ coroutines ... only use their state machines to store local state ... that lives across suspension points.
Yes and this is briefly mentioned in that analysis as a key advantage of stackless coroutines compared to fibers. If you might call a function that requires 500k of stack, a fiber has to provide for that amount of stack space to be available; a stackless coroutine doesn't need to store the 500k of data, provided that it doesn't live across await points.
- Rusky 3y agoFibers can make that exact same optimization by using a separate stack (as a stackless coroutine uses a separate state machine) alongside the C stack. This can be done either through stack switching, or by treating the fiber stack more like an ordinary object without a special reserved ABI register. The reason Windows fibers failed is not because they were stackful, but because they tried to use only one stack at a time.
- zozbot234 3y agoThis would seem to be comparable to segmented stacks - which turn out to be fiddly enough that Golang got rid of them. And they're said to be even less feasible in languages that don't use GC and can't adjust pointers to account for moved data.
- Rusky 3y agoSegmented vs contiguous stacks is a completely orthogonal design choice here. The key is merely that this stack is separate from the C stack but accessible simultaneously. As long as you have that, it can be segmented, or it can be contiguous and movable for growth if you have a GC and/or forbid pointers to locals, or it can be perfectly sized if you do a whole-program analysis on stack usage, or it can be large and non-moving like the C stack.