Comparando o tempo de compilação de Rust e C++
(quick-lint-js.com)Li um texto interessante em outro lugar e gostaria de compartilhá-lo.
Rust e C++ costumam ser comparados em vários aspectos. No entanto, era difícil comparar diretamente o tempo de compilação, porque é raro que o mesmo projeto seja escrito nas duas linguagens. O quick-lint-js, um projeto escrito em C++, reescreveu parte do código em Rust para comparar os tempos de compilação. No entanto, o Windows ficou de fora do ambiente de compilação.
Critérios para o port
- Excluindo bibliotecas de terceiros
- Trabalho realizado em Linux e macOS
- Ampla suíte de testes
- FFI, ponteiros, contêineres padrão e personalizados, classes e funções utilitárias, I/O, concorrência, genéricos, macros, SIMD, herança, ...
Conclusão
- O tempo de compilação do Rust é parecido com o do C++ ou mais lento (pelo menos neste projeto)
- Rust exige escrever mais código do que C++
- Em builds completos, C++ é parecido ou mais rápido
- Em builds incrementais, às vezes é mais curto e às vezes mais longo (em alguns casos, muito mais longo)
- Foi decidido não portar o restante do quick-lint-js para Rust (talvez isso mude se houver melhora no tempo de build?)
4 comentários
Parece que também há bastante gente usando Rust por aqui. Fico curioso para saber em quais setores vocês trabalham.
Depois da primeira compilação, no C++, se você modificar arquivos
.cppisolados em vez de headers com muitas dependências, a compilação fica bem rápida; fico curioso para saber como isso é no Rust.Vi que isso já estava explicado em detalhes na seção de perguntas frequentes da documentação do Rust, então estou compartilhando aqui.
====================================
Parece que a compilação do Rust é lenta. Por que isso acontece?
Porque ele traduz o código para linguagem de máquina e faz otimizações. O Rust oferece abstrações de alto nível que são compiladas para código de máquina eficiente, e esse processo de tradução naturalmente leva tempo, especialmente quando há otimizações.
Ainda assim, o tempo de compilação do Rust não é tão ruim quanto pode parecer, e há motivos para acreditar que ele continuará melhorando. Ao comparar projetos de tamanho semelhante em C++ e Rust, o tempo para compilar o projeto inteiro geralmente é parecido. A principal razão para a sensação de que o Rust compila lentamente é que C++ e Rust têm modelos de compilação diferentes: no C++, a unidade de compilação é um arquivo, enquanto no Rust é um crate composto por vários arquivos. Por isso, durante o desenvolvimento, ao alterar um único arquivo em C++, o tempo de compilação pode cair muito mais do que no Rust. Atualmente, há um grande trabalho em andamento para refatorar o compilador Rust e possibilitar compilação incremental; quando isso for concluído, o tempo de compilação no Rust também deve melhorar, de forma semelhante ao modelo do C++.
Independentemente do modelo de compilação, há vários elementos no design da linguagem Rust que afetam o tempo de compilação.
Primeiro, o Rust tem um sistema de tipos relativamente complexo e precisa gastar um tempo de compilação nada desprezível para impor as restrições que tornam o Rust seguro em tempo de execução.
Segundo, o compilador Rust carrega uma dívida técnica antiga e, em especial, a qualidade do LLVM IR gerado não é muito boa, então o LLVM precisa gastar tempo para “corrigir” isso. No futuro, etapas de otimização e tradução baseadas em MIR talvez reduzam a carga que o compilador Rust impõe ao LLVM.
Terceiro, o fato de o Rust usar LLVM para geração de código é uma faca de dois gumes. Graças ao LLVM, o Rust entrega desempenho de execução de nível mundial, mas o LLVM é um framework enorme que não foi projetado com foco em tempo de compilação e é particularmente vulnerável a entradas de baixa qualidade.
Por fim, a estratégia do Rust de monomorphise tipos genéricos de forma semelhante ao C++ gera código rápido, mas tem o problema de exigir a geração de uma quantidade consideravelmente maior de código em comparação com outras estratégias de tradução. Esse inchaço de código pode ser trocado por vantagens e desvantagens de despacho dinâmico usando objetos de trait.
Uma coisa é certa: projetos em Rust consomem muito espaço em disco durante o build. Lembro de ter ficado surpreso ao ver que um projeto que usava mais de uma centena de bibliotecas acabou ocupando algo em torno de 2 GB...