Fast because it is native
Templates compile to bytecode and run on a VM written in Rust, cached per template, so a cold request costs the same as a warm one. There is no host VM to boot, no bytecode to warm and no garbage collector to tune. The whole engine, under load, fits in about sixty megabytes.
“Hello World”, one page, one machine
A single .cfm page in
--production mode against a warmed Lucee 7 on the
same machine (Apple M-series), same page, Apache Bench, eight-second runs. Requests per
second, higher is better.
| Concurrency | RustCFML | Lucee 7.0 | Gap | RustCFML keep-alive | Lucee keep-alive |
|---|---|---|---|---|---|
-c 1 |
1,908 | 1,205 | 3,118 | 1,625 | |
-c 10 |
5,466 | 2,648 | 21,716 | 8,125 | |
-c 50 |
6,983 | 3,503 | 25,833 | 8,085 | |
-c 100 |
7,528 | 3,107 | 25,855 | 7,419 |
Keep-alive is where the gap widens. Both engines improve with persistent connections, but RustCFML keeps scaling: at one hundred concurrent clients it holds around 25,800 requests per second while Lucee falls back to roughly 7,400. If your traffic arrives through a reverse proxy with an upstream keep-alive pool, this is the column that describes your production traffic.
| RustCFML | Lucee 7.0 | |
|---|---|---|
| Memory (RSS, under load) | ~60 MB | ~560 MB |
| Time to first request | instant | ~15 s |
| Artifact | 1 binary | JVM + runtime |
| Engine | Total | Speedup |
|---|---|---|
| RustCFML | 1,116 | baseline |
| BoxLang 1.14 | 1,368 | 1.23× |
| Lucee 7.0.4 | 7,884 | 7.1× |
Built for performance
Compile, then run
Tags are preprocessed to CFScript, then lexed, parsed and compiled to stack-based bytecode. The bytecode is cached per template, so the second request for a page runs no compiler at all.
No VM under the VM
There is no JVM, so no warm-up, no garbage-collection pauses and no container startup. The process is the runtime, and it is tens of megabytes.
Warm caches in production mode
--production caches the Application.cfc resolution, URL-to-file resolution and bytecode permanently instead of checking modification times per request. Worth 3–4×.
Parallel SQL in Rust
Query-of-queries is a real SQL engine in crates/cfml-qoq, parallelised across cores with rayon, not an embedded HSQLDB doing string work.
Performance testing
They are the project’s own, published in the README, on one Apple M-series machine, on a page that does almost nothing. That makes them a good comparison of engine overhead and a poor predictor of your application, where the database is usually the floor. Treat them as a reason to benchmark your own workload, and nothing more.
- Page: a “Hello World”
.cfm, served from a directory with anApplication.cfc - RustCFML:
--serve --production, current release - Lucee: version 7.0, warmed before the run; the QoQ table uses 7.0.4
- Tool: Apache Bench, eight-second runs, median of five for the QoQ suite
- Shipped binaries are built with profile-guided optimisation (fat LTO plus profile data); the
cargo build --releaseyou run yourself is not, and will be slower - Query-of-queries: the public
cfml-qoq-perf-testssuite, 10 SELECTs over 1M in-memory rows
The QoQ figures were published against an earlier RustCFML (v0.112) and have not been restated since. The full write-up lives in docs/performance.md.
# 1. start the engine the way you would ship it
rustcfml --serve ./webroot --production &
# 2. warm it, then measure
ab -n 2000 -c 10 http://127.0.0.1:8500/index.cfm
ab -n 5000 -c 50 -k http://127.0.0.1:8500/index.cfm
# 3. watch where the time actually goes
rustcfml --serve ./webroot --production --profile=30
# 4. compare a single template without the server at all
rustcfml ./webroot/index.cfm
What --production actually changes
Development mode checks that files have not changed on every request so edits are
picked up instantly. Production mode caches three lookups permanently (the
Application.cfc resolution, URL-to-file resolution and
compiled bytecode) and drops the per-request readdir.
You reload by restarting. It is also honoured as
RUSTCFML_PRODUCTION=1.
Detail in Deployment.
Small switches with real effects
upstream rustcfml {
server unix:/run/rustcfml.sock;
keepalive 32;
}
Benchmark it on your own workload
Grab the binary, point it at a real page and measure. If your numbers are worse than these, open an issue with the template. That is how the engine got faster.