On 7/10/12 6:41 PM, Sebastian Sylvan wrote:
It would be cool if tasks started out more like PPL/TBB/Cilk tasks and
transitioned into the current thread-like construct and allocated
stack space only if needed. I.e. the first time a task needs to yield
its underlying "worker thread" (because it's about to block) it would
go through the work of allocating a stack (and heap?) and copy its
state into it.

This is hard in Rust because we don't have moving GC. We're working on it, but it will be quite a ways off. Even if we had moving GC, we still couldn't take a thread stack and move it somewhere, since arbitrary data can be pinned to the stack frame as a consequence of the way unsafe and borrowed pointers work.

There are, however, other optimizations we can do:

* As part of pipes, implement a blocking send-and-yield-to-target function that transitions straight to the new task without a trip through the scheduler. This basically optimizes down into a context switch, which should be on the order of a function call that saves and restores all registers.

* Have a thread-local set of "new stacks" always ready for use.

* Avoid creating a heap for a new task until the first malloc.

So in the fully optimized world the fast send-and-yield-to-target path might look like:

1. Grab a preallocated task structure and stack segment for the new task. This is just the head of a linked list stored in TLS; no locking is necessary.

2. Assuming the arguments to the task fit in registers, copy the registers into the new task structure.

3. Context switch; exchange all registers with the registers in the new task.

This may be competitive with Cilk. Can't predict without benchmarks, of course, but this seems reasonably likely to be fast.

Patrick
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to