On Wed, Nov 13, 2013 at 1:49 PM, Bill Myers <[email protected]> wrote:
> I see several proposals for the future of Rust tasks, and I think one of the
> best approaches is being overlooked, and that is something similar to async
> in C# (http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx).
>
> In C#, the "async" keyword can be applied to functions and it causes the
> compiler to transform a function that returns T into a function that returns
> a Task<T> (which is C#'s name for a future of type T) representing the
> potentially asynchronous computation.
>
> Blocking is representing by using the "await" keyword on a future (typically
> returned by a call to another "async" function), and it causes the compiler
> to perform a Continuation-Passing Style transformation, and attach the
> continuation to the future, returning another future representing the
> composed computation.
>
> I/O functions are designed to return futures, so in this system blocking
> causes all calling "async" functions to return, building up a chain of
> continuations on the heap, which is equivalent to the machine stack in a
> current-Rust task, but which is as small as needed, and is only used for
> call chains that block.
>
> In Rust, this transformation is much more delicate, because the resulting
> return value futures must have a lifetime that is the smallest among all the
> arguments to the function, if those arguments are needed by the
> continuation, and the argument types must be "shareable" between parallel
> forks (e.g. std::rc::Rc is not shareable because RC manipulation is
> non-atomic).
>
> However, it is possible to restrict the system to use non-delimited
> continuations instead of the delimited continuations and futures, which
> would avoid this problem, since futures cannot be used explicitly anymore
> (at the cost of making flexible parallelism impossible).
>
> In this latter case, it would be equivalent to the current task system,
> except for requiring blocking functions to be marked "async"; the "await"
> keyword would not be required, since it would effectively become compulsory
> if there are no first-class futures returned for async functions.
>
> Advantages:
> - Functions and interfaces that can perform I/O or can block are clearly
> marked by a keyword
> - Can have billions of blocked tasks (with hundreds of gigabytes of RAM)
> since the memory used by each blocked task is truly minimized because it's
> on the heap
>
> Disadvantages:
> - Requires an heap allocation for every function call to an async function
> (to hold the continuation data)
> - Non-"async" functions cannot call "async" functions, so interfaces must be
> explicitly marked as async or not
> - Requires to implement the transform in the compiler
>
> Microsoft switched to this paradigm in the latest version of C# and in the
> Windows RT API, and it might be an appropriate choice for Rust too.

The issue with async/await is that while it maps very well to the AIO
primitives like IOCP and POSIX AIO, it doesn't map well to something
that's solid on Linux. It's just not how I/O is done on the platform.
It uses *non-blocking* I/O so scale up socket servers, with
notification of ready state rather than completion state. This doesn't
work for file system access though.

There's a significant performance hit from moving maybe-blocking I/O
calls into thread pools to fit a square peg into a round hole.
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to