Skip to content

perf: ask ESLint to spread its own lint across threads - #323

Closed
alexander-akait wants to merge 1 commit into
mainfrom
perf/eslint-concurrency
Closed

perf: ask ESLint to spread its own lint across threads#323
alexander-akait wants to merge 1 commit into
mainfrom
perf/eslint-concurrency

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Summary

ESLint leaves its concurrency option "off", which lints on the thread webpack builds on. Over three hundred modules that holds the main thread for 1084 ms and costs the whole build about fifteen per cent — which also means #319's overlap of linting with module building could not actually overlap. The ESLint check now asks for "auto" unless you say otherwise.

Measured on a four-core runner, 300 modules, arms interleaved and warmed, best of three:

arm full build max main-thread block
concurrency: "off" 3205 ms 1084 ms
this PR's default 2729 ms 6 ms
concurrency: 4 3974 ms 7 ms

"auto" rather than a count, because ESLint sizes "auto" against the machine while a fixed number fights webpack for the same cores and came out slower than no threads at all; it is also the form ESLint answers with ESLintPoorConcurrencyWarning, which "auto" does not trigger.

Two things it is not. It is not a new option — concurrency is ESLint's own and is passed through untouched, "off" included, so this only changes what is sent when nothing was written. And it is not the worker pool the equivalent plugins for other bundlers offer: a single jest-worker measured 3426 ms against 3026 in-process, and a pool of four beat ESLint's own threads by eight per cent standalone while hitting the same oversubscription in a real build — so that approach was measured and dropped rather than built.

The guard is 9.34.0, where ESLint gained the option; the peer range starts at ^9.0.0, and ESLint rejects an option it has never heard of with Invalid Options. Flat config only, since that is where the option lives.

What kind of change does this PR introduce?

perf

Did you add tests for your changes?

Yes — test/concurrency.test.js over a new test/mock/eslint-options recorder, six cases: the default is asked for, a user's number and "off" survive, 9.33.0 is not offered the option, 9.34.0 is, and an eslintrc config is left alone.

Does this PR introduce a breaking change?

No. Anything written by hand is passed through as before, and an ESLint that lacks the option is never sent it.

If relevant, what needs to be documented once your changes are merged or what have you already documented?

The ESLint section of README.md is updated here, including that webpack spells this idea parallelism and uses the word concurrency for something else, so the option's meaning is ESLint's. The webpack.js.org page wants the same note after release.

Use of AI

AI was used. Claude Code benchmarked five arms standalone and three inside a real webpack build, bisected the published ESLint tarballs to find the release that added the option, then wrote the guard, the mock, the tests and the documentation. Every number above came out of a run, not an estimate.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GzZci4NQeiqwdrVfd7dGXy


Generated by Claude Code

ESLint leaves `concurrency` off, which lints on the thread webpack builds
on. Over three hundred modules that holds the main thread for 1084 ms and
costs the build about fifteen per cent: 3205 ms against 2729 ms once the
lint threads.

`"auto"` is asked for rather than a count. ESLint sizes it against the
machine, where a fixed number fights webpack for the same cores and came
out slower than no threads at all — 3974 ms at four on a four core runner,
against 3611 ms with none — and is also what ESLint emits
`ESLintPoorConcurrencyWarning` over.

Only where the loaded ESLint knows the option, which is 9.34.0 and above
under flat config; the peer range starts at 9.0.0, and anything below that
rejects an option it has never heard of.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GzZci4NQeiqwdrVfd7dGXy
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.

1 participant