Clause

Benchmarks

O Clause comparado com o Erlang/OTP numa única máquina: os mesmos programas Erlang, compilados pelo erlc e pelo clau -O2, medem o tempo dos seus kernels após uma chamada de aquecimento. Estes números mudam a cada otimização.

Média geométrica dos tempos dos kernels, Clause -O2 face ao JIT da BEAM (OTP)
1,49× mais rápido em média
Kernels em que o Clause é mais rápido
31 / 31
Média geométrica em 2026-10-12, a primeira execução registada
20,2×

Tempos dos kernels

Mediana de 3 execuções em milissegundos. A barra mostra o tempo do Clause dividido pelo do OTP numa escala logarítmica.

Clause mais rápidoOTP mais rápido🔺 As execuções variaram mais de metade da mediana.
KernelOTP JITClause -O2Clause ÷ OTP
Geração de dados
bigint_factorialCalcula o fatorial de 3000 com inteiros grandes, 330 vezes1.620,17212,760,13×
binary_appendAcrescenta 10 000 inteiros de 32 bits a um binary crescente, 23 000 vezes1.080,93802,570,74×
list_of_tuplesConstrói uma lista de 200 000 tuplos pequenos, 260 vezes1.467,601.128,440,77×
list_to_tupleConverte listas de 1000 elementos em tuplos, 170 000 vezes1.586,381.278,690,81×
map_putInsere 2000 chaves inteiras num map, uma a uma, 4900 vezes1.605,841.519,510,95×
string_buildConstrói 20 000 cadeias a partir de inteiros e átomos, 1000 vezes1.044,38720,730,69×
Processamento de dados
binary_matchSoma 20 000 inteiros de 32 bits extraídos de um binary, 49 000 vezes1.272,631.071,470,84×
comprehensionComprehension que filtra e duplica 20 000 inteiros, 15 000 vezes1.407,08893,850,64×
int_to_listConverte 20 000 inteiros em cadeias e de volta, 2000 vezes908,70412,790,45×
map_foldlAplica map e depois fold a 20 000 inteiros, 4500 vezes1.500,771.113,040,74×
map_updateIncrementa cada valor de um map de 500 chaves, 24 000 vezes1.151,28669,970,58×
small_mapAtualiza 80 milhões de vezes um pequeno map de estado1.486,441.061,830,71×
sortOrdena uma lista de 20 000 inteiros aleatórios, 600 vezes1.112,37466,550,42×
term_to_binaryCodifica e descodifica um termo aninhado grande, 4300 vezes1.433,291.071,950,75×
E/S de ficheiros
large_readLê um ficheiro de 16 MB em blocos de 64 KB, 370 vezes1.444,151.007,930,70×
large_writeEscreve um ficheiro de 16 MB em blocos de 64 KB, 200 vezes1.019,80989,090,97×
read_fileLê um ficheiro inteiro de 16 MB numa só chamada, 330 vezes1.485,521.483,031,00×
read_lineLê linha a linha um ficheiro de texto de 20 000 linhas, 52 vezes1.522,071.467,280,96×
small_filesEscreve, relê e apaga 500 ficheiros pequenos, 11 vezes1.209,751.116,400,92×
Recolha de lixo
explicit_collectForça a recolha de lixo com 10 000 tuplos vivos, 5100 vezes1.547,98639,850,41×
grow_shrinkFaz crescer o heap com uma lista de 200 000 elementos e larga-a, 300 vezes1.041,41861,750,83×
long_lived_churnMantém uma janela deslizante de 10 000 elementos vivos no meio de lixo, 370 vezes1.351,271.095,820,81×
short_processesLança 5000 processos efémeros que geram lixo cada um, 69 vezes1.667,281.037,980,62×
Bibliotecas
qlcExecuta a transformação qlc sobre 27 consultas e 3 módulos, 11 vezes1.873,721.714,660,92×
Troca de mensagens
fan_in100 processos enviam 1000 mensagens cada um a um só, 25 vezes1.402,68391,780,28×
large_messageEnvia uma lista de 100 000 elementos a outro processo e de volta, 560 vezes1.063,94789,040,74×
ping_pongTroca uma mensagem entre dois processos 2 milhões de vezes1.504,97904,200,60×
ringPassa um testemunho 3050 vezes por um anel de 1000 processos1.438,211.099,660,76×
Sockets em loopback
tcp_connectAbre 900 ligações TCP em loopback, com eco de 25 mensagens de 1 KB em cada1.418,851.047,850,74×
tcp_echoEco de 30 000 mensagens de 1 KB por TCP em loopback1.455,621.136,060,78×
udp_round_tripIda e volta de um datagrama de 1 KB, 27 900 vezes, por UDP em loopback1.458,071.196,820,82×

Programas completos

Tempo real em segundos, incluindo o arranque, mediana das execuções.

ProgramaOTP JITClause -O2Clause ÷ OTP
bench_datagenConstrói em massa listas, tuplos, maps, binaries e inteiros grandes8,545,720,67×
bench_dataprocOrdenação, fold, atualização de maps, matching de binaries e conversões10,456,760,65×
bench_fileEscrita e leitura de ficheiros pequenos e grandes, leitura por linhas6,956,240,90×
bench_gcProcessos efémeros, heap que cresce e encolhe, dados vivos5,833,690,63×
bench_libraryA parse transform do qlc em runtime, como qlc:q/1 a usa2,301,890,82×
bench_msgPingue-pongue, fan-in, anel de processos e cópia de mensagens grandes5,693,280,58×
bench_socketEco TCP, ligações TCP e idas e voltas UDP em loopback5,994,570,76×

Progresso

Média geométrica do tempo do Clause dividido pelo do OTP em cada dia com execuções registadas. As execuções anteriores a 2026-10-21 não estavam fixadas a um conjunto de CPUs, pelo que parte da alteração desse dia se deve à fixação.

DataCommitClause ÷ 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×

Tamanho dos executáveis

Tamanho em megabytes dos programas de teste tal como o Clause os constrói em cada nível de otimização.

Programa-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

Tamanhos com -O2 das últimas 6 execuções dos benchmarks, da mais antiga para a mais recente, um commit do Clause por execução. A tabela abaixo acrescenta o total de todos os programas bench_* e o tamanho do compilador clau.

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
DataCommitTodos os programas bench_*clau
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

Configuração

Máquina
Intel64 Family 6 Model 183 Stepping 1, GenuineIntel, 32 CPUs lógicos, Windows 11 (10.0.26200)
Conjunto de CPUs
Núcleos de desempenho 0-15, 16 de 32 CPUs lógicos
Erlang/OTP
29, ERTS 17.1
Commit do Clause
f4e5f3e0
Execução
2026-10-30

O OTP e o Clause correm nos mesmos CPUs: cada programa de benchmark está fixado aos núcleos de desempenho do processador, pelo que num CPU híbrido nenhum kernel acaba num núcleo de eficiência mais lento. Ambos mantêm um escalonador ativo por cada CPU do conjunto, sem o vincular a um CPU concreto dentro dele.

Para executar os benchmarks, use make benchmark ou make-benchmark.bat no repositório do Clause; as notas de benchmarks descrevem os programas e as opções. Notas de benchmarks