Clause

Benchmarks

Clause compared with Erlang/OTP on one machine: the same Erlang programs, compiled by erlc and by clau -O2, time their kernels after a warm-up call. These numbers change with every optimization.

Geometric mean of kernel times, Clause -O2 against the BEAM JIT (OTP)
1.49× faster on average
Kernels where Clause is faster
31 / 31
Geometric mean on 2026-10-12, the first recorded run
20.2×

Kernel times

Median of 3 runs in milliseconds. The bar shows Clause's time divided by OTP's on a logarithmic scale.

Clause fasterOTP faster🔺 Runs varied by more than half of the median.
KernelOTP JITClause -O2Clause ÷ OTP
Data generation
bigint_factorialComputes the factorial of 3,000 with big integers, 330 times1,620.17212.760.13×
binary_appendAppends 10,000 32-bit integers to a growing binary, 23,000 times1,080.93802.570.74×
list_of_tuplesBuilds a list of 200,000 small tuples, 260 times1,467.601,128.440.77×
list_to_tupleConverts 1,000-element lists to tuples, 170,000 times1,586.381,278.690.81×
map_putInserts 2,000 integer keys into a map one by one, 4,900 times1,605.841,519.510.95×
string_buildBuilds 20,000 strings from integers and atoms, 1,000 times1,044.38720.730.69×
Data processing
binary_matchSums 20,000 32-bit integers matched out of a binary, 49,000 times1,272.631,071.470.84×
comprehensionList comprehension filtering and doubling 20,000 integers, 15,000 times1,407.08893.850.64×
int_to_listConverts 20,000 integers to strings and back, 2,000 times908.70412.790.45×
map_foldlMaps, then folds a list of 20,000 integers, 4,500 times1,500.771,113.040.74×
map_updateIncrements every value of a 500-key map, 24,000 times1,151.28669.970.58×
small_mapUpdates a small state map 80 million times1,486.441,061.830.71×
sortSorts a list of 20,000 random integers, 600 times1,112.37466.550.42×
term_to_binaryEncodes and decodes a large nested term, 4,300 times1,433.291,071.950.75×
File I/O
large_readReads a 16 MB file in 64 KB chunks, 370 times1,444.151,007.930.70×
large_writeWrites a 16 MB file in 64 KB chunks, 200 times1,019.80989.090.97×
read_fileReads a whole 16 MB file in one call, 330 times1,485.521,483.031.00×
read_lineReads a 20,000-line text file line by line, 52 times1,522.071,467.280.96×
small_filesWrites, reads back and deletes 500 small files, 11 times1,209.751,116.400.92×
Garbage collection
explicit_collectForces garbage collection with 10,000 live tuples, 5,100 times1,547.98639.850.41×
grow_shrinkGrows the heap with a 200,000-element list, then drops it, 300 times1,041.41861.750.83×
long_lived_churnKeeps a sliding window of 10,000 live elements among garbage, 370 times1,351.271,095.820.81×
short_processesSpawns 5,000 short-lived processes that each make garbage, 69 times1,667.281,037.980.62×
Libraries
qlcRuns the qlc transform over 27 queries and 3 modules, 11 times1,873.721,714.660.92×
Message passing
fan_in100 processes each send 1,000 messages to one, 25 times1,402.68391.780.28×
large_messageSends a 100,000-element list to another process and back, 560 times1,063.94789.040.74×
ping_pongBounces one message between two processes 2 million times1,504.97904.200.60×
ringPasses a token around a 1,000-process ring 3,050 times1,438.211,099.660.76×
Loopback sockets
tcp_connectOpens 900 TCP connections over loopback, echoing 25 messages of 1 KB on each1,418.851,047.850.74×
tcp_echoEchoes 30,000 messages of 1 KB over loopback TCP1,455.621,136.060.78×
udp_round_tripBounces a 1 KB datagram 27,900 times over loopback UDP1,458.071,196.820.82×

Whole programs

Wall time in seconds, startup included, median of the runs.

ProgramOTP JITClause -O2Clause ÷ OTP
bench_datagenBuilds lists, tuples, maps, binaries and big integers in bulk8.545.720.67×
bench_dataprocSorting, folds, map updates, binary matching and conversions10.456.760.65×
bench_fileSmall and large file writes and reads, line reads6.956.240.90×
bench_gcShort-lived processes, heap growth and shrinking, live data churn5.833.690.63×
bench_libraryThe qlc parse transform at run time, as qlc:q/1 uses it2.301.890.82×
bench_msgPing-pong, fan-in, a process ring and large message copies5.693.280.58×
bench_socketTCP echo, TCP connects and UDP round trips over loopback5.994.570.76×

Progress

Geometric mean of Clause's time divided by OTP's on each recorded run day. Runs before 2026-10-21 were not pinned to a CPU set, so part of the change on that day comes from the pinning.

DateCommitClause ÷ OTP
2026-10-12a7bc0c9b20.2×
2026-10-138a244d9c16.9×
2026-10-1455f42a9d16.9×
2026-10-156ed3851c2.73×
2026-10-1697295c841.95×
2026-10-17a8c3f8f61.38×
2026-10-18336caea71.41×
2026-10-207d7a2f2e1.00×
2026-10-2171ec52f80.78×
2026-10-23dea685080.69×
2026-10-24af1050430.65×
2026-10-26d6eafa720.71×
2026-10-30f4e5f3e00.67×

Executable sizes

Size of the benchmark programs as Clause builds them at each optimization level, in megabytes.

Program-O0-O2-O2 --lto
bench_datagen9.90 MB9.82 MB9.82 MB
bench_dataproc10.42 MB10.01 MB10.01 MB
bench_file11.34 MB10.59 MB10.59 MB
bench_gc9.89 MB9.81 MB9.81 MB
bench_library10.24 MB9.94 MB9.95 MB
bench_msg9.91 MB9.82 MB9.82 MB
bench_socket11.58 MB10.64 MB10.65 MB

-O2 sizes of the last 6 benchmark runs, oldest first, one Clause commit each. The table below adds the total of all bench_* programs and the size of the clau compiler.

024681012 MBbench_datagen, 2026-10-20 7d7a2f2e: 6.29 MBbench_datagen, 2026-10-21 71ec52f8: 6.32 MBbench_datagen, 2026-10-23 dea68508: 6.33 MBbench_datagen, 2026-10-24 af105043: 6.33 MBbench_datagen, 2026-10-26 d6eafa72: 8.55 MBbench_datagen, 2026-10-30 f4e5f3e0: 9.82 MB9.82bench_datagenbench_dataproc, 2026-10-20 7d7a2f2e: 6.62 MBbench_dataproc, 2026-10-21 71ec52f8: 6.64 MBbench_dataproc, 2026-10-23 dea68508: 6.65 MBbench_dataproc, 2026-10-24 af105043: 6.65 MBbench_dataproc, 2026-10-26 d6eafa72: 8.74 MBbench_dataproc, 2026-10-30 f4e5f3e0: 10.01 MB10.01bench_dataprocbench_file, 2026-10-20 7d7a2f2e: 6.72 MBbench_file, 2026-10-21 71ec52f8: 6.75 MBbench_file, 2026-10-23 dea68508: 6.75 MBbench_file, 2026-10-24 af105043: 6.75 MBbench_file, 2026-10-26 d6eafa72: 9.20 MBbench_file, 2026-10-30 f4e5f3e0: 10.59 MB10.59bench_filebench_gc, 2026-10-20 7d7a2f2e: 6.28 MBbench_gc, 2026-10-21 71ec52f8: 6.32 MBbench_gc, 2026-10-23 dea68508: 6.32 MBbench_gc, 2026-10-24 af105043: 6.32 MBbench_gc, 2026-10-26 d6eafa72: 8.54 MBbench_gc, 2026-10-30 f4e5f3e0: 9.81 MB9.81bench_gcbench_library, 2026-10-26 d6eafa72: 9.30 MBbench_library, 2026-10-30 f4e5f3e0: 9.94 MB9.94bench_librarybench_msg, 2026-10-20 7d7a2f2e: 6.29 MBbench_msg, 2026-10-21 71ec52f8: 6.32 MBbench_msg, 2026-10-23 dea68508: 6.33 MBbench_msg, 2026-10-24 af105043: 6.33 MBbench_msg, 2026-10-26 d6eafa72: 8.55 MBbench_msg, 2026-10-30 f4e5f3e0: 9.82 MB9.82bench_msgbench_socket, 2026-10-20 7d7a2f2e: 6.39 MBbench_socket, 2026-10-21 71ec52f8: 6.42 MBbench_socket, 2026-10-23 dea68508: 6.43 MBbench_socket, 2026-10-24 af105043: 6.43 MBbench_socket, 2026-10-26 d6eafa72: 9.33 MBbench_socket, 2026-10-30 f4e5f3e0: 10.64 MB10.64bench_socket
  • 2026-10-207d7a2f2e
  • 2026-10-2171ec52f8
  • 2026-10-23dea68508
  • 2026-10-24af105043
  • 2026-10-26d6eafa72
  • 2026-10-30f4e5f3e0
DateCommitAll bench_* programsclau
2026-10-207d7a2f2e38.59 MB59.50 MB
2026-10-2171ec52f838.78 MB59.54 MB
2026-10-23dea6850838.79 MB59.54 MB
2026-10-24af10504338.81 MB59.65 MB
2026-10-26d6eafa7262.21 MB59.98 MB
2026-10-30f4e5f3e070.63 MB60.75 MB

Setup

Machine
Intel64 Family 6 Model 183 Stepping 1, GenuineIntel, 32 logical CPUs, Windows 11 (10.0.26200)
CPU set
Performance cores 0-15, 16 of 32 logical CPUs
Erlang/OTP
29, ERTS 17.1
Clause commit
f4e5f3e0
Run
2026-10-30

OTP and Clause run on the same CPUs: every benchmark program is pinned to the performance cores of the processor, so on a hybrid CPU no kernel lands on a slower efficiency core. Both keep one scheduler online per CPU of that set, unbound within it.

To run the benchmarks yourself, use make benchmark or make-benchmark.bat in the Clause repository; the benchmark notes describe the programs and options. Benchmark notes