Benchmarks
Clause im Vergleich mit Erlang/OTP auf einer Maschine: Dieselben Erlang-Programme, kompiliert mit erlc und mit clau -O2, messen die Laufzeit ihrer Kernels nach einem Aufwärmaufruf. Diese Zahlen ändern sich mit jeder Optimierung.
- Geometrisches Mittel der Kernel-Zeiten, Clause -O2 gegenüber dem BEAM-JIT (OTP)
- 1,49× im Mittel schneller
- Kernels, bei denen Clause schneller ist
- 31 / 31
- Geometrisches Mittel am 2026-10-12, dem ersten erfassten Lauf
- 20,2×
Kernel-Zeiten
Median aus 3 Läufen in Millisekunden. Der Balken zeigt die Zeit von Clause geteilt durch die von OTP auf logarithmischer Skala.
| Kernel | OTP JIT | Clause -O2 | Clause ÷ OTP | |
|---|---|---|---|---|
| Datenerzeugung | ||||
| bigint_factorialBerechnet die Fakultät von 3000 mit großen Ganzzahlen, 330-mal | 1.620,17 | 212,76 | 0,13× | |
| binary_appendHängt 10.000 32-Bit-Ganzzahlen an ein wachsendes Binary an, 23.000-mal | 1.080,93 | 802,57 | 0,74× | |
| list_of_tuplesBaut eine Liste aus 200.000 kleinen Tupeln, 260-mal | 1.467,60 | 1.128,44 | 0,77× | |
| list_to_tupleWandelt Listen mit 1000 Elementen 170.000-mal in Tupel um | 1.586,38 | 1.278,69 | 0,81× | |
| map_putFügt 2000 Ganzzahlschlüssel einzeln in eine Map ein, 4900-mal | 1.605,84 | 1.519,51 | 0,95× | |
| string_buildBaut 20.000 Zeichenketten aus Ganzzahlen und Atomen, 1000-mal | 1.044,38 | 720,73 | 0,69× | |
| Datenverarbeitung | ||||
| binary_matchSummiert 20.000 32-Bit-Ganzzahlen, per Matching aus einem Binary, 49.000-mal | 1.272,63 | 1.071,47 | 0,84× | |
| comprehensionComprehension, die 20.000 Ganzzahlen filtert und verdoppelt, 15.000-mal | 1.407,08 | 893,85 | 0,64× | |
| int_to_listWandelt 20.000 Ganzzahlen in Zeichenketten und zurück, 2000-mal | 908,70 | 412,79 | 0,45× | |
| map_foldlWendet map und dann fold auf 20.000 Ganzzahlen an, 4500-mal | 1.500,77 | 1.113,04 | 0,74× | |
| map_updateErhöht jeden Wert einer Map mit 500 Schlüsseln 24.000-mal | 1.151,28 | 669,97 | 0,58× | |
| small_mapAktualisiert eine kleine Zustands-Map 80 Millionen Mal | 1.486,44 | 1.061,83 | 0,71× | |
| sortSortiert eine Liste mit 20.000 zufälligen Ganzzahlen, 600-mal | 1.112,37 | 466,55 | 0,42× | |
| term_to_binaryKodiert und dekodiert einen großen verschachtelten Term, 4300-mal | 1.433,29 | 1.071,95 | 0,75× | |
| Datei-I/O | ||||
| large_readLiest eine 16-MB-Datei in Blöcken zu 64 KB, 370-mal | 1.444,15 | 1.007,93 | 0,70× | |
| large_writeSchreibt eine 16-MB-Datei in Blöcken zu 64 KB, 200-mal | 1.019,80 | 989,09 | 0,97× | |
| read_fileLiest eine ganze 16-MB-Datei mit einem Aufruf, 330-mal | 1.485,52 | 1.483,03 | 1,00× | |
| read_lineLiest eine Textdatei mit 20.000 Zeilen zeilenweise, 52-mal | 1.522,07 | 1.467,28 | 0,96× | |
| small_filesSchreibt, liest und löscht 500 kleine Dateien, 11-mal | 1.209,75 | 1.116,40 | 0,92× | |
| Garbage Collection | ||||
| explicit_collectErzwingt Garbage Collection mit 10.000 lebenden Tupeln, 5100-mal | 1.547,98 | 639,85 | 0,41× | |
| grow_shrinkLässt den Heap mit einer 200.000-Elemente-Liste wachsen, verwirft sie, 300-mal | 1.041,41 | 861,75 | 0,83× | |
| long_lived_churnHält ein gleitendes Fenster aus 10.000 lebenden Elementen inmitten von Müll, 370-mal | 1.351,27 | 1.095,82 | 0,81× | |
| short_processesStartet 5000 kurzlebige Prozesse, die jeweils Müll erzeugen, 69-mal | 1.667,28 | 1.037,98 | 0,62× | |
| Bibliotheken | ||||
| qlcFührt die qlc-Transformation über 27 Abfragen und 3 Module aus, 11-mal | 1.873,72 | 1.714,66 | 0,92× | |
| Nachrichtenaustausch | ||||
| fan_in100 Prozesse senden je 1000 Nachrichten an einen, 25-mal | 1.402,68 | 391,78 | 0,28× | |
| large_messageSendet eine Liste mit 100.000 Elementen an einen Prozess und zurück, 560-mal | 1.063,94 | 789,04 | 0,74× | |
| ping_pongSchickt eine Nachricht 2 Millionen Mal zwischen zwei Prozessen hin und her | 1.504,97 | 904,20 | 0,60× | |
| ringReicht ein Token 3050-mal durch einen Ring aus 1000 Prozessen | 1.438,21 | 1.099,66 | 0,76× | |
| Loopback-Sockets | ||||
| tcp_connectÖffnet 900 TCP-Verbindungen über Loopback mit je 25 Echos zu 1 KB | 1.418,85 | 1.047,85 | 0,74× | |
| tcp_echoEcho von 30.000 Nachrichten zu 1 KB über Loopback-TCP | 1.455,62 | 1.136,06 | 0,78× | |
| udp_round_trip27.900 UDP-Roundtrips eines 1-KB-Datagramms über Loopback | 1.458,07 | 1.196,82 | 0,82× | |
Vollständige Programme
Gesamtlaufzeit in Sekunden, einschließlich Start, Median der Läufe.
| Programm | OTP JIT | Clause -O2 | Clause ÷ OTP | |
|---|---|---|---|---|
| bench_datagenErzeugt massenhaft Listen, Tupel, Maps, Binaries und große Ganzzahlen | 8,54 | 5,72 | 0,67× | |
| bench_dataprocSortieren, Folds, Map-Updates, Binary-Matching und Umwandlungen | 10,45 | 6,76 | 0,65× | |
| bench_fileSchreiben und Lesen kleiner und großer Dateien, zeilenweises Lesen | 6,95 | 6,24 | 0,90× | |
| bench_gcKurzlebige Prozesse, wachsender und schrumpfender Heap, lebende Daten | 5,83 | 3,69 | 0,63× | |
| bench_libraryDie qlc-Parse-Transform zur Laufzeit, wie qlc:q/1 sie nutzt | 2,30 | 1,89 | 0,82× | |
| bench_msgPing-Pong, Fan-in, Prozessring und Kopieren großer Nachrichten | 5,69 | 3,28 | 0,58× | |
| bench_socketTCP-Echo, TCP-Verbindungsaufbau und UDP-Roundtrips über Loopback | 5,99 | 4,57 | 0,76× |
Fortschritt
Geometrisches Mittel der Zeit von Clause geteilt durch die von OTP an jedem erfassten Lauftag. Läufe vor dem 2026-10-21 waren nicht an eine CPU-Menge gebunden; ein Teil der Änderung an diesem Tag geht daher auf die Bindung zurück.
| Datum | Commit | Clause ÷ OTP |
|---|---|---|
| 2026-10-12 | a7bc0c9b | 20,2× |
| 2026-10-13 | 8a244d9c | 16,9× |
| 2026-10-14 | 55f42a9d | 16,9× |
| 2026-10-15 | 6ed3851c | 2,73× |
| 2026-10-16 | 97295c84 | 1,95× |
| 2026-10-17 | a8c3f8f6 | 1,38× |
| 2026-10-18 | 336caea7 | 1,41× |
| 2026-10-20 | 7d7a2f2e | 1,00× |
| 2026-10-21 | 71ec52f8 | 0,78× |
| 2026-10-23 | dea68508 | 0,69× |
| 2026-10-24 | af105043 | 0,65× |
| 2026-10-26 | d6eafa72 | 0,71× |
| 2026-10-30 | f4e5f3e0 | 0,67× |
Größe der ausführbaren Dateien
Größe der Benchmark-Programme in Megabyte, wie Clause sie auf jeder Optimierungsstufe erzeugt.
| Programm | -O0 | -O2 | -O2 --lto |
|---|---|---|---|
| bench_datagen | 9,90 MB | 9,82 MB | 9,82 MB |
| bench_dataproc | 10,42 MB | 10,01 MB | 10,01 MB |
| bench_file | 11,34 MB | 10,59 MB | 10,59 MB |
| bench_gc | 9,89 MB | 9,81 MB | 9,81 MB |
| bench_library | 10,24 MB | 9,94 MB | 9,95 MB |
| bench_msg | 9,91 MB | 9,82 MB | 9,82 MB |
| bench_socket | 11,58 MB | 10,64 MB | 10,65 MB |
Größen mit -O2 der letzten 6 Benchmark-Läufe, älteste zuerst, ein Clause-Commit pro Lauf. Die Tabelle darunter ergänzt die Summe aller bench_*-Programme und die Größe des Compilers clau.
- 2026-10-207d7a2f2e
- 2026-10-2171ec52f8
- 2026-10-23dea68508
- 2026-10-24af105043
- 2026-10-26d6eafa72
- 2026-10-30f4e5f3e0
| Datum | Commit | Alle bench_*-Programme | clau |
|---|---|---|---|
| 2026-10-20 | 7d7a2f2e | 38,59 MB | 59,50 MB |
| 2026-10-21 | 71ec52f8 | 38,78 MB | 59,54 MB |
| 2026-10-23 | dea68508 | 38,79 MB | 59,54 MB |
| 2026-10-24 | af105043 | 38,81 MB | 59,65 MB |
| 2026-10-26 | d6eafa72 | 62,21 MB | 59,98 MB |
| 2026-10-30 | f4e5f3e0 | 70,63 MB | 60,75 MB |
Testumgebung
- Maschine
- Intel64 Family 6 Model 183 Stepping 1, GenuineIntel, 32 logische CPUs, Windows 11 (10.0.26200)
- CPU-Menge
- Performance-Kerne 0-15, 16 von 32 logischen CPUs
- Erlang/OTP
- 29, ERTS 17.1
- Clause-Commit
- f4e5f3e0
- Lauf
- 2026-10-30
OTP und Clause laufen auf denselben CPUs: Jedes Benchmark-Programm ist an die Performance-Kerne des Prozessors gebunden, sodass auf einer Hybrid-CPU kein Kernel auf einem langsameren Effizienz-Kern landet. Beide halten einen Scheduler pro CPU dieser Menge online, ohne ihn innerhalb der Menge an eine bestimmte CPU zu binden.
Um die Benchmarks selbst auszuführen, make benchmark oder make-benchmark.bat im Clause-Repository verwenden; die Benchmark-Notizen beschreiben die Programme und Optionen. Benchmark-Notizen
Clause