Chisel's perf
While on a visit to Melbourne to be with my daughter, I finally got around to including a few basic templates for Chisel, and built releases for linux, macos, and windows. And I got Claude to tell me how Chisel fares against the other static site generators.
Chisel is about 3× and 18× faster than Zola and Hugo respectively in rendering 100,000 (synthetic) posts — run based on 2 vCPUs.
| Generator | 1k posts (ms) | 5k posts (ms) | 100k posts (ms) |
|---|---|---|---|
| Chisel (in Rust) | 56 | 751 | 3,805 |
| Zola (in Rust) | 104 | 868 | 11,533 |
| Hugo (in Go) | 762 | 3,569 | 69,827 |
This is pure naval-gazing for me, as they are different beasts packed with features. Chisel is a consciously designed tool with general purpose machinery deliberately excluded from it. In this regard, my needs have never wavered since 2012, viz.,
- To write and present code, math, and notes effortlessly
- Enable login-less cryptographically-secure publishing
- Ensure portability of notes together with track changes
- Maintain bare bones, readable, safe, and low-dependency code base
- Use a decent template engine to be able to do more with less code
Zola and Hugo probably pay performance penalties for the number of moving parts and features they offer.
| Area | Chisel | Zola | Hugo |
|---|---|---|---|
| Content model | Flat notes only: Title / date / body in one .md file, one content type, one collection |
Sections + pages, arbitrary nesting, taxonomies, multilingual | Sections, page bundles, taxonomies, multilingual, content types |
| Front matter | None — first two lines of the file are the schema | TOML/YAML front matter, arbitrary keys | TOML/YAML/JSON front matter, arbitrary keys |
| Templating | minijinja (Jinja2-compatible), hand-rolled {% markdown %} preprocessing, 5 custom filters (markdown, age, striptags, wordcount, truncate) |
Tera (Jinja2-like), large built-in filter/function library | Go templates + text/template, large built-in function library, shortcodes |
| Markdown engine | comrak (CommonMark) — tables, footnotes, strikethrough, smart punctuation; raw HTML stripped by design | pulldown-cmark — similar extension set, syntax highlighting, shortcodes, internal links | Goldmark — extensions, syntax highlighting, render hooks |
| Taxonomies/tags | None | Full taxonomy system (categories, tags, custom) | Full taxonomy system |
| Pagination | Built-in | Built-in | Built-in |
| Multilingual/i18n | None | Built-in | Built-in |
| Asset pipeline | None — CSS is a static file copied by hand | Sass compilation, asset processing | Sass/PostCSS, image processing, JS bundling (esbuild) |
| Shortcodes/embeds | None | Built-in shortcodes | Built-in shortcodes |
| RSS/feeds | One hand-written JSON feed template (last N posts) | Built-in Atom/RSS | Built-in RSS |
| Live server / dev preview | None — author’s workflow is a Makefile + entr watching *.md and rsyncing to a Raspberry Pi for live preview |
Built-in zola serve with live reload |
Built-in hugo server with live reload |
| Config surface | Five consts hardcoded in main.rs (paths, feed count, date formats) — no config file, edit-and-recompile |
config.toml, extensive |
hugo.yaml/toml/json, extensive |
| Extensibility | None — no plugin system; changing behavior means editing the Rust source | Limited (Tera functions/filters in some setups) | Modules, themes, extensive plugin-like ecosystem |
| Parallelism | rayon-parallel note parsing (explicit design goal) | Mostly single-threaded per-page render | Goroutine-parallel page builds |
| Codebase size / dependency count | ~587 lines, 7 crates | Large Rust codebase, many crates | Large Go codebase, many modules |
| Output | HTML pages + one JSON feed | Full static site (HTML, assets, sitemap, RSS, search index option) | Full static site (HTML, assets, sitemap, RSS) |
| Themes | None (author’s own hand-written templates only) | Theme ecosystem | Large theme ecosystem |