Mica 5.0.0 Technical Portrait · Chapter 7 of 9 · reading guide
A young compiler making performance claims has to be careful, so this chapter leads with its method and its honesty before its numbers.
What these numbers are. Observations taken on the author’s two development machines — an Apple arm64 laptop and an AMD64 Threadripper workstation — reproducible from the project’s committed measurement scripts. They are not an official, audited benchmark suite, and they are not a claim that Mica beats GCC in general. They indicate where Mica currently stands.
The metric. The primary gate is retired-instruction count (Ir) — a
deterministic measure immune to run-to-run noise. Wall-clock time is reported as
an advisory second metric. Ratios below are Mica ÷ gcc -O2 unless stated; <
1.00× means Mica emits fewer instructions. The benchmarks are real: the Computer
Language Benchmarks Game kernels and a dedicated heap-allocation suite, among a
dozen micro-benchmarks.
◈ Result 1 — the heap costs non-allocating code nothing
The first thing to verify about a new heap is that it does not tax code that
doesn’t use it. It does not. A heap runtime call is emitted only in a function
that uses new, dispose, defer, or until. The three established compute
kernels allocate nothing — and after the entire memory subsystem was added, their
generated assembly contains zero heap calls, and their instruction counts
against gcc -O2 are identical to the pre-heap baseline, to the instruction.
The heap is purely additive. There is no per-function cost, and the deployment class (hosted vs fixed-arena) changes none of it — a scalar kernel’s assembly is byte-identical across classes.
◈ Result 2 — scalar kernels are competitive with gcc -O2
On the CLBG scalar kernels, against gcc -O2, by retired instructions:
| Kernel (Mica ÷ gcc -O2, Ir) | arm64 | amd64 |
|---|---|---|
| Mandelbrot | 0.98× | 0.94× |
| N-body | 1.33× | 1.42× |
| spectral-norm | 1.13× | 1.23× |
Two things are worth stating plainly. Mandelbrot runs in fewer instructions than
gcc -O2 on both architectures — a scalar kernel at or below parity, which for a
from-scratch backend a year into existence is a real result. On amd64, spectral-
norm reaches cycle parity (≈ 1.004× by cycle count) even where its instruction
count is higher. The other kernels sit close, within roughly 0.94×–1.42× — the
band the SSA backend (Chapter 5) was built to reach. Wall-clock
ratios track the same shape (arm64 ≈ 1.04–1.06×; amd64 ≈ 1.01–1.25×).
This is the honest headline: on straight-line numeric code, a single-developer
compiler is within a small constant factor of GCC at -O2, and ahead on at least
one kernel.
◈ Result 3 — on one allocation-bound workload, the region beats gcc -O2
This is the result worth the chapter. On an allocation-heavy benchmark —
repeated waves of small cells, written, read, and released — with the same
algorithm in Mica (per-cell and region variants) and in C compiled by gcc:
| Metric | arm64 | amd64 |
|---|---|---|
| region ÷ per-cell allocation (Ir) | 0.72× | 0.62× |
| region ÷ per-cell allocation (wall) | 0.88× | 0.76× |
| per-cell allocation ÷ gcc -O2 (Ir) | 1.71× | 1.29× |
| region ÷ gcc -O2 (Ir) | 1.22× | 0.80× |
The amd64 figure is the notable one. Mica’s compiler-scheduled region
allocator — bump-allocate within a per-owner arena, reclaim the whole region in
bulk at the owner’s exit (Chapter 3) — out-counts
gcc -O2 with glibc malloc/free on this allocation-bound workload, at 0.80×
its retired instructions.
The honesty that goes with it: on wall-clock, glibc’s very low absolute latency
keeps it ahead. The win is on the deterministic instruction-count metric, the one
immune to noise. But it is a genuine, reproducible win on a real industrial-shaped
workload — and it is not a hand-tuned arena the programmer wrote. It is the
allocator the compiler chose, automatically, from a lifetime it proved. The
programmer wrote until F; the speed came from the proof.
That is the deeper point: Mica’s safety and its speed are the same mechanism. Because the compiler proved the lifetime, it could schedule the allocator that serves it best. Proving lifetimes and scheduling allocators is one idea, not two.
◈ Result 4 — compile speed
A compiler that is slow to run is its own kind of failure. Mica’s lock-free phased concurrency (Chapter 6) keeps it fast even with the full SSA backend engaged:
- A 100,000-line program compiles, with full optimization, in about 5.5 seconds — down sharply over the 5.0.0 performance arc.
- A stress series of generated programs up to 100,000 lines, and a case that passes a 1 MB aggregate through the ABI, pin these numbers in the harness — so a regression in compile speed fails a test.
Because the parallel phases scale linearly with the number of source files, a larger project does not pay a super-linear compile-time penalty.
◈ How to read all of this
Mica is not faster than GCC, and this chapter does not claim it is. GCC at
-O2/-O3 carries decades of IPA, LTO, vectorization, and target tuning that a
year-old backend does not. What the numbers show is narrower and, in its way, more
interesting:
- On scalar numeric code, Mica is already within a small constant factor of
gcc -O2, and ahead on at least one kernel. - On an allocation-bound workload, the compiler-scheduled region wins on instruction count — because safety analysis and allocation strategy are the same engine.
- The heap is free for code that doesn’t use it.
How each of these stands against GCC 15 specifically — feature by feature — is the one-page summary.
Where to next
Numbers are only trustworthy if something keeps them honest. That something is the test harness — and it doubles as the best map of what the compiler can actually do.
→ Chapter 8 — Testing & Architecture · back to the reading guide