Let's talk about tokio's `LocalSet`

(side note: why does this forum not have a category: "discussion"? "help" seems overly broad.)

As advised I'm starting a new topic.

The question is about tokio's LocalSet which guarantees a sequentially consistent single-thread like environment across .await point by ensuring that they execute on a single thread (the current thread). This feature allows the building of more traditional event-loop based environments (such as a traditional JS runtime). However, fundamentally, tokio appears designed to provide an M:N threading implementation so internally it is a multi-threaded program.

The question is to what extent LocalSet provides an efficient single-threaded execution engine given that it provides the full feature set of the tokio API. For instance, if a task calls tokio::sleep it seems that there's no separate code path for a call from a LocalSet task (the code seems to be using an Arc here unless I'm misreading it). So an interesting question is to what extent such a use would pay for unnecessary synchronization overhead (use of Arc where Rc would suffice, etc.), and potentially whether there's a need or use for a purely single-threaded async engine (if it doesn't already exist.) Of course, certain system interactions (like with a I/O threadpool to offload blocking I/O, etc.) will require synchronization in any event if this environment were to provide support for them.

1 Like

It is true that even if you use LocalSet, anything that is not specific to the LocalSet will still use synchronization. The major thing that you gain by using a LocalSet is that your types do not have to use synchronization.

It is worth mentioning that there are some things that make it necessary to have synchronization in code using LocalSet. For instance, the std Waker type is unconditionally Send, so tasks may be woken up from any thread.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.