Overleaf's free plan now stops any compile after 10 seconds, and a lot of theses that used to build fine are on the wrong side of that line. The usual advice is to upgrade or to make the document smaller, but the length of the text is rarely what costs the time. Timing one real project, variant by variant, shows where it goes.
The project is a sample master's thesis: four chapters, natbib with a .bib file, a table of contents, two pgfplots charts and one TikZ diagram. It's compiled with Tectonic 0.16.9 on an M1 Mac, using the same command the LaTeX tab of the osFoundry desktop app runs:
let mut cmd = Command::new(executable); cmd.args(["-X", "compile", "--untrusted", "--outdir"]) .arg(&root) .current_dir(&root) .env("TECTONIC_UNTRUSTED_MODE", "1") .kill_on_drop(true); --untrusted turns off shell escape, which matters further down.
One compile is three TeX runs
The first thing the log shows is that "a compile" isn't one run:
note: Running TeX ... note: Running BibTeX on main.aux ... note: Rerunning TeX because bibtex was run ... note: Rerunning TeX because "main.aux" changed ... note: Running xdvipdfmx ... The first pass writes citation keys and section titles to main.aux. BibTeX turns the keys into a bibliography, the second pass typesets it, and that shifts page numbers, so a third pass fixes the table of contents and the references. latexmk and Overleaf run the same loop. Anything slow in the document is paid for three times.
Where the time goes
Each variant below was built twice with a warm package cache, timed with a small loop:
for d in full samples-100 csv-table no-figures; do ( cd "$d" start=$(python3 -c 'import time; print(time.time())') TECTONIC_UNTRUSTED_MODE=1 tectonic -X compile --untrusted main.tex > run.log 2>&1 python3 -c "import time; print('$d', round(time.time() - $start, 1), 's')" grep -c 'Running TeX\|Rerunning TeX' run.log ) done | Variant | Whole build | TeX passes |
|---|---|---|
Full thesis, plots at samples=500 and samples=300 | 14.4–15.4 s | 3 |
Same plots at samples=200 and samples=100 | 9.2–9.4 s | 3 |
Same plots at samples=100 and samples=60 | 7.8 s | 3 |
| Same curves read from CSV files, every point kept | 6.7–6.8 s | 3 |
No figures (each tikzpicture replaced by a box) | 5.5–5.9 s | 3 |
| Japanese version of the full thesis (xeCJK, Hiragino fonts) | 22.8 s | 3 |
Text, bibliography and table of contents together take under 6 seconds. The figures take the other 9, and nearly all of that is pgfplots computing the curves. A function plot like {40 + 35*exp(-((mod(x,24)-8)^2)/3) + ...} is evaluated point by point in TeX's own fixed-point arithmetic, on every one of the three passes. Drawing the same 500 points from a file costs about a second in total.
Cutting samples is the obvious lever, and it does work, but it shows. At 100 samples the commuter peaks in the weekly chart turn into corners. At 200 the build drops just under 10 seconds and the curves look nearly the same, though some of the small wiggles go. Reading the points from a CSV keeps every one of them and is faster than either:
% before: computed on every pass \addplot[domain=0:168, samples=500, thick, blue] {41 + 33*exp(-((mod(x,24)-8)^2)/3.2) + ...}; % after: the same 500 points, written once by the script that made the data \addplot[thick, blue] table[x=hour, y=model, col sep=comma]{week.csv}; For a thesis this is usually the honest version anyway, since the plotted values came out of Python or R in the first place.
The Japanese build is the other measurable cost: with identical figures it's about 50% slower than the English one, and the only differences are the Japanese text, xeCJK and the system fonts it loads. On a cold machine there's one more: the first Tectonic run on an empty cache downloaded 427 package and font files, 46 MB, before typesetting anything.
The usual fix needs shell escape
Overleaf's help page on compile timeouts suggests externalising TikZ pictures, so each one is built once and reused as a PDF. The tikz external library does that by having TeX start a second TeX process per figure, which is a shell command. Under --untrusted that is refused:
warning: chapters/method.tex:20: runsystem(xelatex -halt-on-error -interaction=batchmode -jobname "main-figure0" ...)...disabled. error: chapters/method.tex:20: Package tikz Error: Sorry, the system call 'xelatex ...' did NOT result in a usable output file 'main-figure0' That's on purpose. Shell escape lets a .tex file run any command, which is fine for your own thesis and not for a ZIP someone sent you. Without it, the same effect takes two steps by hand: put each figure in its own standalone document, compile it once, and \includegraphics the PDF in the thesis.
Finding the error in a multi-file project
The last slow part is human. TeX reports an error in whichever \input file it is reading, and Tectonic prints it as error: chapters/results.tex:50: Undefined control sequence. The app's build log turns that into a clickable line with one regular expression, and falls back to the classic TeX format, where the error starts with ! and the line number follows a few lines later as l.50:
const tectonic = /^error:\s+(.+?):(\d+):\s*(.+)$/.exec(line) if (tectonic) return [{ file: tectonic[1].replace(/^\.\//, ''), line: Number(tectonic[2]), message: tectonic[3] }] if (!line.startsWith('! ')) return [] const next = lines.slice(index + 1, index + 5).find((part) => /^l\.\d+/.test(part.trim())) Compiled on your own machine, the full thesis never meets a 10-second limit. On Overleaf's free plan, plotting from data files instead of formulas is what brings this one back under. The desktop app that ran these builds is free from the osFoundry download page.


