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-devbox

Why 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-provisioninstalls toolchains by name — Go, GCC, LLVM, QEMU, Python, Docker, the measurement tools, the compiler
mica-cloudcreates a machine on Azure or Google Cloud with all of that on it, and removes it entirely
mica-measurethe 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               # everything

Each 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 clouds

us · 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:00

Parking 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.json

Every 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:

MetricWhat it isCharacter
instructionsretired instructions, counted by callgrinddeterministic to the instruction, and the harshest view of Mica: it counts instructions, not time
cyclesthe processor’s own countersthe truest measure, and the one a virtual machine often cannot offer
wall clockwhat a person actually waits foravailable 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:

Kernelwall clockinstructions
Fasta1.04x2.92x
SpectralNorm1.09x1.64x
Mandelbrot1.22x1.15x
FannkuchRedux1.28x2.95x
ReverseComplement1.32x2.54x
NBody1.40x1.51x
KNucleotide1.49x3.79x
PiDigits1.50x3.09x
BinaryTrees2.36x2.43x
RegexRedux7.26x8.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 counts

Working 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 entirely

Everything 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.