One binary, no runtime, files linted in parallel
Fast
Speed decides where linting fits in your day. A checker that takes an afternoon belongs in a nightly job, where you hear about a problem long after you stopped thinking about it. One that finishes while you are still reading the diff can sit in your editor, your pre-commit hook, and your pipeline at once—and that is a different tool, even when the rules are identical.
Install ValeFour real documentation sets
Four projects, four markup formats, each linted with the configuration it ships—their rules, their overrides, unmodified. Pick one to see what a full run costs it.
- Pages
- 2,826
- Prose
- 31.3 MB
- Rules
- 82
- Format
- Markdown
- Commit
- 57f859d1
Corpus size, relative to the largest here.
The largest corpus here and the most rules. Excludes one 4.5 MB generated GraphQL reference; including it the run takes 45 s.
Pages per second of wall clock over the whole corpus. Files run several at a time, so this is throughput, not the time a single page takes.
Format moves this number more than corpus size does. Markdown Vale parses itself, at about 7 ms a page. reStructuredText and AsciiDoc go first through the tools that define them—Docutils and Asciidoctor—and Vale holds those open for the whole run instead of starting one per page, which is most of the difference between 53 ms and 128 ms a page here and what those conversions used to cost. Rule count matters second: Docker runs fourteen rules, GitLab eighty-two.
Every rule ran against every page—no sampling, no incremental cache. Each project links to its own docs and config above, so any of these is reproducible with one command.
Every rule, without the noise
Vale has three levels, and each project decides which findings sit at which. That decision is what makes it practical to switch every rule on—the same selection above drives this chart.
The shapes differ because the policies do. GitLab reserves error for a single thing across 2,826 pages and lets the rest inform; Docker puts most of its findings
there. Neither is wrong—the level is set per rule, so the decision about what stops a build gets
made once, in the rule, instead of being argued over in review.
What another style guide costs you
Speed in the abstract is not the useful question. The useful question is what it costs to turn on the rules you actually want.
Going from one style guide to five adds 90 ms. Most of even that is the one-time cost of loading and compiling the rules, paid on every CLI invocation—which is why the language server, which pays it once and then keeps the styles in memory, can re-lint as you type.
Nothing runs but Vale
Nothing to install alongside it
One statically linked executable. No interpreter starts, no module graph resolves, no virtual environment activates—and nothing is uploaded, so nothing waits on a response.
Every core you have
The GitLab run spent close to four cores’ worth of CPU throughout: files are linted several at a time, and results stream back as they land.
Where that speed goes
While you write
The language server loads your styles once and keeps them, so re-linting the buffer costs a fraction of a cold run. Alerts reach your editor with any fixes a rule defines attached.
Editor integration →Before you commit
A typical repository in well under a second is fast enough to sit in a pre-commit hook without becoming the reason people reach for --no-verify.
pre-commit →In CI
A single binary to fetch and a machine-readable report to publish—no toolchain to provision on the runner first.
GitHub Actions →Check it yourself
Every figure here comes from a public repository and an unmodified configuration. These are the exact commands for the project selected above—and then run it on your own docs, which is the number that actually matters.
How these were measured
Vale v3.17.0, built from commit 5f071ef5, on an
Apple M1 with 8 cores, macOS 15.7. The GitLab figures use commit 57f859d1 and the .vale.ini in that repository, unmodified. The per-page figures use this site's documentation with Vale, Microsoft, Google, write-good, proselint at MinAlertLevel = suggestion. Your hardware and your prose will give you different numbers; the commands above are the
ones that tell you which.