Skip to content

extension_host: Avoid creating a Tokio runtime#45990

Merged
Veykril merged 2 commits intozed-industries:mainfrom
marcocondrache:fix/tokio-runtime
Jan 4, 2026
Merged

extension_host: Avoid creating a Tokio runtime#45990
Veykril merged 2 commits intozed-industries:mainfrom
marcocondrache:fix/tokio-runtime

Conversation

@marcocondrache
Copy link
Contributor

@marcocondrache marcocondrache commented Jan 3, 2026

While profiling Zed, I noticed around 12 tokio-runtime-worker threads. Since gpui_tokio runs a Tokio runtime with only two worker threads, this meant something else was spinning up a default Tokio runtime (My machine has 10 cores).

After digging into it a bit, it looks like wasmtime-wasi needs a Tokio runtime for some of its calls. That’s also why we run extension tasks on gpui-tokio in the first place.

Reproduction case:

  1. Run a clean Zed build.
  2. Sample the process → only 2–3 Tokio threads.
  3. Install a WASM extension (for example https://github.com/zed-extensions/nix), which shouldn’t pull in anything that creates its own runtime.
  4. Sample the process again → 10+ Tokio worker threads show up.
marcocondrache@xawed ~/P/zed (main)> sample 34260 1 | grep -E "Thread_"
Sampling process 34260 for 1 second with 1 millisecond of run time between samples
Sampling completed, processing symbols...
Sample analysis of process 34260 written to file /tmp/zed_2026-01-03_112527_5pq7.sample.txt
    744 Thread_3086626   DispatchQueue_1: com.apple.main-thread  (serial)
    744 Thread_3086629: RayonWorker0
    ....
    744 Thread_3086651: MacWatcher
    744 Thread_3086653: MacWatcher
    744 Thread_3086661: com.apple.NSEventThread
    744 Thread_3086680: tokio-runtime-worker
    744 Thread_3086681: tokio-runtime-worker
    ...
    744 Thread_3087087: tokio-runtime-worker
    744 Thread_3087089: tokio-runtime-worker
    744 Thread_3087090: tokio-runtime-worker
    744 Thread_3087091: tokio-runtime-worker
    744 Thread_3087092: tokio-runtime-worker
    744 Thread_3087093: tokio-runtime-worker
    744 Thread_3087094: tokio-runtime-worker
    744 Thread_3087095: tokio-runtime-worker
    744 Thread_3087096: tokio-runtime-worker
    744 Thread_3087097: tokio-runtime-worker
    ...

Release Notes:

  • Reduced number of threads when using extensions

Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Jan 3, 2026
@github-actions github-actions bot added the community champion Issues filed by our amazing community champions! 🫶 label Jan 3, 2026
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
@osiewicz
Copy link
Member

osiewicz commented Jan 3, 2026

Just a heads-up (I haven't actually reviewed this PR thoroughly): this part of codebase is a bit sensitive to whether it's running on background vs foreground thread. In practice, we want to off-load as much work onto background executor as possible so as to not load extensions using foreground thread whenever possible. See #41398

@marcocondrache
Copy link
Contributor Author

@osiewicz thanks a lot for the heads-up. I’ve tried to reflect this by splitting the loading task into two parts. The heavier work (compilation and parsing) still runs on the background executor, while the remaining part, which is mostly wasi calls, runs on gpui_tokio and should be I/O bound.

@Veykril Veykril self-assigned this Jan 4, 2026
Copy link
Member

@Veykril Veykril left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

From what I can tell, all the work is still happening on the background (either our background workers, or the tokio ones, so that should be fine from that I can tell)

@Veykril Veykril merged commit 61b3889 into zed-industries:main Jan 4, 2026
24 checks passed
rtfeldman pushed a commit that referenced this pull request Jan 5, 2026
While profiling Zed, I noticed around 12 `tokio-runtime-worker` threads.
Since `gpui_tokio` runs a Tokio runtime with only two worker threads,
this meant something else was spinning up a default Tokio runtime (My
machine has 10 cores).

After digging into it a bit, it looks like `wasmtime-wasi` needs a Tokio
runtime for some of its calls. That’s also why we run extension tasks on
`gpui-tokio` in the first place.

Reproduction case:

1. Run a clean Zed build.
2. Sample the process → only 2–3 Tokio threads.
3. Install a WASM extension (for example
https://github.com/zed-extensions/nix), which shouldn’t pull in anything
that creates its own runtime.
4. Sample the process again → 10+ Tokio worker threads show up.

```
marcocondrache@xawed ~/P/zed (main)> sample 34260 1 | grep -E "Thread_"
Sampling process 34260 for 1 second with 1 millisecond of run time between samples
Sampling completed, processing symbols...
Sample analysis of process 34260 written to file /tmp/zed_2026-01-03_112527_5pq7.sample.txt
    744 Thread_3086626   DispatchQueue_1: com.apple.main-thread  (serial)
    744 Thread_3086629: RayonWorker0
    ....
    744 Thread_3086651: MacWatcher
    744 Thread_3086653: MacWatcher
    744 Thread_3086661: com.apple.NSEventThread
    744 Thread_3086680: tokio-runtime-worker
    744 Thread_3086681: tokio-runtime-worker
    ...
    744 Thread_3087087: tokio-runtime-worker
    744 Thread_3087089: tokio-runtime-worker
    744 Thread_3087090: tokio-runtime-worker
    744 Thread_3087091: tokio-runtime-worker
    744 Thread_3087092: tokio-runtime-worker
    744 Thread_3087093: tokio-runtime-worker
    744 Thread_3087094: tokio-runtime-worker
    744 Thread_3087095: tokio-runtime-worker
    744 Thread_3087096: tokio-runtime-worker
    744 Thread_3087097: tokio-runtime-worker
    ...
```

Release Notes:

- Reduced number of threads when using extensions

---------

Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
LivioGama pushed a commit to LivioGama/zed that referenced this pull request Jan 20, 2026
While profiling Zed, I noticed around 12 `tokio-runtime-worker` threads.
Since `gpui_tokio` runs a Tokio runtime with only two worker threads,
this meant something else was spinning up a default Tokio runtime (My
machine has 10 cores).

After digging into it a bit, it looks like `wasmtime-wasi` needs a Tokio
runtime for some of its calls. That’s also why we run extension tasks on
`gpui-tokio` in the first place.

Reproduction case:

1. Run a clean Zed build.
2. Sample the process → only 2–3 Tokio threads.
3. Install a WASM extension (for example
https://github.com/zed-extensions/nix), which shouldn’t pull in anything
that creates its own runtime.
4. Sample the process again → 10+ Tokio worker threads show up.

```
marcocondrache@xawed ~/P/zed (main)> sample 34260 1 | grep -E "Thread_"
Sampling process 34260 for 1 second with 1 millisecond of run time between samples
Sampling completed, processing symbols...
Sample analysis of process 34260 written to file /tmp/zed_2026-01-03_112527_5pq7.sample.txt
    744 Thread_3086626   DispatchQueue_1: com.apple.main-thread  (serial)
    744 Thread_3086629: RayonWorker0
    ....
    744 Thread_3086651: MacWatcher
    744 Thread_3086653: MacWatcher
    744 Thread_3086661: com.apple.NSEventThread
    744 Thread_3086680: tokio-runtime-worker
    744 Thread_3086681: tokio-runtime-worker
    ...
    744 Thread_3087087: tokio-runtime-worker
    744 Thread_3087089: tokio-runtime-worker
    744 Thread_3087090: tokio-runtime-worker
    744 Thread_3087091: tokio-runtime-worker
    744 Thread_3087092: tokio-runtime-worker
    744 Thread_3087093: tokio-runtime-worker
    744 Thread_3087094: tokio-runtime-worker
    744 Thread_3087095: tokio-runtime-worker
    744 Thread_3087096: tokio-runtime-worker
    744 Thread_3087097: tokio-runtime-worker
    ...
```

Release Notes:

- Reduced number of threads when using extensions

---------

Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
LivioGama pushed a commit to LivioGama/zed that referenced this pull request Jan 20, 2026
While profiling Zed, I noticed around 12 `tokio-runtime-worker` threads.
Since `gpui_tokio` runs a Tokio runtime with only two worker threads,
this meant something else was spinning up a default Tokio runtime (My
machine has 10 cores).

After digging into it a bit, it looks like `wasmtime-wasi` needs a Tokio
runtime for some of its calls. That’s also why we run extension tasks on
`gpui-tokio` in the first place.

Reproduction case:

1. Run a clean Zed build.
2. Sample the process → only 2–3 Tokio threads.
3. Install a WASM extension (for example
https://github.com/zed-extensions/nix), which shouldn’t pull in anything
that creates its own runtime.
4. Sample the process again → 10+ Tokio worker threads show up.

```
marcocondrache@xawed ~/P/zed (main)> sample 34260 1 | grep -E "Thread_"
Sampling process 34260 for 1 second with 1 millisecond of run time between samples
Sampling completed, processing symbols...
Sample analysis of process 34260 written to file /tmp/zed_2026-01-03_112527_5pq7.sample.txt
    744 Thread_3086626   DispatchQueue_1: com.apple.main-thread  (serial)
    744 Thread_3086629: RayonWorker0
    ....
    744 Thread_3086651: MacWatcher
    744 Thread_3086653: MacWatcher
    744 Thread_3086661: com.apple.NSEventThread
    744 Thread_3086680: tokio-runtime-worker
    744 Thread_3086681: tokio-runtime-worker
    ...
    744 Thread_3087087: tokio-runtime-worker
    744 Thread_3087089: tokio-runtime-worker
    744 Thread_3087090: tokio-runtime-worker
    744 Thread_3087091: tokio-runtime-worker
    744 Thread_3087092: tokio-runtime-worker
    744 Thread_3087093: tokio-runtime-worker
    744 Thread_3087094: tokio-runtime-worker
    744 Thread_3087095: tokio-runtime-worker
    744 Thread_3087096: tokio-runtime-worker
    744 Thread_3087097: tokio-runtime-worker
    ...
```

Release Notes:

- Reduced number of threads when using extensions

---------

Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
LivioGama pushed a commit to LivioGama/zed that referenced this pull request Feb 15, 2026
While profiling Zed, I noticed around 12 `tokio-runtime-worker` threads.
Since `gpui_tokio` runs a Tokio runtime with only two worker threads,
this meant something else was spinning up a default Tokio runtime (My
machine has 10 cores).

After digging into it a bit, it looks like `wasmtime-wasi` needs a Tokio
runtime for some of its calls. That’s also why we run extension tasks on
`gpui-tokio` in the first place.

Reproduction case:

1. Run a clean Zed build.
2. Sample the process → only 2–3 Tokio threads.
3. Install a WASM extension (for example
https://github.com/zed-extensions/nix), which shouldn’t pull in anything
that creates its own runtime.
4. Sample the process again → 10+ Tokio worker threads show up.

```
marcocondrache@xawed ~/P/zed (main)> sample 34260 1 | grep -E "Thread_"
Sampling process 34260 for 1 second with 1 millisecond of run time between samples
Sampling completed, processing symbols...
Sample analysis of process 34260 written to file /tmp/zed_2026-01-03_112527_5pq7.sample.txt
    744 Thread_3086626   DispatchQueue_1: com.apple.main-thread  (serial)
    744 Thread_3086629: RayonWorker0
    ....
    744 Thread_3086651: MacWatcher
    744 Thread_3086653: MacWatcher
    744 Thread_3086661: com.apple.NSEventThread
    744 Thread_3086680: tokio-runtime-worker
    744 Thread_3086681: tokio-runtime-worker
    ...
    744 Thread_3087087: tokio-runtime-worker
    744 Thread_3087089: tokio-runtime-worker
    744 Thread_3087090: tokio-runtime-worker
    744 Thread_3087091: tokio-runtime-worker
    744 Thread_3087092: tokio-runtime-worker
    744 Thread_3087093: tokio-runtime-worker
    744 Thread_3087094: tokio-runtime-worker
    744 Thread_3087095: tokio-runtime-worker
    744 Thread_3087096: tokio-runtime-worker
    744 Thread_3087097: tokio-runtime-worker
    ...
```

Release Notes:

- Reduced number of threads when using extensions

---------

Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed The user has signed the Contributor License Agreement community champion Issues filed by our amazing community champions! 🫶

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants