Tornando os binários Rust menores por padrão
Os binários “hello world” do Rust vêm sendo criticados há muito tempo por terem vários megabytes, o que muitos veem como uma contradição à reputação de “abstrações de custo zero” e algo que afasta desenvolvedores acostumados a executáveis C pequenos. Uma mudança recente no Cargo fará com que os símbolos de debug da biblioteca padrão sejam removidos por padrão quando nenhum debuginfo for solicitado, reduzindo binários de release típicos em cerca de 90% (para algumas centenas de kilobytes) enquanto mantém símbolos completos disponíveis para builds de desenvolvimento. Comentadores debatem o quanto o tamanho do binário importa em sistemas modernos versus ambientes embarcados e restritos, e ponderam essa mudança frente a trade-offs sobre backtraces, comportamento de panic, otimização em tempo de link e o design do Rust com linking estático e sem ABI estável.
Primeiras impressões e tamanho do binário como sinal
- Vários comentaristas dizem que um “hello world” de vários MB pode afastar avaliadores imediatamente, especialmente desenvolvedores C/C++ acostumados a binários pequenos.
- Outros argumentam que o tamanho inicial é sobretudo um custo fixo e não prevê o crescimento marginal à medida que os programas ficam maiores.
- Há debate sobre se o “tamanho do hello world” é um bom proxy do custo de abstração: alguns acham que sim em geral, enquanto outros observam que o salto do Rust de 4MB para 400KB (via remoção de símbolos de debug) mostra que o tamanho pode ser dominado por escolhas de tooling, não por overhead da linguagem.
O que há em um “hello world” Rust de ~415KB?
- Principais contribuintes citados:
- Suporte a backtrace: caminhada de pilha, parsing de DWARF, demangling de nomes, tratamento de caminhos, seções ELF comprimidas.
- Maquinário de I/O: stdout com buffer, sincronização, alocador, implementação de vetores.
- Formatação, especialmente floats, que dependem de tabelas de dados substanciais e tratamento de casos-limite.
- O linking estático de std (por portabilidade e pela ausência de uma ABI estável de Rust) naturalmente puxa mais coisas do que um programa C ligado dinamicamente.
Remoção de info de debug e stack traces
- Comportamento anterior: binários de release ainda incorporavam a info de debug de std, inflando o “hello world” para ~4MB.
- Novo padrão:
strip = "debuginfo"quando nenhum debuginfo é solicitado, removendo o DWARF de std, mas preservando o comportamento em runtime. - Consequência: backtraces de release perdem números de linha, mas comentaristas observam que eles raramente eram úteis sem debug info para o código do usuário.
- Alguns temem perder símbolos; outros enfatizam que debug info externo/dividido e
debuginfodsão o padrão correto de longo prazo.
Ajuste manual de tamanho e trade-offs
- Receita comum:
opt-level="z",lto=true,codegen-units=1,panic="abort", além de construir std companic_abort/panic_immediate_aborte fazer stripping. Isso pode chegar a dezenas de KB. - Trade-offs discutidos:
- Compilação mais lenta e, às vezes, execução mais lenta em builds otimizados para tamanho.
panic="abort"remove unwinding, destruidores em panic e alguns padrões de recuperação; comparado a-fno-exceptions.- Fazer stripping de tudo (não só debuginfo) pode quebrar binários;
--strip-unneededé destacado.
Quando o tamanho do binário importa (e quando não importa)
- Alguns dizem que qualquer coisa abaixo de 1MB é suficiente para a maioria dos usos em desktop/servidor; desempenho e tempo de compilação importam mais.
- Outros, especialmente em embedded/Linux em dispositivos restritos e contêineres com poucos recursos, enfatizam que kilobytes somam e podem ser uma restrição rígida.
- Há também um ângulo ambiental/eficiência: binários grandes e trabalho desperdiçado são vistos como inchaço sistêmico.
Linkagem estática vs dinâmica e estabilidade de ABI
- Rust usa std estaticamente por padrão porque sua ABI é instável; bibliotecas Rust dinâmicas são possíveis, mas desencorajadas.
- A ABI C pode ser usada para objetos compartilhados estáveis, chamáveis por outras linguagens.
- Rust embarcado frequentemente usa
#![no_std], o que contorna grande parte desse overhead; mas muitos sistemas Linux “embarcados” ainda se preocupam com o tamanho de binários com std completo.
Processo do projeto e atitudes
- Alguns criticam o fato de que esse problema “óbvio” tenha permanecido por ~7 anos, vendo isso como sinal de foco em recursos em vez de fundamentos.
- Outros enquadram isso como priorização normal: poucos usuários estavam bloqueados, havia workarounds, e muitos problemas mais urgentes competiam por atenção.
- Há amplo acordo de que melhorar os padrões, mesmo para questões com workarounds conhecidos, é importante para o polimento e a percepção do Rust.