Skip to content

fix(rolldown): set worker thread count with ROLLDOWN_WORKER_THREADS#9086

Merged
IWANABETHATGUY merged 1 commit intorolldown:mainfrom
fpotter:worker-threads-override
Apr 14, 2026
Merged

fix(rolldown): set worker thread count with ROLLDOWN_WORKER_THREADS#9086
IWANABETHATGUY merged 1 commit intorolldown:mainfrom
fpotter:worker-threads-override

Conversation

@fpotter
Copy link
Copy Markdown
Contributor

@fpotter fpotter commented Apr 13, 2026

Summary

In scenarios where you're running many concurrent instances of rolldown on the same machine (e.g., scheduled via Bazel), it's preferable to have each use a smaller number of worker threads.

As it was, each instance of rolldown would start a thread pool with count 1.5 times the number of physical CPUs. Running many instances concurrently would lead to high system load averages, with lots of rolldown worker threads just waiting to get scheduled, and each build running slower than it otherwise would.

Fix

Similar to the existing ROLLDOWN_MAX_BLOCKING_THREADS env var, we allow override of the worker thread count via ROLLDOWN_WORKER_THREADS.

We also set the thread name to "rolldown-worker" so it's easier to spot the change.

Test Plan

We can observe the number of worker threads started with strace on Linux.

Note that, in each invocation, we'll see (2) more worker threads than the value we set in .worker_threads(...) for Tokio. I believe these are the ephemeral threads creating for blocking calls.

Default stays the same

By default, expect the same 1.5X number of worker threads as before:

# My system has 8 cores
$ cat /proc/cpuinfo | grep 'cpu cores' | uniq
cpu cores	: 8

$ cd examples/basic-typescript
$ strace -f -e trace=prctl -o prctl.log -- pnpm build
$ cat prctl.log | grep -F 'prctl(PR_SET_NAME, "rolldown-worker"' | wc -l
14
# Expected: (8 * 1.5) + 2 = 14

Can set to 1

$ cd examples/basic-typescript
$ strace -f -e trace=prctl -o prctl.log -- env ROLLDOWN_WORKER_THREADS=1 pnpm build
$ cat prctl.log | grep -F 'prctl(PR_SET_NAME, "rolldown-worker"' | wc -l
3
# Expected: 1 + 2 = 3

Can set to 100

$ cd examples/basic-typescript
$ strace -f -e trace=prctl -o prctl.log -- env ROLLDOWN_WORKER_THREADS=100 pnpm build
$ cat prctl.log | grep -F 'prctl(PR_SET_NAME, "rolldown-worker"' | wc -l
102
# Expected: 100 + 2 = 102

Copy link
Copy Markdown
Member

@IWANABETHATGUY IWANABETHATGUY left a comment

Choose a reason for hiding this comment

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

LGTM

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Apr 13, 2026

Merging this PR will not alter performance

✅ 4 untouched benchmarks
⏩ 10 skipped benchmarks1


Comparing fpotter:worker-threads-override (f6bb1fd) with main (f1cb5a2)2

Open in CodSpeed

Footnotes

  1. 10 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

  2. No successful run was found on main (b51b22d) during the generation of this report, so f1cb5a2 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

## Summary

In scenarios where you're running many concurrent instances of rolldown
on the same machine (e.g., scheduled via Bazel), it's preferable to have
each use a smaller number of worker threads.

As it was, each instance of rolldown would start a thread pool with
count 1.5 times the number of physical CPUs.  Running many instances
concurrently would lead to high system load averages, with lots of
rolldown worker threads just waiting to get scheduled, and each build
running slower than it otherwise would.

## Fix

Similar to the existing `ROLLDOWN_MAX_BLOCKING_THREADS` env var, we
allow override of the worker thread count via `ROLLDOWN_WORKER_THREADS`.

We also set the thread name to "rolldown-worker" so it's easier to spot
the change.

## Test Plan

We can observe the number of worker threads started with strace on
Linux.

Note that, in each invocation, we'll see (2) more worker threads than
the value we set in `.worker_threads(...)` for Tokio.  I believe these
are the ephemeral threads creating for blocking calls.

#### Default stays the same

By default, expect the same 1.5X number of worker threads as before:

```sh
# My system has 8 cores
$ cat /proc/cpuinfo | grep 'cpu cores' | uniq
cpu cores	: 8

$ cd examples/basic-typescript
$ strace -f -e trace=prctl -o prctl.log -- pnpm build
$ cat prctl.log | grep -F 'prctl(PR_SET_NAME, "rolldown-worker"' | wc -l
14
# Expected: (8 * 1.5) + 2 = 14
```

#### Can set to 1

```sh
$ cd examples/basic-typescript
$ strace -f -e trace=prctl -o prctl.log -- env ROLLDOWN_WORKER_THREADS=1 pnpm build
$ cat prctl.log | grep -F 'prctl(PR_SET_NAME, "rolldown-worker"' | wc -l
3
# Expected: 1 + 2 = 3
```

#### Can set to 100

```sh
$ cd examples/basic-typescript
$ strace -f -e trace=prctl -o prctl.log -- env ROLLDOWN_WORKER_THREADS=100 pnpm build
$ cat prctl.log | grep -F 'prctl(PR_SET_NAME, "rolldown-worker"' | wc -l
102
# Expected: 100 + 2 = 102
```
@IWANABETHATGUY IWANABETHATGUY enabled auto-merge (squash) April 14, 2026 16:49
@IWANABETHATGUY IWANABETHATGUY force-pushed the worker-threads-override branch from 4a9007f to f6bb1fd Compare April 14, 2026 16:49
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 14, 2026

Deploy Preview for rolldown-rs canceled.

Name Link
🔨 Latest commit f6bb1fd
🔍 Latest deploy log https://app.netlify.com/projects/rolldown-rs/deploys/69de702ca759aa0008d516eb

@IWANABETHATGUY IWANABETHATGUY merged commit 24416a0 into rolldown:main Apr 14, 2026
31 checks passed
This was referenced Apr 15, 2026
shulaoda added a commit that referenced this pull request Apr 16, 2026
## [1.0.0-rc.16] - 2026-04-16

### 🚀 Features

- const enum cross-module inlining support (#8796) by @Dunqing
- implement module tagging system for code splitting (#9045) by @hyf0

### 🐛 Bug Fixes

- rolldown_plugin_vite_manifest: handle duplicate chunk names for CSS entries (#9059) by @sapphi-red
- improve error message for invalid return values in function options (#9125) by @shulaoda
- await async export-star init wrappers (#9101) by @thezzisu
- never panic during diagnostic emission (#9091) by @IWANABETHATGUY
- include array rest pattern in binding_identifiers (#9112) by @IWANABETHATGUY
- rolldown: set worker thread count with ROLLDOWN_WORKER_THREADS (#9086) by @fpotter
- rolldown_plugin_lazy_compilation: escape request ID in proxy modules (#9102) by @h-a-n-a
- treat namespace member access as side-effect-free (#9099) by @IWANABETHATGUY
- relax overly conservative side-effect leak check in chunk optimizer (#9085) by @IWANABETHATGUY
- runtime: release `cb` reference after `__commonJS` factory initialization (#9067) by @hyf0-agent
- `@__NO_SIDE_EFFECTS__` wrapper should not remove dynamic imports (#9075) by @IWANABETHATGUY
- rolldown_plugin_vite_import_glob: use POSIX path join/normalize for glob resolution (#9077) by @shulaoda
- emit REQUIRE_TLA error when require() loads a module with top-level await (#9071) by @jaehafe
- emit namespace declaration for empty modules in manual chunks (#8993) by @privatenumber
- rolldown_plugin_vite_import_glob: keep common base on path segment boundary (#9070) by @shulaoda
- prevent circular runtime helper imports during facade elimination (#8989) (#9057) by @IWANABETHATGUY
- correct circular dependency check in facade elimination (#9047) by @h-a-n-a
- docs: correct dead link in CodeSplittingGroup.tags JSDoc (#9051) by @hyf0
- emit DUPLICATE_SHEBANG warning when banner contains shebang (#9026) by @IWANABETHATGUY

### 🚜 Refactor

- use semantic reference flags for member write detection (#9060) by @Dunqing
- extract UsedSymbolRefs newtype wrapper (#9130) by @IWANABETHATGUY
- dedupe await wrapping in export-star init emit (#9119) by @IWANABETHATGUY
- calculate side-effect-free function symbols on demand (#9120) by @IWANABETHATGUY
- extract duplicated top-level await handling into shared helper (#9087) by @IWANABETHATGUY
- rolldown_plugin_vite_import_glob: use split_first for get_common_base (#9069) by @shulaoda
- simplify ESM init deduplication with idiomatic insert check (#9044) by @IWANABETHATGUY

### 📚 Documentation

- document runtime module placement strategy in code-splitting design (#9062) by @IWANABETHATGUY
- clarify `options` hook behavior difference with Rollup in watch mode (#9053) by @sapphi-red
- meta/design: introduce module tags (#9017) by @hyf0

### ⚡ Performance

- convert `generate_transitive_esm_init` to iterative (#9046) by @IWANABETHATGUY

### 🧪 Testing

- merge strict/non_strict test variants using configVariants (#9089) by @IWANABETHATGUY

### ⚙️ Miscellaneous Tasks

- disable Renovate auto-updates for oxc packages (#9129) by @IWANABETHATGUY
- upgrade oxc@0.126.0 (#9127) by @Dunqing
- deps: update napi to v3.8.5 (#9126) by @renovate[bot]
- deps: update dependency @napi-rs/cli to v3.6.2 (#9123) by @renovate[bot]
- move lazy-compilation design doc (#9117) by @h-a-n-a
- deps: update dependency vite-plus to v0.1.18 (#9118) by @renovate[bot]
- deps: update dependency vite-plus to v0.1.17 (#9113) by @renovate[bot]
- deps: update oxc to v0.125.0 (#9094) by @renovate[bot]
- deps: update dependency follow-redirects to v1.16.0 [security] (#9103) by @renovate[bot]
- deps: update test262 submodule for tests (#9097) by @sapphi-red
- deps: update crate-ci/typos action to v1.45.1 (#9096) by @renovate[bot]
- deps: update rust crates (#9081) by @renovate[bot]
- deps: update npm packages (#9080) by @renovate[bot]
- remove outdated TODO in determine_module_exports_kind (#9072) by @jaehafe
- rust/test: support `extendedTests: false` shorthand in test config (#9050) by @hyf0
- ci: extract shared infra-changes anchor in path filters (#9054) by @hyf0
- add docs build check to catch dead links in PRs (#9052) by @hyf0

### ❤️ New Contributors

* @thezzisu made their first contribution in [#9101](#9101)
* @fpotter made their first contribution in [#9086](#9086)
* @jaehafe made their first contribution in [#9071](#9071)
* @privatenumber made their first contribution in [#8993](#8993)

Co-authored-by: shulaoda <165626830+shulaoda@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants