We built this for ourselves, and it turned out to be the thing we most wanted
to hand to anyone else working with Mica. So it is in the
starter repository as of today,
under devkit/, and one git clone away.
The short version: when the work wants a bigger machine than the one in front of you — many cores for a long build, the other processor architecture, a region closer to where you are — one command creates it, installs everything, and opens your editor on it. When you are finished, one command takes it away and the billing stops.
git clone https://gitlab.com/mica-lang/mica-container.git
cd mica-container
devkit/mica-devboxWhy we wrote it
Mica’s own development is not comfortable on a single machine. The compiler targets two architectures and the test suite exercises both, so a machine that can only test one tests half of it without saying which half. The benchmarks want silicon that nobody else is using at the same moment. Some questions want thirty-two cores for an hour and nothing for the rest of the week.
Renting exactly that, for exactly that hour, is what a cloud is for. What the cloud is not good at is being simple: a machine has a size with a name nobody remembers, in a region with a different name on each vendor, behind quotas that are invisible until they refuse you, and it keeps billing after you have forgotten it exists.
So the devkit is three commands over those problems.
mica-provision | installs toolchains by name — Go, GCC, LLVM, QEMU, Python, Docker, the measurement tools, the compiler |
mica-cloud | creates a machine on Azure or Google Cloud with all of that on it, and removes it entirely |
mica-measure | the numbers a release publishes: Mica against gcc -O2, and how much Mica the test suite compiles |
mica-devbox is one command over all three, for the case that turned out to be
the common one: give me a machine to work on, and open it.
Setting up a machine you already have
The provisioning half is useful on its own, and needs no cloud at all. It installs the same toolchains on a laptop, a container, or a bare-metal box:
devkit/mica-provision mica samples # the compiler and the examples
devkit/mica-provision go gcc bench # or name what you want
devkit/mica-provision all # everythingEach feature comes from wherever the current version actually lives — Go and Docker from their own publishers, LLVM from the project’s own repository, and the rest from the distribution, because a package the distribution maintains is the one that still works after an upgrade. Running it twice is safe: every feature checks before it installs.
Saying where in words
A machine near Amsterdam is called westeurope on one cloud and europe-west4
on the other. Nobody outside those two companies remembers that, and a
developer in Seoul should not have to look it up to avoid being handed a
machine in Ireland. So a place can be said in ordinary words:
devkit/mica-devbox --region japan
devkit/mica-cloud up my-box --region us-west
devkit/mica-cloud regions # every name, and what it means on both cloudsus · us-east · us-west · us-central · canada · brazil · europe ·
eu-north · uk · germany · france · asia · singapore · japan ·
korea · india · taiwan · hongkong · australia · middle-east ·
africa
An exact region name still works and is passed through untouched, so this only adds ways to say things.
Mainland China is the one place we cannot answer this way, and the tool says so rather than quietly placing you elsewhere. Microsoft serves it from a separate cloud with separate accounts and endpoints, and Google has no mainland region at all. Whether Hong Kong, Taiwan, or Japan is an acceptable substitute depends on latency and on rules a script has no business guessing at, so it names them and lets you choose.
What the machine costs, and the belt that stops it
The way a cloud machine becomes expensive is by being forgotten. So every
machine is created with a daily shutdown, the price is printed before anything
exists, and --dry-run shows the whole decision without creating a thing:
machine my-box
size Standard_D8as_v7 (amd64)
region westeurope
price 0.386 EUR per hour, about 278 EUR per month if it never sleeps
shutdown 20:00Parking a machine ends the charge for its processor and keeps its disk;
removing it ends everything. On Azure each machine lives in its own resource
group, so removing that group removes every cent attached to it. Google keeps
snapshots outside the machine, where nothing would delete them — so the tool
deletes the ones it made, and down means the same thing on both clouds.
Machines are also chosen by what they cost rather than by how small they are, which is not the same thing: we found a single-core machine billing at twice the rate of a two-core one. Where a cloud publishes prices that can be read without a key, the cheapest machine that satisfies the request wins.
Measuring, and publishing what we measure
The second half of the devkit exists because a compiler’s claims should be checkable by whoever hears them.
devkit/mica-measure benchmarks # Mica against gcc -O2 on this machine
devkit/mica-measure corpus # how much Mica the test suite compiles
devkit/mica-measure all --json results.jsonEvery benchmark kernel is written twice — once in Mica, once in C with the same algorithm — and three metrics are reported side by side, because any one of them alone would mislead:
| Metric | What it is | Character |
|---|---|---|
| instructions | retired instructions, counted by callgrind | deterministic to the instruction, and the harshest view of Mica: it counts instructions, not time |
| cycles | the processor’s own counters | the truest measure, and the one a virtual machine often cannot offer |
| wall clock | what a person actually waits for | available everywhere, noisiest of the three |
Here is a run from a machine the tool created, so you can see the shape of the
thing rather than a summary of it. Mica 7.2.0 against gcc 14.2.0 -O2, on a
four-core AMD EPYC in Google Cloud:
| Kernel | wall clock | instructions |
|---|---|---|
| Fasta | 1.04x | 2.92x |
| SpectralNorm | 1.09x | 1.64x |
| Mandelbrot | 1.22x | 1.15x |
| FannkuchRedux | 1.28x | 2.95x |
| ReverseComplement | 1.32x | 2.54x |
| NBody | 1.40x | 1.51x |
| KNucleotide | 1.49x | 3.79x |
| PiDigits | 1.50x | 3.09x |
| BinaryTrees | 2.36x | 2.43x |
| RegexRedux | 7.26x | 8.48x |
Ratios are Mica divided by gcc, so 1.00x is parity and lower is Mica ahead. Every Mica binary here has all of the language’s safety checks on.
Two things are worth reading in that table honestly. Several kernels run within a third of gcc’s time while executing two to three times its instructions, which is why wall clock is the column that answers the question people are actually asking. And the regex kernel stands at seven times, alone and by a wide margin: that is a known gap with a known cause, and it is on the list.
Cycles are missing from that run because a virtual machine usually does not expose the processor’s counters. The tool says so instead of printing a zero.
The corpus command answers a question people ask silently about any test suite:
1945 test programs, 233874 lines of Mica
114 further programs in the examples and benchmarks, 11045 lines
the suite compiles and runs them 11611 times across architectures, tiers,
memory classes and carrier countsWorking on the compiler from your editor
Remote development splits an editor in two. The half that talks to the machine
runs on your laptop; the halves that understand the code — the language server,
the debugger — run on the machine being worked on, and installing them locally
does nothing at all for a remote window. mica-devbox installs each on the side
that needs it, before the window opens:
devkit/mica-devbox # creates or wakes it, sets up both ends, opens the editor
devkit/mica-devbox --stop # park it: the disk stays, the processor stops billing
devkit/mica-devbox --down # remove it entirelyEverything you edit, build, and run is on the machine; your laptop draws the window. You need Visual Studio Code and git — the cloud tool, the remote-development extension, and the Mica extensions on the machine all arrive by themselves.
What building it taught us
We proved every part of this against live accounts on both clouds before merging it, and nearly everything it now handles correctly is something that went wrong first. Four are worth repeating, because they are the kind of thing that does not show up in a code review.
A malformed line does not fail one command. Cloud-init reads a machine’s setup once, and refuses the whole file if any part of it is wrong — so a single command containing a colon and a space was read as a key and a value, every other command was skipped, and the machine came up finished, reachable, and with no compiler on it. Nothing reported an error. There is now a test that parses the generated setup exactly as a machine would, before any machine is created with it.
A machine you are allowed to see is not a machine you are allowed to create. Cloud capacity is granted per machine family, and a new account is granted none of most of them. The listing that says what a region sells says nothing about that, so the tool offered machines that failed at the last moment — after the resource group already existed. It now reads the account’s own grants first and refuses honestly, naming what the allowance is and how to raise it. This one matters most for the people we most want to help: a newcomer’s account is the most restricted one there is.
A command named mica is not necessarily the compiler. A machine may carry
a wrapper that runs the compiler inside a container, and that wrapper can only
see the directory it was called from — so a benchmark writing its output
elsewhere gets a successful exit code and no files. Measuring through it would
have produced published numbers that were wrong in a way nothing later would
have revealed.
An editor already connected somewhere else ignores being told where to install. Run from inside a container, the command that installs extensions on a remote machine installs them into the container instead, and reports success. The tool detects that case now and leaves the extensions for the window to offer.
None of these were findable by reading the code. They are the argument for spending real money on a real account before telling anyone the thing works.
What this does not change
The published micalang/mica image is untouched and needs no rebuild. The
devkit is tooling beside the product rather than part of it: it runs from a
checkout, on your machine or on one it creates for you, and it works against the
compiler you already have.
What is next
The graphics profile is written but has not run on either cloud yet — neither of our accounts has the quota for it, which is its own small lesson about what “supported” should mean. And the numbers above deserve a permanent home on this site, refreshed with every release, rather than living in a blog post. Both are on the list.
If you try it and something surprises you, we would like to know. It is one clone away, and the devkit’s own guide is the reference.