Mica 7.5.0 is a release with no new sentence in the language, and it is the most consequential release since the AI arc began. Two releases in a row grew Mica toward training a GPT in the language’s own words; this one slows down and does the careful work those features were resting on. Its three subjects are performance, efficiency, and the compiler’s own robustness, and its rule is that nothing is claimed that was not measured: every number below names the machine it was taken on and the date, every defect names the instrument that found it, and every guarantee names the gate that keeps it true.
Everything below is shipped and gated behavior. The benchmark tables are produced by one documented run that anyone can repeat; the sweep that found forty-one defects is a corpus of programs the release gate compiles; and the technical report on the memory model is written against the compiler as it ships.
The release at a glance
| Subject | What changed |
|---|---|
| Performance, measured | the Benchmarks Game kernels run against their C twins on named, rentable machines, by wall clock, both compilers at O2, every Mica check on; eight of ten kernels within 1.97x of gcc -O2 on ARM64 and within 1.49x on AMD64, the regex kernel ahead of C’s engine on ARM64 |
| A price at every merge | every kernel and every standard-library operation runs under callgrind at every merge and must stay within one percent of its pinned instruction count |
| Checked builds on the optimizing lowering | O2,checked keeps every guard on the release code; NBody at O2,checked runs about a third of the instructions the previous checked build ran |
| Memory brought down | strings reclaimed when superseded, a dying value moved instead of copied, an allocation that is a call: RegexRedux 150.9 → 40.1 MB, a million map insertions 119 → 63 MB, a tokenizer over 40,000 merge rules 35.5 s → 0.6 s |
| The first technical report | Technical Report 1, the memory model: where every byte lives, what the compiler proves, what the checked build catches |
| The regex engine rebuilt | linear over the caller’s text, a walk over the matches, \p{L}-class patterns, lookaround refused by name |
| Forty-one defects, by family | an adversarial sweep of 283 programs written to be wrongly accepted; every finding a refusal that names its rule |
| Wrong code and hangs, by instrument | callee-saved registers restored from below the stack pointer at release, found by valgrind; a lost wakeup in the multicore scheduler, found by the emulated leg of the gate |
| Profiling, with the tools you already use | --optimize O2,profiling keeps the line table and the inlining records on the release build’s exact code, so perf, valgrind’s callgrind, gdb and hyperfine attribute an optimized Mica binary to its source lines and name inlined callees as their own frames; the profiling walk runs all four on one program |
| The toolchain | --static, --strip, O0/O1/O2, the utf unit |
| Three spellings change | the archives are mica-<component>-<arch>.a, hosted is hosted-heap, a bare checked selects the release profile |
Performance, on machines anyone can rent
A performance number without a machine, a date and a method is a marketing claim, so 7.5 publishes all three with every number. Ten kernels of the Computer Language Benchmarks Game are implemented twice, in Mica and in C with the identical algorithm and loop structure, and run on two named Google Cloud machine types, an Ampere Altra and an EPYC Milan, with both compilers at O2 and every Mica safety check on: bounds, division guards, the memory-safety floor. Every Mica binary’s output is byte-identical to its C reference on every run, or the run is refused.
The metric that matters is wall clock. Measured on 10 September 2026 with the
7.5 compiler, eight of the ten kernels stand between 1.01x and 1.97x of
gcc -O2 on ARM64 and between 1.05x and 1.49x on AMD64; the regular-expression
kernel runs at 0.69x on ARM64, ahead of C’s engine, and at 1.37x on AMD64. The
two kernels set beside that band measure an allocator and a regular-expression
engine respectively, and the tables name the procedures their time goes to.
Peak memory is measured
beside time and held within a per-kernel budget, and the tables on
the facts page carry the machine types, the zone, the compilers'
versions and the date, so a reader re-measures rather than trusts.
Between releases the number cannot drift. Every kernel of both benchmark suites runs under callgrind on every merge and must stay within one percent of its pinned instruction count; a change that makes one kernel slower by more than that fails the gate with the kernel named. A slower compiler can no longer arrive by accident, and a faster one is recorded the day it lands.
Some of what the release bought, read from the same instrument: a counting
loop compiles to the same six instructions on ARM64 that a hand-written loop
takes; a temporary the optimizer retired no longer takes a stack slot the
prologue zeroes; the string scans behind Pos, Contains, Split and
Replace hunt a separator’s first byte the way the platform’s own library
does; a view passed along is no longer copied on the way.
Checked builds on the optimizing lowering
Until 7.4, a checked build was a debug build with guards. From 7.5 the guards
ride the optimizing lowering: --optimize O2,checked builds the register-homed,
inlined code the release build runs and keeps every guard on it — array
bounds, integer overflow, a cast outside its domain, a non-finite floating
result, a pointer into a region already drained. The guards themselves shrank
to a few instructions each: a non-finite check is one subtraction and one flag
test on the hot path, and the report it would print lives in cold text.
Measured on NBody, the O2,checked build runs about a third of the
instructions the previous checked build ran. A checked build is now something
to ship a test fleet with, not only something to debug under.
mica --compile --link --optimize O2,checked --platform linux,arm64,utf-32 \
--source Program.mica --build outEfficiency: memory brought down, and stated
Three changes to what a program holds, each measured on the program that
exposed it. A string is reclaimed the moment it is superseded, so a loop that
builds a new string each round holds one, not all of them: RegexRedux at five
million bases went from 150.9 MB resident to 40.1 MB. A value whose source dies
at the end of its scope is moved into its destination instead of copied: a
million map insertions went from 119 MB peak to 63 MB. And an allocation is a
call, not a walk: the runtime kept a registry of every cell ever allocated and
walked it on each new, which made allocation quadratic in the number of live
cells; a tokenizer parsing 40,000 merge rules went from 35.5 seconds to 0.6.
The benchmark tables now carry a memory column beside time, held within a
budget per kernel, so a regression in what a program holds fails the same gate
a regression in speed does.
The model behind these numbers is written down. Technical Report 1: Memory management in Mica states where every byte of a program lives, which construct reclaims it, what the compiler proves at compile time, and what the checked build catches at run time — regions, ownership and the value model, for readers who know what a stack and a heap are and have not studied compilers. One promise the first edition made in the future tense is kept in this release: a pointer into a region that has already been drained is reported at its line by the checked build, with the guard reading the cell’s header ahead of the payload.
The standard library ships at O2 — the Mica-written units were built below the
level their own C neighbours were, and correcting that found two real defects
in the optimizer that no build had exercised, both fixed. And a new unit,
utf, carries text to interchange bytes and back: encode, validate, strict and
lossy decode, and a cursor that decodes a chunked stream without losing a code
point cut by a boundary, every failure on the language’s own channel as a
UnicodeError. Transcoding text walks it.
The regular-expression engine, rebuilt at its root
A loop over Find was quadratic, and the reason was not the matcher: the
engine copied the subject into its own scratch on every call. That road is
gone. A compiled pattern is an immutable value; the match state is a cursor the
caller holds; the engine matches over the caller’s text without copying it;
and a walk over the matches is linear however many it answers. The
general-category classes \p{L}, \p{N} and their family are admitted,
spelled as raw regex literals so the backslash is the pattern’s own; lookaround
is refused by name, because the engine matches in linear time by construction
and lookaround is what would break that. On a 32,000-rune text under utf-8 the
Find loop went from 472 ms to 39 ms.
program Words;
imp
WriteLn : std;
Compile, MatchStart, Matching, NextMatch : regex;
Regex, RegexError, Match, MatchCursor : regex;
var
r : Regex;
e : RegexError;
c : MatchCursor;
m : Match;
t : string;
n : int64;
begin
t := "Mica 7.5 measures quality, and quality counts";
r := Compile(0r"\p{L}+") on fail e do leave;
c := MatchStart(address r, t);
n := 0;
while Matching(address c) do begin
m := NextMatch(address r, t, address c);
if m.Found then
n := n + 1;
end;
WriteLn("%lld words", n);
end.6 wordsThe walk reads the caller’s own string at every step; nothing is copied, no window is materialized, and the cursor is a value the caller owns — two walks over one pattern are two cursors.
Robustness: found by a sweep, by instruments, and by the compiler’s own gates
Forty-one defects, fixed by family
The release ran an adversarial sweep against the compiler: 283 programs, each written to be wrongly accepted, aimed at the memory model, the borrow rules, the failure channel and the task discipline. Forty-one were accepted when they should have been refused. Each was root-caused, and the findings closed as families rather than one by one — an address stored where it outlives the storage a call reclaims, a launder of a borrowed pointer through a plainly declared local, a dynamic array grown inside the loop that walks it, a stream variable held past its producer’s activation, a dispose of a part of a cell the pointer only lends. Every one is now a refusal that names its rule and the lawful road; every one is a case in the corpus, so it stays refused.
Wrong code and hangs, found by instruments
Two classes of defect that no test expectation catches were found by running instruments over ordinary programs, which is the release’s own lesson about itself. A release build restored callee-saved registers from below the stack pointer in its epilogue — correct only until a signal handler ran on that stack — found by valgrind reporting fourteen thousand reads below the stack pointer on a program that printed the right answer; fixed on both backends. The multicore scheduler could lose a wakeup at a waiting point, a hang with no deadline — found by the emulated leg of the release gate, reproduced with a C driver under the emulator, fixed in the protocol’s own idiom with two siblings beside it. The loop optimizer crashed on an empty loop body; the constant folder refused at O2 a program it accepted at O0; an element access through a pointer hop and a bit-field store through a pointer crashed the code generator; an allocation’s reserve count was skipped by the analyzer’s passes; a dynamic array allocated through a pointer was homed in the wrong activation; an exported record alias crossed a library contract twice. Each has a case.
The compiler’s own gates
Mica’s compiler runs two internal quality gates on every compile of every test program, ahead of code generation: one over the analyzed program, one over the intermediate representation. In 7.5 they were audited against the compiler’s own code — every contract the code generator and the two backends demand is now stated by the gates first, so an internal fault is reported at the source line with the contract named rather than as a crash deep inside emission. The audit’s first run found a latent inconsistency the emitter had never met and fixed it the same day.
Around those gates, the release gate grew: valgrind over the heap, obligation and string cases on both architectures; the multicore package gate’s 296 legs; the price gate above; the harness’s own tests; the compiler’s package dependency graph pinned; position-independent and non-PIE builds and shared objects in the harness; every remark inventoried across the corpus so the programs users copy pass the compiler’s own review; and every Mica code block on this website compiled by the released compiler. The corpus stands at 13,033 runs on both architectures, every one green at the cut.
The first technical report
Everything above is foundation: the performance and efficiency work a language needs under it before what is built on top can be trusted, measured and stated. One thing stands on that foundation in this release, a new kind of document for Mica.
Technical Report 1 states the memory model whole: regions, ownership and the value model, where every byte lives, what the compiler proves and what the checked build catches. It is written for programmers and students, structured like a paper, and true of the compiler at the commit it names.
The toolchain
--static. A program links wholly statically and runs on a machine with no libc — the road to a container image builtFROM scratchthat holds one file.--stripbeside it for the shipping shape; without it every function keeps its flat name for profilers and debuggers, and every tier carries call-frame information, soperfunwinds a release binary.O0,O1,O2andprofiling. The level spellings stand besidedebugandrelease.profilingjoins any set —O2,profiling— and keeps the line table, the subprogram entries and the inlining records while the code stays the release build’s to the byte. A Mica binary is an ordinary ELF executable with DWARF 5 debug information and call-frame information at every tier, which is what the profilers and debuggers written for C read:perfsamples and unwinds it, valgrind’s callgrind counts its instructions per source line, gdb steps it and names an inlined callee as its own frame, hyperfine times it. Nothing Mica-specific is installed or configured; Profiling a Mica program walks those four on one program, and the container ships them installed.- Two more remarks. Under
--remarks, a regexFindstanding inside a loop under utf-8 and aPartwindow formed from a match’s rune position inside a loop each name the linear road. - The GPU probe, scripted whole. The device floor’s kernels are held bitwise against a serial reference in 89 comparisons at four PTX targets on one card, and the four checks the release runs on real hardware are four scripts that refuse an unreachable host by name. The device work itself — Mica generating GPU kernels for suitable expressions — is 7.6’s headline.
Three spellings change
Each is refused by name with the new spelling in the message, so the fix is never a search; the announcement states each one and what to do.
| Before 7.5 | From 7.5 |
|---|---|
libmicadragon-rt[-fixedarena][-mc]-<arch>.a, libmicadragon-<arch>.a | mica-dragon-rt[-fixedarena][-mc]-<arch>.a, mica-dragon-<arch>.a — mica-stdlib-<arch>.a is unchanged |
--memory-class hosted | --memory-class hosted-heap |
--optimize checked meant debug,checked, and release,checked silently dropped its guards | checked is a flag beside either profile: a bare checked means release,checked, debug,checked keeps every variable observable at the trap, and release,checked keeps every guard |
A program that lets the compiler find its archives, never names the memory class, and spells its optimization profile in full notices nothing.
Shipped alongside
The user container carries the benchmark suites with their wall-clock, memory and per-procedure attribution tables, the profiling tools installed, and the release’s examples; the learn area carries the profiling walk and the transcoding walk; Technical Reports 1 and 2 are published; VS Code extension 4.3.0 accompanies the release with this compiler’s language server. The next release, 7.5.1, follows directly with the plain-programming surface — environment variables, command-line arguments, a flags unit, process spawn — and the editor’s profile and export viewers; 7.6 is the GPU release.
Getting it
The packages are on the download page for amd64 and arm64;
the container image micalang/mica:7.5.0 follows on Docker Hub. The
facts page states where benchmarks and tests stand as of this
release, and every number on it is generated from the repository rather than
typed.