-
Notifications
You must be signed in to change notification settings - Fork 19
Customizing cont.new with stack size #156
Description
One of the trickiest issues to solve in stack switching is how big a stack to allocate for the new coroutine. Empirically, it has been observed that coroutines' memory requirements are often wildly divergent with some (perhaps most) coroutines only needing a small amount of memory to complete their task.
There are several ways of dealing with this:
- use fixed size stacks that are the same size as the default stack.
- implement a strategy for automatically growing stacks
- allow the user (toolchain) to specify the size of the stack for the new coroutine.
The advantages of these different approaches include:
- Simplicity of implementation.
- Sensitivity to actual computation requirements; in addition, the default size of a stack can be set to a small value -- allowing an application to have large numbers of suspended computations.
- The application author may be the best source of actual knowledge about the expected size of a task. Allowing the toolchain to express this facilitates this.
Each of these also has disadvantages:
- Particularly on limited memory platforms (such as mobile devices) there may not be enough address space to accommodate large numbers of large stacks.
- Automatically growing stacks is complex to realize (a stack overflow can occur in code that was not compiled for coroutining) and significantly increases the attack surface for security vulnerabilities.
- the toolchain may not know how much space to allocate for the stack. In particular, WebAssembly does not expose this information -- for good reasons. In addition, the toolchain may guess incorrectly.
A proposal:
allow a form of coarse grain estimation of the expected size of a coroutine, and throw a well defined exception when the actual computation is too large.
I suggest simply adding a marker to the cont.new instruction that declares that "the coroutine is small". This would allow the engine to allocate a small stack structure for that coroutine.
How small is small?
This may be implementation defined; however, I suggest that a more rigorous approach would be to specify a minimum amount of stack space would be available. This could be expressed in bytes but higher level, engine independent way, would be to state this as a combination of frames and local variables.
This approach would allow toolchains to optimize the overall memory footprint of generated applications whilst also allowing for some large stacks. One might imagine, for example, that when implementing generators most coroutines would be marked as small, whereas the default for green threads would be normal sized stacks.