Dragon

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.

BenchmarkDragonRustVerdict
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

  1. 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.
  2. Dicts (1.72× slower) — string-keyed hashmap. We trail Rust, Go and Java here; the hash + string-key path in DragonDict is the suspect, not the loop.
  3. 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.