Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Performance

Wall-clock speed of arity against other R tooling, measured with hyperfine. Two operations are covered:

  • the formatter, compared against air and styler;
  • the linter, compared against jarl and lintr.

Each operation is measured at two scopes: single files (the largest source file of each benchmarked package, plus two synthetic corpus tiers) and whole projects (real R packages). arity is the baseline in every chart, and every other tool’s time is reported relative to it.

The tools also pay very different startup floors: styler and lintr run inside an R process, so a large part of their time on small inputs is interpreter startup rather than real work. Treat the ratios, not the absolute milliseconds, as the takeaway.

The figures below are regenerated manually with task bench and committed as a machine-readable artifact (benches/benchmark_results.json); they are never re-measured when this site is built or in CI.

How it is measured

For single files, each tool is invoked as a user would pipe (formatters) or point it at a file (linters):

ToolInvocation
arityarity format / arity lint FILE
airair format --stdin-file-path bench.R
stylerRscript -e 'styler::style_text(readLines(file("stdin")))'
jarljarl check FILE
lintrRscript -e 'lintr::lint(FILE)'

For projects, each tool walks the package’s R/ source tree in one invocation. Formatters run in check mode so nothing is mutated, but the full formatting work is still done:

ToolInvocation
arityarity format --check R/ / arity lint R/
airair format --check R/
jarljarl check R/
lintrRscript -e 'lintr::lint_dir("R/")'

arity is the baseline; every other tool’s time is reported relative to it. Comparison tools absent from the machine are skipped, so a run without jarl simply omits it from the linter charts. The timing backend prefers hyperfine (warmup plus stddev/min/max); without hyperfine and jq it falls back to a mean-only shell loop and the min/max columns become blank.

The R-backed tools need two caveats. styler and lintr pay an interpreter startup floor plus a steep per-line cost, so they are skipped on documents above 20,000 lines to keep a run tractable; styler is additionally absent from the project charts, because style_dir would rewrite the checkout and it has no check-only directory mode. styler’s persistent on-disk cache of already-styled expressions is deactivated for the measurement, so that every run does the full work rather than inheriting whatever an earlier run happened to style. Because the tools do such different work, this is a rough scale comparison, not a like-for-like one. Set ARITY_BENCH_NO_R=1 to leave both out of a run.

Corpus

Single files mix real and synthetic input. The real documents are the largest source file of each benchmarked package, which is the closest stand-in for the per-file work an editor asks of a formatter or linter. The synthetic tiers are built by concatenating every formatter fixture’s expected.R (crates/arity-formatter/tests/fixtures/formatter/*/expected.R, sorted, blank-line separated) into a base block and repeating it to two sizes. That content repeats, so it is cache-friendly and not representative of real code; it exists to amortize process startup and show rough scaling.

Projects use real R packages: the tidyr and MASS source trees, cloned once at pinned tags into a local cache. The two are deliberately unalike—tidyr is modern tidyverse code, MASS is long-lived base-R-style code. Point the benchmark at your own checkout with ARITY_BENCH_PROJECT=/path/to/pkg task bench, which replaces the list entirely; only a package’s R/ directory is measured.

Setup

  • arity: 0.16.0
  • air: 0.11.0
  • jarl: 0.5.0
  • lintr: 3.3.0.1
  • styler: 1.11.0
  • backend: hyperfine (min runs: 3)
  • host: linux/x86_64, AMD Ryzen 9 7900 12-Core Processor
  • generated: 2026-08-06T14:52:58Z

Results

Each operation gets its own section below, split into single files and whole projects. The arity baseline sits on the dashed line at 1 in every chart; faster tools fall below it, slower tools rise above.

Formatter

Single files

Formatting speed on single files relative to arity, one dot per document: the largest source file of each benchmarked package, then two synthetic corpus tiers. The vertical axis is mean wall-clock time as a ratio to arity on a log scale, so arity lies on the dashed baseline at 1; faster tools fall below it and slower tools rise above. Hover a dot for the exact figures.
Data table
MASS/polr.R (19787 bytes, 534 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity5.84554.95717.9215baseline
air7.91587.03649.41931.4x slower
styler3005.22782991.94733024.0944514.1x slower
tidyr/pivot-wide.R (23349 bytes, 807 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity4.66003.95056.9153baseline
air5.21264.51008.49231.1x slower
styler1657.74811637.98781678.5579355.7x slower
small (128902 bytes, 8892 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity18.889916.438124.1338baseline
air24.700422.659728.36251.3x slower
styler11257.264511235.016211288.0166595.9x slower
large (1546824 bytes, 106704 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity472.6370460.7096493.4121baseline
air311.0487297.7228329.77851.5x faster

Projects

Formatting speed on real R packages (the tidyr and MASS source trees) relative to arity, on the same log-ratio axis.
Data table
tidyr (245685 bytes, 8774 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity25.479623.611228.0976baseline
air35.474833.910638.04281.4x slower
MASS (214820 bytes, 5951 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity50.842648.814553.4183baseline
air61.486159.465365.04811.2x slower

Linter

Single files

Linting speed on single files relative to arity, one dot per document, on the same log-ratio axis as the formatter charts.
Data table
MASS/polr.R (19787 bytes, 534 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity26.236923.803431.0467baseline
jarl12.894611.936215.01832.0x faster
lintr1106.30451088.37351122.854142.2x slower
tidyr/pivot-wide.R (23349 bytes, 807 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity20.996318.805523.3214baseline
jarl10.91989.497412.85761.9x faster
lintr995.9262986.53831014.048747.4x slower
small (128902 bytes, 8892 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity32.556929.840636.1271baseline
jarl28.322826.079333.78901.1x faster
lintr9949.34369893.050510058.4872305.6x slower
large (1546824 bytes, 106704 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity343.8745335.9537363.0020baseline
jarl393.3544385.9586410.66011.1x slower

Projects

Linting speed on real R packages (the tidyr and MASS source trees) relative to arity, on the same log-ratio axis.
Data table
tidyr (245685 bytes, 8774 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity23.475821.826927.5558baseline
jarl13.074311.910015.66571.8x faster
lintr8417.39678391.54078459.3213358.6x slower
MASS (214820 bytes, 5951 lines)
ToolMean (ms)Min (ms)Max (ms)Relative
arity27.624425.741330.8305baseline
jarl17.862416.162022.10381.5x faster
lintr8694.56978652.44718728.7700314.7x slower