Rotor and Tokio

Is there enough room for two asynchronous io frameworks in Rust?

I've spent a bit of time with rotor for io clients, and have found it great once you get over that (significant) cognitive barrier to entry. I've found it works best when you don't try to compose too much in a single loop, so I feel it's given me the tools to write a high performance connection pool that is abstracted away from users, and works well with futures.

Now tokio is a thing, which I haven't started with yet but it looks like it'll be much easier to compose. Does anyone, like @seanmonstar, have experience with both platforms and can outline their thoughts on what works well in either, and whether they see a future for both?

I'm in the process of converting the internal code base of hyper from using rotor to tokio, so I'll have some thoughts, but I haven't completed, so I'll have more later. Here's a disorganized list of what immediately jumps to mind as the reason I'm doing so:

  • tokio does a lot of network programming for me. Once I have a proper diff, I'm sore the majority of it will just be simply deleting lots of code that I needed to write in hyper before, but is so common that tokio does for me.
    • event loop interest registering
    • socket wakeup
    • keeping a record of what io operation blocked, especially important for TLS (since a read could actually be blocked on write during a TLS renegotiation)
  • tokio-proto includes several concepts around message framing that, again, allow deleting code
  • tokio-core knows all about Future, which helps chaining together several async operations (such as for a client needing dns, tcp handshake, tls handshake, and then normal io)
13 Likes

Thanks for sharing your early thoughts, I look forward to more once hyper is fully integrated!

I've been kind of struggling with understanding where exactly tokio sits in the stack, and I think I've hit an hapifany: for my use case (API client), it isn't important. What is important is how easily users can glue together the pipeline they want to run data through. And all I care about is the well-formedness of said data. So suddenly it isn't my responsibility to consider their DNS or TLS requirements, because that's the responsibility of another service, if they choose to utilise it.

Interesting stuff...

The goal of Tokio is to provide everything you need for async network programming. Futures are just an abstraction for managing async state, they do not provide anything out of the box for networking, that is where Tokio fits in.

Of course, Tokio is very young and we're still working on sorting out the details, but as of now, tokio-core is pretty solid out of the box. tokio-core provides all the necessary networking building blocks for doing async programming, like TCP & UDP types and a reactor.

The other bits, like tokio-proto etc... are still very much works in progress, but they provide higher level abstractions to make common network programming patterns easier.

Another goal of Tokio is to be very loosely coupled. So while Tokio may provide things that work "out of the box" they can be replaced / mixed & matched.

I know that this is a little vague, but Tokio is still a very early project. I would recommend focusing on tokio-core, and if you want to explore the other components, maybe jump in the Tokio Gitter channel and we can help provide some guidance.

Also, there should be a lot more documentation coming soonish.

2 Likes