O retorno dos ponteiros de frame
Compensações de desempenho dos ponteiros de frame
- Os principais custos discutidos: um registrador de uso geral a menos (grave em x86 de 32 bits, menor em x86_64 e outras ISAs) e instruções extras de prólogo/epílogo que podem aumentar o tamanho de funções pequenas e frequentemente chamadas e pressionar o I‑cache.
- As regressões de desempenho relatadas variam muito: alguns veem ~1–3% em apps reais; um teste da Phoronix relatou penalidade de média geométrica de ~14%; medições do kernel citaram 5–10% para algumas cargas de trabalho; outros afirmam “menos de 1%” em nível de distro com toolchains modernas.
- Há discordância sobre a qualidade dos benchmarks: alguns chamam benchmarks de bancos de dados de “microbenchmarks”, outros argumentam que são testes end-to-end realistas. Consenso de que o impacto depende da carga de trabalho e não é caracterizado de forma universal.
- x86 de 32 bits ainda é considerado particularmente carente de registradores; para muitas outras arquiteturas, o registrador perdido é visto como negligenciável.
Profiling, depuração e por que os FPs importam
- Muitos consideram essenciais traces de stack confiáveis e de baixo overhead para profiling de CPU, memória e, especialmente, off-CPU, além de rastreamento de execução.
- Sem ponteiros de frame, o perf do kernel precisa copiar grandes blocos de stack e fazer o unwind depois, causando overhead de CPU, memória e disco e exigindo pacotes de debug.
- Desenvolvedores argumentam que “é só recompilar com FPs” é irrealista quando sistemas inteiros e bibliotecas de terceiros estão envolvidos, e torna impraticável pedir traces aos usuários finais.
- Alguns observam que profiling melhorado gerou acelerações de >10–20% em software real, compensando facilmente um pequeno overhead global de FP.
DWARF e abordagens alternativas de unwind
- O unwind DWARF/.eh_frame é descrito como flexível, mas complexo e lento para amostragem de alta taxa ou profiling off-CPU. O caminho atual do perf via DWARF é especialmente custoso por causa da cópia da stack.
- Outros afirmam que o DWARF pode ser tornado rápido com pré-carregamento e cache de informações de unwind, e apontam para profilers baseados em eBPF que convertem tabelas em formatos eficientes no kernel.
- JVM/JIT e outros runtimes de alto nível continuam difíceis: unwind personalizado, stacks mistas nativas/gerenciadas e atividade intensa de JIT tornam soluções apenas com DWARF frágeis ou caras demais em escala.
Padrões, políticas de distro e quem paga o custo
- O debate se concentra em qual deve ser o padrão para kernels, libc e builds de distro.
- Um lado: habilitar FPs globalmente para que o profiling em nível de sistema “funcione automaticamente”, permitindo otimização contínua e análise posterior de releases em produção.
- Outro lado: a maioria dos usuários nunca faz profiling; alguns pontos percentuais de perda em milhões de dispositivos e servidores não são triviais em energia e custo; código sensível a desempenho pode habilitar FPs apenas em builds de desenvolvimento.
- As sugestões incluem atributos por função (com ressalvas), builds separados de libc “dev” versus “end-user” e uso de sistemas baseados em source ou Nix/Guix para alternar a política em nível de sistema.
Segurança e ideias de arquitetura
- Stacks separadas ou espelhadas para endereços de retorno são discutidas como um design mais limpo e seguro, mas o hardware atual e a compatibilidade de ABI limitam a implantação prática.
- Alguns propõem banir
alloca()em vez de pagar o custo de FP; outros retrucam que FPs ao menos são implantáveis agora, enquanto mudanças mais radicais não são.