Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-blocking IO #1

Open
burdges opened this issue Dec 9, 2015 · 7 comments
Open

Non-blocking IO #1

burdges opened this issue Dec 9, 2015 · 7 comments

Comments

@burdges
Copy link

burdges commented Dec 9, 2015

At present this uses blocking IO? Or would you classify it as currently generic over the IO system in the sense that it is not really doing that yet?

Afaik almost everyone doing asynchronous IO in rust is using https://github.com/carllerche/mio in one form of fashion. It's a bare metal wrapper over epoll and kqueue that makes them work alike by calling a single common handler. It'll support Windows eventually too, albeit with some performance penalty.

There are a bunch of libraries that make mio nicer to use, mostly they build coroutines, like https://github.com/dpc/mioco, but several use callbacks like GNUnet's scheduler :

Also https://github.com/tailhook/rotor wants to do asynchronous IO using state machines built with algebraic data types, and composable so you can have them at multiple levels. Ain't exactly like GNUnet's scheduler, but sounds interesting.

I mostly buy @tailhook arguments for state machines over green threads and coroutnes, but his arguments for state machines over futures, promises, etc. consist of a vague claim of closures requiring too many RefCells and Rcs, which may or may not be true.

@canndrew
Copy link
Owner

canndrew commented Dec 9, 2015

At the moment this uses the standard library UnixStream type in blocking mode to talk to GNUnet services. It would be nice to make it generic in the type of blocking runtime it uses (ie. native or mioco). I'm not a big fan of callback-style APIs like GNUnet's scheduler. They obscure the control flow of the code and they don't play nice with Rust's borrow checker. In C, event loops like that are a necessary evil but I think in rust we can do a lot better. I haven't had a fair look at rotor but in my experience state machines also don't play nice with Rust's borrow checker. Because you can't move out of a borrowed context they force you to use state machines at every level of your program from top to bottom. You can't, for example, hold a state machine inside a Mutex because the type system won't let you change it's state. However, @tailhook's blog posts mention this problem so maybe he's found a nice solution to it.

By the way, this library hasn't been updated in a while. I still intend to keep working on it but I'm a bit distracted by other projects at the moment.

@burdges
Copy link
Author

burdges commented Dec 9, 2015

Any opinions on debuging? It's an absolute bitch debugging code that runs close to GNUnet's scheduler, although I think that'd be easier with futures, promises, etc. and Rust's closures help address the unreadability. I think @tailhook claimed that state machines should be easier though. I suppose that's believable, certainty they should be easier to write unit tests for, even when compared to coroutines.

@canndrew
Copy link
Owner

canndrew commented Dec 9, 2015

Yeah, debugging is another reason why I don't like callback-heavy code. Blocking-based (or pseudo-blocking-based a.la. mioco) code is much easier to follow the execution of. I think rotor-style state machines would be great for preventing bugs in the first place. The way that methods consume self and only return it if the object is still in a good state means you get a static guarantee that your code can never find its way into an invalid state. If I had my dream language to re-write the world in it would be pure-functional (ie. no &mut) with linear types so that this how all code would work.

@carllerche
Copy link

I mostly buy @tailhook arguments for state machines over green threads and coroutnes, but his arguments for state machines over futures, promises, etc. consist of a vague claim of closures requiring too many RefCells and Rcs, which may or may not be true.

IMO, a large number of RefCell and Rc usage is not needed with Eventual if a functional style of programming (FRP) is used. State is passed along in a functional style and communication is handled via futures & streams.

@tailhook
Copy link

@carllerche what about performance? It looks like @seanmonstar have tried eventual and got more than 10x drop in performance (hyperium/hyper#395 (comment)). My opinion is that FRP may be used on a much higher level, like managing protocol units rather than TCP chunks and epoll events. But lower level should be implemented as FSM.

@carllerche
Copy link

I have not looked in detail into how @seanmonstar used it. 10x seems excessively high to me in real world usage. Also once specialization lands, I will be able to make some significant performance improvements to Eventual.

There is no doubt that a pure state machine strategy is the fastest, but will take more boiler plate. I personally believe FRP w/ something like Eventual is the most ergonomic way to structure async / concurrent code. It's all a question of tradeoffs.

@burdges
Copy link
Author

burdges commented Mar 29, 2016

Appears capnp-rpc-rust issue 5 discussion clarifies the gj vs eventual issue. It's partially an issues of gj wanting single-threaded performance with Rcs vs eventual wanting thread safety with Arcs and Send bounds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants