Why TeX is Slow and How We Rebuilt It in Pure Rust
If you write papers in academia or technical industry, you know the feeling: you edit one sentence in your LaTeX document, press save, and wait 3 to 15 seconds for latexmk or pdflatex to recompile. In an era where modern compilers build hundreds of thousands of lines of code in sub-second times, why is compiling a 10-page PDF so painfully slow?
For the past year, I built ratex—an ultra-fast, self-contained, pure-Rust TeX engine and build toolchain designed as a ground-up drop-in replacement for pdflatex and latexmk. On incremental edits, ratex rebuilds complex documents in 0.8 to 8.2 milliseconds—over 50× faster than standard TeX Live.
Here is what makes legacy TeX slow, and how we re-architected it in Rust.
1. The 40-Year Bottleneck: Why Legacy TeX is Slow
Standard TeX implementations (such as Web2C / pdfTeX / XeTeX) date back decades. While Donald Knuth's typesetting algorithms are legendary for mathematical beauty, the surrounding runtime model suffers from four major architectural bottlenecks:
- Filesystem Thrashing (kpathsea): Whenever you invoke
\usepackage{amsmath}, TeX Live searches through massive directory trees containing over 100,000 files using thekpathsealibrary. On modern operating systems, thousands ofstat()andopen()syscalls burn hundreds of milliseconds before a single letter is typeset. - The Subprocess Carousel: A standard build does not just run TeX. To resolve citations, cross-references, and table of contents, a Perl script (
latexmk) orchestrates multiple subprocess invocations: runningpdflatex, spawningbibtex, re-runningpdflatex, and repeating until convergence. Each invocation pays the full initialization and process creation penalty. - No Incremental State Validation: If you edit a typo in section 3, legacy engines discard everything and re-parse the entire document, packages, macros, and fonts from disk.
- Memory Unsoundness and Segfaults: Classic TeX engines use fixed static arrays in C with manual memory pointers. When memory limits are exceeded or tricky macro packages clash, you get confusing error dumps or hard crashes.
2. How ratex Rebuilt TeX from Scratch in Rust
To eliminate these bottlenecks without sacrificing Knuth's exact mathematical typesetting rules, ratex was engineered around three principles:
A. 100% In-Memory Package Resolution
Instead of requiring a multi-gigabyte TeX Live installation and traversing disk hierarchies, ratex embeds pre-compressed format assets and over 24,000 standard TeX packages directly into the binary. When a document loads a package, it resolves from an in-memory index in less than 50 microseconds. Zero disk lookups, zero missing package dialogs.
B. Unified Single-Pass Convergence
Rather than executing external Perl wrappers and separate command-line binaries, ratex embeds the TeX engine, package resolver, native BibTeX interpreter, and dependency-tracking driver in one process. It analyzes auxiliary citations and references in-memory, converging multi-pass dependencies in a single lifecycle.
C. Cryptographic Artifact Caching
ratex maintains a lightweight dependency graph with BLAKE3/xxHash state hashing. If only a single paragraph changes, font metrics, macro definitions, and unchanged auxiliary streams are reused immediately, reducing warm incremental rebuilds to under 10 milliseconds.
3. Real-World Performance: 3,000 arXiv Papers
We verified ratex against 3,000 real-world arXiv research papers spanning mathematics, physics, and computer science. The benchmarks speak for themselves:
| Workload | ratex | TeX Live (pdflatex + latexmk) | Speedup |
|---|---|---|---|
| Incremental Rebuild (Warm) | 0.8 – 8.2 ms | 40 – 60 ms | 10× – 70× faster |
| Short Papers (1–3 pages) | 12 – 45 ms | 450 – 900 ms | 20× – 35× faster |
| Long Manuscripts (15–40 pages) | 180 – 650 ms | 3,200 – 7,800 ms | 10× – 18× faster |
| Heavy Math & Citations | 240 – 780 ms | 4,500 – 11,200 ms | 14× – 19× faster |
"Clean compiles across arXiv: ratex cleanly compiled 2,620 papers vs 2,613 for TeX Live, with a 96.39% mean visual pixel parity score."
4. Compiler-Grade Diagnostics (No More Cryptic `?` Prompts)
Every LaTeX user has experienced the dread of Knuth's infamous ? prompt halting a build with a cryptic message buried 800 lines deep in a .log file:
! Undefined control sequence.
l.14 \textbld
{Empirical Results}
?
If you don't know what to press, typing the wrong character can dump 50 cascading phantom errors or hang your editor and automated CI pipeline indefinitely.
Because ratex is engineered like a modern language compiler, it replaces this 1980s terminal prompt with beautiful, rustc-quality visual diagnostics:
error[E0042]: undefined command `\textbld`
--> document.tex:14:5
|
14 | \textbld{Empirical Results}
| ^^^^^^^^ help: did you mean `\textbf`?
= note: macro `\textbld` is not defined in any loaded package
Key diagnostic upgrades in ratex:
- Exact Source Code Spans: Shows the physical file, line, and column with source code context and squiggly underlines.
- Fuzzy Spelling Suggestions: Analyzes Levenshtein distance against all loaded macros to suggest typos (e.g.
\centr→\center). - Unclosed Environment Tracking: When you forget an
\end{equation}, it points to the exact opening tag rather than failing at the end of the file. - Zero Interactive Hangs: Never pauses with a modal
?prompt in non-interactive terminals or CI pipelines.
5. Installing and Getting Started
ratex is fully open source under the MIT and Apache 2.0 licenses. Standalone native packages are available for Linux, macOS, and Windows:
# Arch Linux (AUR)
yay -S ratex-bin
# macOS (Homebrew or Native .pkg)
# Download .pkg installer from GitHub Releases
# Windows
# Download Inno Setup installer (.exe) from GitHub Releases
# Ubuntu / Debian (.deb)
sudo apt install ./ratex_0.1.0_amd64.deb
To compile any paper with automatic BibTeX convergence:
ratex paper.tex
You can drop it directly into VS Code (LaTeX Workshop) by setting "latex-workshop.latex.tools": [{"name": "ratex", "command": "ratex", "args": ["-pdf", "%DOC%"]}].
Help Us Test Your Papers & File Issues
Have a tricky paper, custom style file, or obscure macro package that doesn't compile? Please open an issue on GitHub! We actively welcome minimal reproduction snippets and bug reports at github.com/leoliu0/ratex/issues.
Check out the project on GitHub: github.com/leoliu0/ratex. If you find it useful for your own writing, starring the repo helps others discover it!