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