Skip to content

Repository files navigation

Set of Benchmarks for myc.

Running on Ryzen 3800x and ubuntu 24.04. Add myc-llvm, myc-qbe, myc-c, mycc to Path.

git clone https://github.com/kostya/myc-benchmarks.git
cd myc-benchmarks

LangArena Benchmark:

LangArena is a benchmark suite of 50 tests and 9,000 lines of non-trivial C code (json, base64, multithreaded matmul, neural net, compression, maze A*, bf interpreter, and others) with heavy macros like uthash. The ./c directory contains 29 .c files (230KB total), which we'll use for comparison. This is not just a random benchmark of micro-optimizations or synthetic loops - it's a set of tasks close to production use. Each of the 50 tests validates its output using checksums. A compiler can't "cheat" by deleting or skipping work.

Fetch and Build deps

cd LangArena/c; make MODE=prod target/deps/prod/yyjson.o target/deps/prod/libbase64.o; cd -

Benchmark 1: LangArena single IR file Myc vs Clang.

Compile LangArena C benchmark, from single IR file (to remove parsing overhead). Both Myc LangArena/langarena-single-myc/langarena.myc - 2.07Mb and LL LangArena/langarena-single-ll/langarena.ll - 2.9Mb, represent the same program and both generated from the same 29 C files (in ./LangArena/c folder) in O0 mode without any processing (by scripts LangArena/gen_myc.rb and LangArena/gen_ll.rb, files in the repo was generated for linux64, for macOS need to regenerate with this scripts). This benchmark shows raw optimization and code generation skills for both engines.

Ubuntu clang version 20.1.2 (0ubuntu1~24.04.3) vs myc 0.10.0-dev-4e16e50 LLVM 20.1.2

cd LangArena; ruby run_single_ir_benchmark.rb; cd -
Compiler Compile time Runtime
clang(-O3, ll) 1603ms 52.1s
clang(-O2, ll) 1572ms 52.6s
clang(-O1, ll) 1286ms 55.4s
clang(-O0, ll) 193ms 139.0s
myc-llvm(default) 889ms 59.6s
myc-llvm(final) 1880ms 52.8s
myc-qbe(default) 262ms 68.3s
myc-c(default, clang) 1589ms 60.6s
myc-c(final, clang) 3115ms 53.3s
  1. myc-qbe(default) - compiles only 35% slower than Clang -O0 (262ms vs 193ms), and 6x faster than Clang -O3 (262ms vs 1603ms). Despite near-instant compilation, runtime is only 31% slower than Clang -O3 (68.3s vs 52.1s). myc-qbe delivers a tradeoff that even Go would envy.

  2. myc-llvm(default) - 1.8x faster compilation than Clang -O3 (889ms vs 1603ms), with runtime only 14% slower (59.6s vs 52.1s). A solid balance: fast compiles, decent performance.

  3. myc-llvm(final) - runtime is nearly identical to Clang -O3 (52.8s vs 52.1s, just 1.3% slower), but compilation takes 17% longer (1880ms vs 1603ms). LLVM spends ~280ms more optimizing Myc-generated IR - needs investigation.

  4. myc-c - adds overhead by generating C code and compiling it through the full Clang stack, so it can't compete with the other two backends on compile time. It's primarily a fallback backend for portability. Runtime is respectable: 60.6s default, 53.3s final - within 2% of Clang -O3 when using clang as the final compiler.

plot

This scatter plot shows the tradeoff between compile time and runtime. The ideal is the bottom-left corner: fast compiles, fast runtime. This is the Pareto frontier - you can't improve one without sacrificing the other. Myc-qbe(default) and myc-llvm(default) occupy a spot that even Go would respect. Measured on pure IR files - no C parsing overhead, just optimization and code generation for both MycIR and LLVM-LL.

Benchmark 2: LangArena C benchmark - Mycc,Clang,Gcc,Cproc.

This benchmark compiles the C files in LangArena/c dir (excluding two precompiled dependencies: yyjson.o and libbase64.o). All files are compiled at once, not one by one (clang LangArena/c/src/*.c), to remove the overhead of multiple command invocations.

mycc 0.10.0-dev-4e16e50 c99-subset compiler (backend: unknown) (https://github.com/kostya/myc), gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0, Ubuntu clang version 20.1.2 (0ubuntu1~24.04.3), cproc master

cd LangArena; ruby run_c_benchmark.rb; cd -
Compiler Compile time Runtime
mycc(default, llvm) 2713ms 60.4s
mycc(final, llvm) 3669ms 53.6s
mycc(default, qbe) 2442ms 68.5s
mycc(default, c, clang) 4471ms 59.5s
mycc(final, c, clang) 4920ms 52.0s
clang(-O3, c) 3042ms 51.8s
clang(-O2, c) 3001ms 52.0s
clang(-O1, c) 2739ms 54.2s
clang(-O0, c) 1605ms 141.1s
gcc(-O3, c) 3470ms 52.4s
gcc(-O2, c) 2986ms 54.7s
gcc(-O1, c) 2143ms 58.0s
gcc(-O0, c) 1304ms 134.9s
cproc 726ms 72.8s
  1. Parsing is the real bottleneck for clang. Compare Clang -O0 on C (1605ms) vs Clang -O0 on LLVM IR (193ms). 88% of Clang's compile time is spent on parsing C and generating IR, not on optimization or codegen. Shocking O_o.

  2. cproc proves fast C parsing is possible. cproc compiles the same C code in 726ms - 2.2x faster than Clang -O0. Runtime is only 40% slower than Clang -O3 (72.8s vs 51.8s). As we saw earlier from myc-qbe results, QBE (cproc's backend) spends ~262ms on codegen, meaning cproc's parsing itself is roughly ~464ms.

  3. mycc doesn't shine in this benchmark. mycc relies on libclang for parsing, and has very rough frontend implementation (3-week POC), not a production C frontend.

  4. GCC has better O0->O3 scaling.

plot

Benchmark 3: LangArena C benchmark amalgamation - Mycc,Clang,Gcc,Cproc.

This benchmark compiles the amalgamated C file LangArena/c-amalgamation/single.c. It can now be directly compared with Benchmark 1 (single IR), since the unexpected per-file overhead (from Benchmark 2) has been eliminated.

cd LangArena; ruby run_c_amalgamation_benchmark.rb; cd -
Compiler Compile time Runtime
mycc(default, llvm) 1285ms 59.3s
mycc(final, llvm) 2306ms 52.6s
mycc(default, qbe) 716ms 67.8s
mycc(default, c, clang) 2114ms 56.6s
mycc(final, c, clang) 2647ms 51.9s
clang(-O3, c) 1803ms 51.9s
clang(-O2, c) 1767ms 51.6s
clang(-O1, c) 1463ms 54.9s
clang(-O0, c) 355ms 141.7s
gcc(-O3, c) 2712ms 52.3s
gcc(-O2, c) 2154ms 54.4s
gcc(-O1, c) 1219ms 57.9s
gcc(-O0, c) 543ms 134.4s
cproc 166ms 72.6s
  1. mycc consistently adds ~450ms over single IR - this is the cost of libclang overhead.

  2. cproc is the absolute leader in compilation speed.

  3. Clang adds roughly ~200ms for all optimization levels compared to single IR.

plot

Benchmark 4: Brainfuck compiler

This benchmark compares different IRs (LLVM, QBE, C, Myc) against each other. The same Brainfuck program generates each IR, then compiles and runs. This shows whether Myc adds overhead compared to using each backend directly.

cd brainfuck-compiler && ruby run.rb
IR Compiler IR size, Kb Compile time Run time
llvm-ll clang(-O3) 1529 1298ms 624ms
myc myc-llvm(default) 486 213ms 714ms
myc myc-llvm(final) 486 1073ms 616ms
qbe-ssa qbe + clang(as+linker) 345 122ms + 140ms 780ms
myc myc-qbe(default) 486 479ms 772ms
c clang(-O3) 128 1166ms 615ms
myc myc-c(default) 486 1336ms 623ms
myc myc-c(final) 486 1544ms 641ms

Benchmark 5: Examples

This benchmark compare myc backens on simple micro benchmarks:

cd examples && ruby run.rb
Benchmark Backend Compile Run
mandel.myc myc-llvm 320ms 721ms
myc-qbe 499ms 773ms
myc-c 1320ms 614ms
myc-llvm-final 1111ms 615ms
myc-qbe-final 483ms 775ms
myc-c-final 1577ms 637ms
bf.myc myc-llvm 91ms 1350ms
myc-qbe 105ms 2677ms
myc-c 117ms 1601ms
myc-llvm-final 102ms 1292ms
myc-qbe-final 104ms 2697ms
myc-c-final 115ms 1429ms
loop.myc myc-llvm 85ms 411ms
myc-qbe 100ms 369ms
myc-c 101ms 234ms
myc-llvm-final 89ms 327ms
myc-qbe-final 98ms 368ms
myc-c-final 100ms 247ms
loop.c myc-llvm 231ms 420ms
myc-qbe 137ms 368ms
myc-c 146ms 224ms
myc-llvm-final 122ms 403ms
myc-qbe-final 132ms 421ms
myc-c-final 127ms 423ms
sieve.c myc-llvm 141ms 229ms
myc-qbe 144ms 285ms
myc-c 148ms 237ms
myc-llvm-final 134ms 234ms
myc-qbe-final 132ms 235ms
myc-c-final 132ms 233ms

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages