Benchmarks
Dragon vs Rust · best-of-3 · all -O2 · same machine
Rust is the yardstick, not the target. It is the fastest language with a comparable safety story, which makes it the honest place to measure our runtime against. Dragon's goal is C-class speed with a surface a Python developer can read; these numbers say how close we are and where we are not.
| Benchmark | Dragon | Rust | Verdict |
|---|---|---|---|
| Fibonacci (recursive, n=42) | 0.848s | 0.986s | parity (1.16×, within noise) |
| Mandelbrot (float, 1600², 100 iter) | 0.421s | 0.452s | parity (1.07×, within noise) |
| Sieve of Eratosthenes (1M) | 0.007s | 0.006s | tie (noise) |
| String concat (10k) | 0.003s | 0.003s | tie (noise) |
| Object creation (1M) | 0.002s | 0.003s | tie (noise) |
| Parallel sum (8×30M fork-join) | 0.174s | 0.149s | Dragon 1.17× slower |
| Dictionary / hashmap (3M str-key ops) | 1.144s | 0.666s | Dragon 1.72× slower |
| Binary trees (alloc/GC churn, depth 14) | 0.255s | 0.095s | Dragon 2.68× slower |
Where we stand
On compute-bound work Dragon runs at parity with rustc. Recursive integer math (fib) and tight float loops (mandelbrot) both land within run-to-run variance, in both directions: we have measured fib anywhere from 1.02× to 1.16× across snapshots, so the nominal lead is not a lead. Parity with a mature systems compiler is the real result. On fib we also beat Go and Java, and trail C/C++ by only ~12%, which is the number we actually care about.
The three sub-10 ms rows — sieve, string concat, object creation — are noise, not signal. They finish in 2–7 ms, dominated by process startup rather than the workload. Worth noting: object creation at 2 ms means the old GC-tracking overhead no longer shows up at this scale.
Three gaps we're closing
- Binary trees (2.68× slower) — the worst, and pure alloc/free churn, so it measures the refcount runtime, not codegen. Every node is two atomic ops under mutexes. The acyclic-skip-tracking / escape-analysis work is the fix; binary-trees is the canary that moves when it lands.
- Dicts (1.72× slower) — string-keyed hashmap. We trail Rust, Go and Java here; the hash + string-key path in
DragonDictis the suspect, not the loop. - Parallel sum (1.17× slower) — the closest gap. Green-thread fork-join carries a little more overhead than Rust's threads; we still beat Java and sit near Go.
Bottom line
Dragon is at parity with Rust on compute and behind it on allocation-heavy and hashmap work. That gap is the price of reference counting rather than a borrow checker: you get native speed without lifetimes, and you pay for it where allocation churn dominates. It is a deliberate trade, not one we are content with. Per our first commandment (speed is king), the refcount/alloc path is the highest-leverage target, and it's what we're working on next. These numbers are re-run and updated as the runtime improves.
