tokio icon indicating copy to clipboard operation
tokio copied to clipboard

Proposal: Deprecate Tokio's LocalSet

Open Darksonn opened this issue 1 year ago • 8 comments

This is a proposal to deprecate the Tokio LocalSet abstraction in favor of a new LocalRuntime type. Currently, to spawn !Send tasks on Tokio you must use a combination of a current-thread runtime and LocalSet to make that work. However, tasks on a LocalSet are separate from the rest of the runtime in an uncomfortable way. For example:

  • Tasks on the LocalSet can tokio::spawn to get onto the runtime, but once you're on the runtime, you can no longer spawn_local to get back into the LocalSet.
  • From the runtime's perspective, all of the tasks in the LocalSet behave like a single task using FuturesUnordered, so various runtime options such as event_interval behave in a very surprising way by counting many tasks as a single task.
  • After discussions with Deno (a while ago), use of LocalSet has been shown to involve considerable performance overhead compared to unsafely spawning the !Send tasks onto a current-thread runtime.

Because of the above, I have proposed to add a new type called LocalRuntime which will be the replacement. Please see #6739 for the feature request to add that type. However, beyond just adding a new LocalRuntime type, I am also proposing to formally deprecate the LocalSet type. That's this issue.

Specifically, I am proposing the following course of action:

  1. First, we add a LocalRuntime type, which would close #6739.
  2. Then, 6 months later, we add #[deprecated] to the LocalSet type, so that existing users of LocalSet receive a warning that recommends LocalRuntime.
  3. Finally, since we are a stable 1.x crate, we keep LocalSet working forever.

I believe that all existing uses of LocalSet can be replaced either by the new LocalRuntime or by FuturesUnordered. The advantage of this approach is that the current design of LocalSet make it impossible to add some features without having them be really confusing:

  • Issue #3181 proposes to add hooks that run when a task is spawned / destroyed. The hooks would not run for tasks on the LocalSet. This is confusing.
  • Task dumps currently don't look inside block_on, which means that LocalSet tasks are completely invisible to task dumps.

In both cases, supporting LocalSet well is very difficult. As long as LocalSet remains a first-class citizen, it is difficult to introduce new features that affect all tasks without having confusing behavior when LocalSet is used.

Note that spawn_local is not being deprecated. The intent is that it will work together with LocalRuntime.

Some alternative options:

  • Do nothing. The previously mentioned disadvantages apply.
  • Add LocalRuntime but do not deprecate LocalSet. This provides a way to work around the performance issues of LocalSet, but ultimately it is still difficult to introduce new features that affect all tasks on the runtime.

The purpose of this issue is to gather feedback from users of LocalSet. Please post your experience below. I am especially interested in use-cases that cannot be replaced by LocalRuntime or FuturesUnordered.

Darksonn avatar Aug 01 '24 20:08 Darksonn

I am strongly in favor of this proposal.

Noah-Kennedy avatar Aug 01 '24 20:08 Noah-Kennedy

how we can unsafe spawn no send fut on runtime? I didn't found unsafe method to do

taikulawo avatar Sep 02 '24 16:09 taikulawo

how we can unsafe spawn no send fut on runtime? I didn't found unsafe method to do

Right now, you can only spawn such things on a LocalSet via spawn_local.

With the PR I've opened to add LocalRuntime, there you will soon be able to use spawn_local on a special runtime with a different type signature as well.

Note that these are not unsafe - it is perfectly sound to spawn a future in these contexts where doing so is valid.

Noah-Kennedy avatar Sep 02 '24 17:09 Noah-Kennedy

Anyone interested in following the LocalRuntime work can follow the PR (#6808) or the tracking issue (#6739).

Noah-Kennedy avatar Sep 03 '24 14:09 Noah-Kennedy

I am also in favour of this. The actix runtime is based on LocalSet which can bite you if you use tokio::spawn somewhere and that future uses actix::spawn. I will rewrite the actix_rt crate to use the new method once this is released.

Sytten avatar Sep 03 '24 20:09 Sytten

On the actix-rt note, a better migration path for our downstream users would be if #[tokio::main] has this as a flavor option with or soon after release of LocalRuntime, making actix-rt an optional dependency strictly for actors support.

robjtede avatar Sep 04 '24 00:09 robjtede

We'd better write a short migration guideline, I believe a few migration examples are enough.

ADD-SP avatar Aug 30 '25 10:08 ADD-SP

Hello folks, tokio is moving forward with the stabilization of LocalRuntime, we welcome community involvement, especially in discussing downstream impacts.

See #7558

ADD-SP avatar Aug 30 '25 10:08 ADD-SP