Acelerando o código: não passe structs maiores que 16 bytes no AMD64
- Para melhorar o desempenho da linguagem Neat, foi alterada a forma de passar arrays: em vez de um único parâmetro de struct, passaram a ser usados três parâmetros de ponteiro.
- O motivo de os arrays de Neat serem mais lentos que os arrays da linguagem D era que o array, com 24 bytes, excedia 16 bytes e por isso os parâmetros eram passados de outra forma.
- Segundo a especificação da ABI SystemV AMD64, toda struct com mais de 16 bytes é passada por ponteiro.
Confirmando o problema com benchmarks
- Os benchmarks confirmaram a diferença de desempenho entre passar uma struct e passar campos individuais.
- Ao passar uma struct, é necessário alocar na pilha e copiar; ao passar campos individuais, eles são enviados diretamente por registradores SSE.
- Passar campos individuais mostrou desempenho cerca de 2 vezes melhor do que passar uma struct.
A escolha do projetista da linguagem
- Ao chamar uma API em C, é preciso seguir a ABI de C, mas tipos de alto nível usados internamente não precisam ser representados como structs.
- O projetista da linguagem pode decidir como arrays, tuplas e tipos soma serão passados.
- Passar separadamente os campos de tipos com mais de 16 bytes pode ajudar a melhorar o desempenho.
Opinião do GN⁺
- Este artigo é muito útil para desenvolvedores interessados em otimização de software.
- Ele mostra, especialmente ao desenvolver aplicações sensíveis a desempenho, que o tamanho da struct e a forma de passá-la podem ter impacto importante.
- Projetistas de linguagem e desenvolvedores de API podem usar essa informação para encontrar oportunidades de melhorar o desempenho.
1 comentários
Comentário do Hacker News
vec3(3xfloat) de 12 bytes para 16 bytes, então o motor gráfico foi submetido a benchmark. Descobriu-se que usar 16 bytes era mais rápido por se alinhar melhor a leituras de 8 bytes. Como resultado,vec3passou a ser usado comovec4. Recomenda-se sempre fazer benchmark do sistema como um todo.cdeclpadrão, structs maiores que 8 bytes não são passadas em registradores.struct Vectorpara uma referênciaconst struct Vector &. Muito código C++ com bugs de ponteiro usou ponteiros sem necessidade, quando passar por referência teria sido mais fácil e mais seguro.