quick-lint-js

Find bugs in JavaScript programs.

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
Flow
ESLint + TypeScript plugin
ESLint + Airbnb rules
TypeScript
TypeScript (JSX parser)
Deno (no linting)
Deno
response time (lower is better)
Results data table
linter response time (milliseconds)
min avg max ÷ qljsquick-lint-js
quick-lint-js 0.24 0.25 0.27 1.0×
ESLint 39.13 40.16 41.04 159.9×
ESLint + Vue plugin 44.94 47.91 53.20 190.7×
ESLint + React plugin 53.77 56.67 59.19 225.6×
Flow 61.03 61.48 62.07 244.8×
ESLint + TypeScript plugin 59.11 63.17 66.61 251.5×
ESLint + Airbnb rules 128.26 133.51 143.10 531.5×
TypeScript 175.26 195.47 205.85 778.2×
TypeScript (JSX parser) 202.52 216.75 257.74 862.8×
Deno (no linting) 269.71 272.13 279.22 1083.3×
Deno 279.27 282.10 293.25 1123.0×

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
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.10 0.11 1.0×
Flow 29.60 29.94 30.14 304.0×
ESLint + React plugin 29.38 30.72 35.01 311.9×
ESLint + TypeScript plugin 31.75 34.49 36.33 350.1×
Deno 231.27 232.48 233.75 2360.3×
Deno (no linting) 232.00 232.74 233.39 2362.9×
TypeScript (JSX parser) 275.02 275.62 276.13 2798.3×

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
Rome
RSLint
ESLint
ESLint + Vue plugin
ESLint + React plugin
ESLint + TypeScript plugin
Flow
ESLint + Airbnb rules
TypeScript
TypeScript (JSX parser)
Deno (no linting)
Deno
response time (lower is better)
Results data table
linter response time (milliseconds)
min avg max ÷ qljsquick-lint-js
quick-lint-js 0.28 0.34 0.44 1.0×
Rome 3.86 4.33 5.05 12.6×
RSLint 21.09 22.23 23.29 64.7×
ESLint 39.15 40.12 42.43 116.9×
ESLint + Vue plugin 43.66 46.87 52.84 136.5×
ESLint + React plugin 51.97 55.00 57.53 160.2×
ESLint + TypeScript plugin 59.44 62.56 66.58 182.2×
Flow 70.71 73.79 79.19 214.9×
ESLint + Airbnb rules 120.27 128.18 138.09 373.3×
TypeScript 134.45 164.57 188.96 479.3×
TypeScript (JSX parser) 133.65 170.21 214.42 495.8×
Deno (no linting) 278.84 280.26 282.66 816.3×
Deno 278.59 282.06 284.00 821.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).