Clause

Benchmarks

Clause comparé à Erlang/OTP sur une même machine : les mêmes programmes Erlang, compilés par erlc et par clau -O2, chronomètrent leurs noyaux après un appel de préchauffage. Ces chiffres évoluent à chaque optimisation.

Moyenne géométrique des temps des noyaux, Clause -O2 face au JIT de BEAM (OTP)
1,49× plus rapide en moyenne
Noyaux où Clause est plus rapide
31 / 31
Moyenne géométrique au 2026-10-12, première exécution enregistrée
20,2×

Temps des noyaux

Médiane de 3 exécutions en millisecondes. La barre montre le temps de Clause divisé par celui d'OTP sur une échelle logarithmique.

Clause plus rapideOTP plus rapide🔺 Les exécutions ont varié de plus de la moitié de la médiane.
NoyauOTP JITClause -O2Clause ÷ OTP
Génération de données
bigint_factorialCalcule la factorielle de 3000 en grands entiers, 330 fois1 620,17212,760,13×
binary_appendAjoute 10 000 entiers 32 bits à un binary croissant, 23 000 fois1 080,93802,570,74×
list_of_tuplesConstruit une liste de 200 000 petits tuples, 260 fois1 467,601 128,440,77×
list_to_tupleConvertit des listes de 1000 éléments en tuples, 170 000 fois1 586,381 278,690,81×
map_putInsère 2000 clés entières dans une map, une à une, 4900 fois1 605,841 519,510,95×
string_buildConstruit 20 000 chaînes à partir d'entiers et d'atomes, 1000 fois1 044,38720,730,69×
Traitement de données
binary_matchAdditionne 20 000 entiers 32 bits extraits d'un binary, 49 000 fois1 272,631 071,470,84×
comprehensionComprehension qui filtre et double 20 000 entiers, 15 000 fois1 407,08893,850,64×
int_to_listConvertit 20 000 entiers en chaînes et inversement, 2000 fois908,70412,790,45×
map_foldlApplique map puis fold à 20 000 entiers, 4500 fois1 500,771 113,040,74×
map_updateIncrémente chaque valeur d'une map de 500 clés, 24 000 fois1 151,28669,970,58×
small_mapMet à jour 80 millions de fois une petite map d'état1 486,441 061,830,71×
sortTrie une liste de 20 000 entiers aléatoires, 600 fois1 112,37466,550,42×
term_to_binaryEncode et décode un grand terme imbriqué, 4300 fois1 433,291 071,950,75×
E/S fichiers
large_readLit un fichier de 16 Mo par blocs de 64 Ko, 370 fois1 444,151 007,930,70×
large_writeÉcrit un fichier de 16 Mo par blocs de 64 Ko, 200 fois1 019,80989,090,97×
read_fileLit un fichier entier de 16 Mo en un seul appel, 330 fois1 485,521 483,031,00×
read_lineLit ligne par ligne un fichier texte de 20 000 lignes, 52 fois1 522,071 467,280,96×
small_filesÉcrit, relit et supprime 500 petits fichiers, 11 fois1 209,751 116,400,92×
Ramasse-miettes
explicit_collectForce le ramasse-miettes avec 10 000 tuples vivants, 5100 fois1 547,98639,850,41×
grow_shrinkFait grossir le tas avec une liste de 200 000 éléments, puis la libère, 300 fois1 041,41861,750,83×
long_lived_churnGarde une fenêtre glissante de 10 000 éléments vivants parmi les déchets, 370 fois1 351,271 095,820,81×
short_processesLance 5000 processus éphémères qui produisent chacun des déchets, 69 fois1 667,281 037,980,62×
Bibliothèques
qlcExécute la transformation qlc sur 27 requêtes et 3 modules, 11 fois1 873,721 714,660,92×
Passage de messages
fan_in100 processus envoient chacun 1000 messages à un seul, 25 fois1 402,68391,780,28×
large_messageEnvoie une liste de 100 000 éléments à un autre processus, aller-retour, 560 fois1 063,94789,040,74×
ping_pongRenvoie un message entre deux processus 2 millions de fois1 504,97904,200,60×
ringFait passer un jeton 3050 fois dans un anneau de 1000 processus1 438,211 099,660,76×
Sockets en boucle locale
tcp_connectOuvre 900 connexions TCP sur loopback, avec 25 échos de 1 Ko sur chacune1 418,851 047,850,74×
tcp_echoRenvoie en écho 30 000 messages de 1 Ko en TCP sur loopback1 455,621 136,060,78×
udp_round_tripRenvoie un datagramme de 1 Ko 27 900 fois en UDP sur loopback1 458,071 196,820,82×

Programmes complets

Temps réel en secondes, démarrage compris, médiane des exécutions.

ProgrammeOTP JITClause -O2Clause ÷ OTP
bench_datagenConstruit en masse listes, tuples, maps, binaries et grands entiers8,545,720,67×
bench_dataprocTri, fold, mises à jour de maps, filtrage de binaries, conversions10,456,760,65×
bench_fileÉcriture et lecture de petits et grands fichiers, lecture par ligne6,956,240,90×
bench_gcProcessus éphémères, tas qui grossit puis rétrécit, données vivantes5,833,690,63×
bench_libraryLa parse transform de qlc à l'exécution, telle que qlc:q/1 l'utilise2,301,890,82×
bench_msgPing-pong, fan-in, anneau de processus et copie de gros messages5,693,280,58×
bench_socketÉcho TCP, connexions TCP et allers-retours UDP sur loopback5,994,570,76×

Progression

Moyenne géométrique du temps de Clause divisé par celui d'OTP pour chaque jour d'exécution enregistré. Les exécutions antérieures au 2026-10-21 n'étaient pas épinglées à un ensemble de processeurs ; une partie de l'évolution de ce jour-là vient donc de l'épinglage.

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×

Taille des exécutables

Taille en mégaoctets des programmes de test tels que Clause les construit à chaque niveau d'optimisation.

Programme-O0-O2-O2 --lto
bench_datagen9,90 Mo9,82 Mo9,82 Mo
bench_dataproc10,42 Mo10,01 Mo10,01 Mo
bench_file11,34 Mo10,59 Mo10,59 Mo
bench_gc9,89 Mo9,81 Mo9,81 Mo
bench_library10,24 Mo9,94 Mo9,95 Mo
bench_msg9,91 Mo9,82 Mo9,82 Mo
bench_socket11,58 Mo10,64 Mo10,65 Mo

Tailles en -O2 des 6 dernières exécutions des benchmarks, de la plus ancienne à la plus récente, un commit de Clause par exécution. Le tableau ci-dessous ajoute le total de tous les programmes bench_* et la taille du compilateur clau.

024681012 Mobench_datagen, 2026-10-20 7d7a2f2e: 6,29 Mobench_datagen, 2026-10-21 71ec52f8: 6,32 Mobench_datagen, 2026-10-23 dea68508: 6,33 Mobench_datagen, 2026-10-24 af105043: 6,33 Mobench_datagen, 2026-10-26 d6eafa72: 8,55 Mobench_datagen, 2026-10-30 f4e5f3e0: 9,82 Mo9.82bench_datagenbench_dataproc, 2026-10-20 7d7a2f2e: 6,62 Mobench_dataproc, 2026-10-21 71ec52f8: 6,64 Mobench_dataproc, 2026-10-23 dea68508: 6,65 Mobench_dataproc, 2026-10-24 af105043: 6,65 Mobench_dataproc, 2026-10-26 d6eafa72: 8,74 Mobench_dataproc, 2026-10-30 f4e5f3e0: 10,01 Mo10.01bench_dataprocbench_file, 2026-10-20 7d7a2f2e: 6,72 Mobench_file, 2026-10-21 71ec52f8: 6,75 Mobench_file, 2026-10-23 dea68508: 6,75 Mobench_file, 2026-10-24 af105043: 6,75 Mobench_file, 2026-10-26 d6eafa72: 9,20 Mobench_file, 2026-10-30 f4e5f3e0: 10,59 Mo10.59bench_filebench_gc, 2026-10-20 7d7a2f2e: 6,28 Mobench_gc, 2026-10-21 71ec52f8: 6,32 Mobench_gc, 2026-10-23 dea68508: 6,32 Mobench_gc, 2026-10-24 af105043: 6,32 Mobench_gc, 2026-10-26 d6eafa72: 8,54 Mobench_gc, 2026-10-30 f4e5f3e0: 9,81 Mo9.81bench_gcbench_library, 2026-10-26 d6eafa72: 9,30 Mobench_library, 2026-10-30 f4e5f3e0: 9,94 Mo9.94bench_librarybench_msg, 2026-10-20 7d7a2f2e: 6,29 Mobench_msg, 2026-10-21 71ec52f8: 6,32 Mobench_msg, 2026-10-23 dea68508: 6,33 Mobench_msg, 2026-10-24 af105043: 6,33 Mobench_msg, 2026-10-26 d6eafa72: 8,55 Mobench_msg, 2026-10-30 f4e5f3e0: 9,82 Mo9.82bench_msgbench_socket, 2026-10-20 7d7a2f2e: 6,39 Mobench_socket, 2026-10-21 71ec52f8: 6,42 Mobench_socket, 2026-10-23 dea68508: 6,43 Mobench_socket, 2026-10-24 af105043: 6,43 Mobench_socket, 2026-10-26 d6eafa72: 9,33 Mobench_socket, 2026-10-30 f4e5f3e0: 10,64 Mo10.64bench_socket
  • 2026-10-207d7a2f2e
  • 2026-10-2171ec52f8
  • 2026-10-23dea68508
  • 2026-10-24af105043
  • 2026-10-26d6eafa72
  • 2026-10-30f4e5f3e0
DateCommitTous les programmes bench_*clau
2026-10-207d7a2f2e38,59 Mo59,50 Mo
2026-10-2171ec52f838,78 Mo59,54 Mo
2026-10-23dea6850838,79 Mo59,54 Mo
2026-10-24af10504338,81 Mo59,65 Mo
2026-10-26d6eafa7262,21 Mo59,98 Mo
2026-10-30f4e5f3e070,63 Mo60,75 Mo

Configuration

Machine
Intel64 Family 6 Model 183 Stepping 1, GenuineIntel, 32 processeurs logiques, Windows 11 (10.0.26200)
Ensemble de processeurs
Cœurs de performance 0-15, 16 sur 32 processeurs logiques
Erlang/OTP
29, ERTS 17.1
Commit Clause
f4e5f3e0
Exécution
2026-10-30

OTP et Clause s'exécutent sur les mêmes processeurs : chaque programme de benchmark est épinglé aux cœurs de performance du processeur, si bien que sur un processeur hybride aucun noyau (kernel) ne tombe sur un cœur d'efficacité plus lent. Les deux gardent un ordonnanceur actif par processeur de cet ensemble, sans le lier à un processeur précis de l'ensemble.

Pour lancer les benchmarks vous-même, utilisez make benchmark ou make-benchmark.bat dans le dépôt Clause ; les notes de benchmark décrivent les programmes et les options. Notes de benchmark