quick-lint-js

Find bugs in JavaScript programs.

JS linter benchmarks

Which JavaScript linter is the fastest and consumes the least energy? We benchmarked different JavaScript linters to give you the answer.

LSP: incremental-change-wait express-router.js

An LSP server is software which plugs into your code editor. It provides diagnostics (error squigglies), go-to-definition, and auto-complete. This benchmark measures how long an LSP server takes to give diagnostics after making a change in a JavaScript file (e.g. after typing a character). In other words, it measures input latency. Lower latency means a faster-feeling editor.

Results

0 ms 60 FPS 50 ms 100 ms 150 ms 200 ms 250 ms 300 ms 350 ms 0.1 ms 1 ms 10 ms 100 ms 350 ms
quick-lint-js
ESLint
ESLint + Vue plugin
ESLint + React plugin
ESLint + TypeScript plugin
Flow
ESLint + Airbnb rules
Biome
Deno (no linting)
Deno
TypeScript (JSX parser)
TypeScript
response time (lower is better)
Results data table
linter response time (milliseconds)
min avg max ÷ qljsquick-lint-js
quick-lint-js 0.24 0.26 0.29 1.0×
ESLint 29.31 30.67 31.63 118.7×
ESLint + Vue plugin 33.24 33.87 35.20 131.1×
ESLint + React plugin 38.13 38.65 39.39 149.7×
ESLint + TypeScript plugin 50.76 53.04 55.78 205.4×
Flow 67.61 68.17 69.12 263.9×
ESLint + Airbnb rules 79.11 79.96 80.84 309.6×
Biome 143.48 145.70 147.95 564.1×
Deno (no linting) 258.08 258.73 259.89 1001.8×
Deno 258.58 259.26 259.80 1003.8×
TypeScript (JSX parser) 247.91 271.79 278.27 1052.3×
TypeScript 248.56 274.65 278.13 1063.4×

Benchmark details

Setup (untimed)

  1. Start the LSP server.
  2. Wait for initialization to finish.
  3. Open one document with contents from express-router.js.
  4. Wait for diagnostics.

Work (timed)

Repeat the following steps N times:

  1. Change a few characters in the document, sending small deltas in an LSP message.
  2. Wait for diagnostics.

LSP: incremental-change-wait react-quickly-ch10.jsx

This benchmark measures how long an LSP server takes to give diagnostics to an editor.

This benchmark is similar to the incremental-change-wait benchmark, except it uses a JSX (React) source file instead of a vanilla JavaScript source file.

Results

0 ms 60 FPS 50 ms 100 ms 150 ms 200 ms 250 ms 300 ms 350 ms 0.1 ms 1 ms 10 ms 100 ms 350 ms
quick-lint-js
Biome
Flow
ESLint + React plugin
ESLint + TypeScript plugin
Deno
Deno (no linting)
TypeScript (JSX parser)
response time (lower is better)
Results data table
linter response time (milliseconds)
min avg max ÷ qljsquick-lint-js
quick-lint-js 0.08 0.11 0.13 1.0×
Biome 5.97 6.47 7.27 60.6×
Flow 27.21 27.55 27.77 258.0×
ESLint + React plugin 27.98 28.43 28.97 266.2×
ESLint + TypeScript plugin 26.96 28.93 33.00 270.9×
Deno 226.97 227.86 228.56 2133.6×
Deno (no linting) 227.70 228.19 228.66 2136.7×
TypeScript (JSX parser) 274.45 275.37 275.96 2578.4×

Benchmark details

Setup (untimed)

  1. Start the LSP server.
  2. Wait for initialization to finish.
  3. Open one document with contents from react-quickly-ch10.jsx.
  4. Wait for diagnostics.

Work (timed)

Repeat the following steps N times:

  1. Add or remove a few characters in the document, sending small deltas in an LSP message.
  2. Wait for diagnostics.

LSP: full-change-wait express-router.js

This benchmark measures how long an LSP server takes to give diagnostics to an editor.

This benchmark differs from the incremental-change-wait benchmark in that the editor gives the new version of the file entirely rather than just the incremental changes. This is for compatibility with linters such as RSLint which do not support incremental changes.

Results

0 ms 60 FPS 50 ms 100 ms 150 ms 200 ms 250 ms 300 ms 350 ms 0.1 ms 1 ms 10 ms 100 ms 350 ms
quick-lint-js
RSLint
ESLint
ESLint + Vue plugin
Flow
ESLint + React plugin
ESLint + TypeScript plugin
ESLint + Airbnb rules
Biome
TypeScript (JSX parser)
Deno (no linting)
Deno
TypeScript
response time (lower is better)
Results data table
linter response time (milliseconds)
min avg max ÷ qljsquick-lint-js
quick-lint-js 0.29 0.32 0.38 1.0×
RSLint 20.12 20.17 20.23 63.9×
ESLint 29.27 30.10 31.11 95.4×
ESLint + Vue plugin 32.72 33.42 34.12 106.0×
Flow 32.80 33.45 34.36 106.0×
ESLint + React plugin 37.50 38.45 39.11 121.9×
ESLint + TypeScript plugin 48.87 50.98 53.81 161.6×
ESLint + Airbnb rules 79.09 80.24 81.72 254.4×
Biome 143.88 145.63 148.62 461.7×
TypeScript (JSX parser) 224.56 257.80 285.38 817.4×
Deno (no linting) 258.04 258.99 259.62 821.2×
Deno 257.61 259.03 260.01 821.3×
TypeScript 224.95 272.06 309.69 862.6×

Benchmark details

Setup (untimed)

  1. Start the LSP server.
  2. Wait for initialization to finish.
  3. Open one document with contents from express-router.js.
  4. Wait for diagnostics.

Work (timed)

Repeat the following steps N times:

  1. Change a few characters in the document, sending the entire new document in an LSP message.
  2. Wait for diagnostics.

Methodology

These benchmarks measure the following linters:

These benchmarks were measured on the following machine:

Comments

Deno

Deno's LSP server (and thus its Visual Studio Code extension) delays processing by 200 milliseconds. This means that Deno appears to be much slower than it actually is, but this artificial latency does affect the editing experience.

TypeScript

TypeScript's LSP server (but not its Visual Studio Code extension) delays processing by 200 milliseconds + 50 milliseconds. This means that TypeScript appears to be much slower than it actually is, but this artificial latency does affect the editing experience (in all editors except Visual Studio Code).