Hacker News new | ask | show | jobs
by Const-me 3103 days ago
> The tokio-core crate provides the central event loop

Does it mean it only uses a single thread for IO notifications?

If yes, the performance won’t be exceptionally great, especially on servers with many CPU cores and fast network interfaces.

The underlying OS APIs (both epoll, kqueue and iocp) do support multithreaded asynchronous IO, so that’s not some platform limitation.

1 comments

One can spawn as many reactors as you would like. The only thing a reactor does is receive events off of epoll (or other system selector) and notify the associated task. The task could be on the reactor thread or across a different thread.

Generally speaking, how to optimize concurrency for a network based application is pretty use case specific.

tl;dr, you can fully take advantage of many core systems w/ Tokio.

High I/O systems usually spawn multiple reactors, e.g. one reactor per CPU core, and run these reactors on the same set of file descriptors.

Does that library support such use case? Or does it imply 1-to-many relation between reactors and files/sockets? The latter doesn’t scale well.

Tokio is about being flexible (true today, even more true in the upcoming release). It is more about set of primitives that you can assemble in a way that fits your needs. You can structure the concurrency of your application however you want.

So...

> High I/O systems usually spawn multiple reactors, e.g. one reactor per CPU core.

Depends on what you are calling multiple reactors. If you mean a loop that responds to events and run tasks, then yes. For example, you can plug in [this](http://github.com/carllerche/futures-pool) as the task executor and get a multi threaded, work stealing, scheduler.

Or, maybe you are talking about OS level selectors (epoll), in which case you are going to run up against OS limitations.

> you are talking about OS level selectors (epoll), in which case you are going to run up against OS limitations.

Yes, about them, but I’m not sure what OS limitations do you mean?

For Windows, it works fine from the very first NT 3.51 version of IOCP.

For Linux it indeed didn’t work in the very first version of epoll, but they fixed that adding EPOLLONESHOT flag, and recently EPOLLEXCLUSIVE flag for accept(), allowing to implement proper scaling of IO readiness notifications across multiple CPU cores.

You can get this working with Tokio if you know what you are doing.

However, I personally advise against it as I have found that deferring to the OS for scheduling results in poor thread affinity (your state gets bounced around threads unnecessarily).

You generally get better throughput by either running multiple fully isolated reactors (the seastar approach) or running a single reactor which only flags tasks as ready to be executed, and then use a work stealing thread pool to do the actual execution.

Both of these structures are easy to achieve with Tokio.

libevent2 (which tokio is very similar to) has the same constraint:

> Currently, only one thread can be dispatching a given event_base at a time. If you want to run events in multiple threads at once, you can either have a single event_base whose events add work to a work queue, or you can create multiple event_base objects.

http://www.wangafu.net/~nickm/libevent-2.1/doxygen/html/

We don't want to have to decide which thread will handle each connection, just pick an idle one.
Yes you can do this. The actual socket is not pinned to any thread, so you can move it to a thread pool or whatever.