On Aug 26, 2014, at 8:39 PM, Patrick Walton <pcwal...@mozilla.com> wrote:
> On 8/26/14 4:25 PM, Cameron Zwarich wrote: >> Cons: >> - Still requires an abstraction layer for features that differ across >> platforms, unless we fix a target platform. >> - There is a semantic gap between OS I/O primitives and Rust channels, and >> the problem of having a task that processes events from both still needs to >> be solved. >> - It is not easy to reclaim the wasted stack space of native threads. >> - We currently have a lot of per-pipeline tasks for loading resources, >> caches, etc. If we used native threads, it seems unlikely that we would use >> individual threads for each of these (e.g. every single loader task for >> every frame doing independent multiplexing of I/O), and we would want to >> pool them across pipelines. This introduces the (fairly certain, given past >> experiences) risk of Rust task failure induced by one pipeline affecting the >> loading of resources for another pipeline. Building on a smaller >> browser-agnostic abstraction means that the amount of trusted code (for the >> sake of isolation, not mere memory safety) is reduced, and there is less of >> a chance of browser-specific concerns causing problems. > > Your email deserves a more thought-out response than this, so I owe a more > in-depth reply, but just for what it's worth: I think the "failure brings > down other unrelated I/O operations in the thread pool" is an important point > that we will need to address. Indeed, "use a native task per I/O resource so > that we can handle failure" isn't a very compelling story. > > Part of the solution may well be to isolate failure using the "evil" `try` > functionality in the standard library. To be clear, I don't imagine this will > entail full C++/Java-style exceptions: there would be a sharing limitation > (which can be enforced by bounds on a callback) to encourage construction of > data structures that are safe for error recovery. > > In a sense, using `try` in this way is forcing us to recreate part of > libgreen. However, in the context of the resource manager, I think it's > better for Servo than libgreen was from an efficiency standpoint. This is > because the `try` model decouples two things that libgreen forced clients to > glue together: *failure isolation* and *a machine stack*. In the libgreen > model, if you want to isolate failure (which is very much desired by Servo), > you need to keep a machine stack around in 1:1 correspondence with your > failure domain (which does not seem desirable for each I/O resource from a > memory usage point of view). For I/O resources, there's no need to keep a > machine stack around, as the amount of state that each I/O resource needs can > be significantly smaller than an entire machine stack. (High-performance > evented I/O servers like nginx and HAProxy demonstrate that the performance > gains of forgoing the machine stack can be significant.) > > There's definitely work to be done to create all of this functionality, but I > think that there's a reasonable case to be made that, as far as the > performance of the resource task is concerned, Servo will come out better > than it would have using libgreen. Perhaps a succinct way of stating your point, if I am understanding it correctly, is that use of libgreen-style tasks conflates dynamically scoped failure isolation (i.e. ‘exceptions’) with the preservation of a machine stack as a continuation. Is your idea essentially to have an I/O thread pool that runs a particular request, using ‘try’ to isolate failure, and deliver a message back to a task within the pipeline / constellation compartment that is free to explode at any point? There is an additional complication here with getting rid of the machine stack in that the lifetime system in the Rust language gives a privileged status to the machine stack. The moment you CPS-convert a program you can’t use lifetimes to track ownership as effectively, and have to either merge things or use ref-counting / GC. This might not be applicable to our use-case; the resource loading tasks that multiplex I/O already track multiple resources. Thinking about these problems, it is clear that libgreen was never going to be a solution as-is. But its removal from the standard library and likely deprecation just forces the issue a bit, in that we should now decide what we actually want and use / fork libgreen as appropriate. There is an independently interesting question of how relevant the performance concerns of C10k+ servers are to I/O in browsers. From specific past experiences, reducing the number of copies of data and the number of hops between threads is important, but I’m not sure how much extra benefit is gained by going the distance. Cameron _______________________________________________ dev-servo mailing list dev-servo@lists.mozilla.org https://lists.mozilla.org/listinfo/dev-servo