- OxCaml, um superconjunto de OCaml da Jane Street, permite declarar ao compilador com
[@zero_alloc]a proibição de alocação no heap em toda a árvore de chamadas de uma função - Se ocorrer uma alocação no caminho de chamada declarado, isso aparece imediatamente como falha de compilação, o que ajuda a bloquear regressões mais rápido do que descobri-las depois com um profiler
- Em C, C++, Java, Go, C#, Rust, Zig, OCaml e outras, normalmente a abordagem principal é encontrar e reduzir alocações em hot paths com um profiler
- Código de hot path pode voltar a gerar alocações com pequenas mudanças, então, se o contexto da otimização original for esquecido, a mesma investigação acaba sendo repetida
- Convenções de passagem de allocator em Zig ou em parte do Rust moderno também ajudam, mas uma verificação do compilador é uma proteção mais direta do que uma convenção
O que [@zero_alloc] muda na gestão de alocações
- OxCaml é um superconjunto de OCaml da Jane Street e oferece suporte para afirmar que uma função não faz alocações no heap
- Ao adicionar
[@zero_alloc]a uma função, o compilador verifica não só essa função, mas toda a árvore de chamadas abaixo dela quanto a alocações no heap - Se houver uma alocação dentro da árvore de chamadas, o build falha e o compilador informa a ocorrência da alocação
- Pode ser possível criar verificações parecidas com análise estática, mas, entre linguagens mainstream, é raro ver esse tipo de recurso embutido no próprio compilador com base em resumos gerados
Diferença em relação à abordagem centrada em profiler
- Em outras linguagens, o normal é encontrar alocações com um profiler e depois remover ou reduzir essas alocações, especialmente dentro de loops executados milhões de vezes
- C, C++, Java, Go, C#, Rust, Zig e OCaml são listadas como exemplos dessa abordagem centrada em profiler
- Mudar apenas uma linha em um hot path pode reintroduzir alocações, e então é preciso voltar ao profiler para descobrir a causa
- Em Zig ou em parte do Rust moderno, é possível reduzir regressões evitando passar o allocator para as funções, mas isso depende de convenções
- A diferença de
[@zero_alloc]é que, em vez de análise posterior ou regras de equipe, o compilador bloqueia regressões de alocação no momento do build
1 comentários
Comentários no Lobste.rs
Entendi que o motivo de passar um allocator como argumento de função em Zig é impedir que funções que não recebem um allocator como argumento possam fazer alocações no heap; será que está certo?
Se a afirmação de que “convenções podem ser ignoradas” estiver realmente correta, parece diferente da intenção
Mesmo dentro de uma função, é possível criar um novo allocator, assim como fora dela
gift link: https://theconsensus.dev/p/2026/…
nogchá bastante tempo, e acho que ele tem uma semântica parecida no sentido de que o GC é quem cuida das alocaçõeshttps://dlang.org/phobos/dmd_nogc.html
Em certo momento também adicionaram, de forma experimental, exceções nogc, mas não verifiquei o estado atual nem a implementação
https://dlang.org/changelog/2.079.0.html#dip1008
Usar apenas core em Rust também é uma forma de evitar alocações
Essa abordagem acaba sendo mais próxima de “controle suas dependências” ou “verifique manualmente todo o grafo de chamadas”.
O foco do artigo está em como uma ferramenta como o compilador impõe estaticamente certas propriedades e oferece um fluxo de trabalho para encontrar de forma produtiva os pontos em que essas propriedades são violadas
D tem
@nogc, e depois disso a questão é usar apenas abstrações diretamente controláveis que tenham padrões de alocação clarosComo perdemos a capacidade de criar títulos de artigos descritivos, vale acrescentar: o ponto central é um recurso em que você marca uma função com
[@zero_alloc]e o compilador rejeita o programa se a árvore de chamadas dessa função tocar no heapFico curioso se esse tipo de abordagem também poderia ser aplicada a várias condições como “não lança exceções nem entra em panic”, “sem locks” e “sempre termina”