Benchmarks
Run time, binary size and build time against go build, with the method.
All numbers compare marmot with go build (Go 1.27) on the same machine. A program counts
only if its output is identical to Go's. Each result is the median of five runs after one
warm-up run.
Early numbers
These are early numbers from a young compiler. They will change.
Run time
Apple M3 Pro, 43 programs.
| Build | Average speed against Go |
|---|---|
marmot build (dev, fast code generator) | not measured yet |
marmot build (dev, MARMOT_TIER0=0) | 1.4x faster |
marmot build -release | 1.6x faster |
"Average" is the geometric mean. 33 of the 43 programs are faster than Go in release mode and 10 are slower. An 8-core Intel desktop running Linux gives a similar picture: 1.6x faster on average over 45 programs.
By kind of program
| Program | What it stresses | Against Go |
|---|---|---|
| convolution | numeric loops | 17.8x faster |
| bit tricks | integer operations | 10.1x faster |
| sum, min, max | simple loops over slices | 8.9x faster |
| struct copy | copying values | 4.6x faster |
| interface calls | method calls through interfaces | 3.5x faster |
| string search | finding substrings | 2.8x faster |
| closures | calling function values | 2.0x faster |
| channel ping-pong | goroutine hand-off | 1.5x faster |
| quicksort | branches and swaps | about equal |
| tree building | allocation and garbage collection | 0.9x (slower) |
| defer in a loop | defer cost | 0.7x (slower) |
Where marmot wins big, the cause is usually vector instructions that Go's compiler does not
emit. Where it loses, the cause is allocation and defer, which Go has tuned for years.
Loops that can run in parallel
marmot can prove that the iterations of some loops do not depend on each other, and then run them on all cores. This is off by default while it is being reviewed. With it on:
These use every core, so they are faster in wall-clock time, not in total CPU work.
Binary size
| Program | marmot | go |
|---|---|---|
| hello world with println, -release | 148 KB | 1.68 MB |
| hello world with fmt.Println, -release | 665 KB | 2.4 MB |
| hello world with println, -O z | 100 KB | 1.17 MB (stripped) |
| small program using fmt, sort, strings, a map | 500 KB | 1.62 MB (stripped) |
Build time
First build
Building the compiler itself (./cmd/marmot, 238 packages including the standard library)
from empty caches on both sides, measured 2026-11-13 10:46 on a quiet Apple M3 Pro:
| Case | marmot | go |
|---|---|---|
| first build of cmd/marmot, empty caches | 5.13 to 5.43 s | 5.23 to 6.34 s |
A first build compiles every package of the standard library the program uses. Rebuilds are where the build cache and the incremental front end pay off.
Rebuilds
The same tree and the same run (2026-11-13 10:46, 238 packages), with the incremental front end, the default. The edits add one line to a package: "leaf" is the main package, "deep" is a package that most of the compiler uses. Each case ran twice for each compiler, alternating.
| Case | marmot | go |
|---|---|---|
| rebuild, nothing changed | 0.05 to 0.07 s | 0.14 to 0.15 s |
| one line edit, leaf package | 0.68 to 0.70 s | 0.50 to 0.51 s |
| one line edit, deep package | 0.94 to 0.96 s | 0.90 to 0.93 s |
A rebuild with nothing changed is where the build cache pays off.
Dev builds use a fast code generator that writes machine code directly, without LLVM
(MARMOT_TIER0=0 turns it off). It is never used with -release.
Memory
On small programs marmot binaries use about half the memory of Go binaries at run time, mostly because the runtime starts fewer things up front.
How to reproduce
make
go run ./bench/cmd/bench -list # see the programs
go run ./bench/cmd/bench # run them
go run ./bench/report # write the reportRun benchmarks on an idle machine. Other work on the same machine changes the results a lot.