Cópia estática
Copiado de docs/evidence/performance-lessons.md em https://github.com/poppy-team/aipo-lang (MIT). Fixado na revisão ce47c4e070404fc41722ccd8e2b7b808b99062a8, blob 91fbcf299f86f471f8ec982bf367d3037f31eaee. O repositório de origem permanece canônico; esta cópia é atualizada por um pull request de sincronização, não em tempo real.
Uma das maiores lições de engenharia do projeto Aipo é a disciplina de medição empírica: código que parece uma otimização no papel muitas vezes não gera ganho real quando submetido a rigorosos testes pareados.
Documentar os experimentos que foram revertidos é tão importante quanto celebrar as melhorias mantidas.
Durante a evolução da VM e do runtime, as seguintes otimizações foram comprovadas por medição com controle estatístico:
fields de 1.001,77ms para 718,20ms (redução de 28,31%).frames.last() nos acessos a variáveis locais, gerando reduções estáveis de -3,71% em arithmetic, -6,65% em fields e -4,17% em recursion.SetField: Value de forma determinística para estruturas não protegidas (unguarded), mantendo a semântica de rollback intacta.Sete hipóteses de otimização foram minuciosamente implementadas, testadas com o script pareado scripts/perf/paired.sh e revertidas após os dados confirmarem ausência de ganho demonstrável:
| Experimento | Hipótese Técnica | Resultado Observado | Decisão |
|---|---|---|---|
| 1. Cache de Metadados de Métodos | Evitar buscas repetidas na tabela de métodos | Sem variação estatisticamente significante | Revertido |
2. Pool de Nomes (Rc<str> vs Enum) | Reduzir alocações na resolução de identificadores | Custo de chaveamento superou a economia | Revertido |
| 3. Guardedness na Entrada de Cache | Evitar checagens dinâmicas redundantes | Neutro no wall-clock | Revertido |
4. Flags fixed por Slot | Bitmask compacta para campos imutáveis | Ruído dentro da margem de erro (±2%) | Revertido |
| 5. Cache de Tipos Guarded | Reutilização de esquemas de proteção | Ganho nulo frente à contenção de cache L2 | Revertido |
6. Layout Denso de StructInstance | Vetor contíguo para campos primitivos | Deslocamento de offset oscilou entre +7% e neutro | Revertido |
| 7. Despacho de Método Sem Alocar | Evitar ponteiros intermediários | Compilador já eliminava alocações no caminho feliz | Revertido |
Uma calibração com número fixo de iterações revelou um fato crucial:
VmFault (72 bytes).Result produziu ganho nulo (-0,16%), comprovando que o LLVM já afundava a montagem da falha para fora do caminho feliz (cold branch).Para evitar retrabalho em máquinas sujeitas a ruído e contenção de CPU:
arithmetic é o controle obrigatório, por não depender de structs nem de despacho dinâmico de métodos.RUSAGE_CHILDREN) é a única métrica confiável. Wall-clock em ambiente concorrido produz falsos positivos.A trilha de micro-otimização do interpretador foi formalmente encerrada. Qualquer reabertura futura exigirá hardware dedicado e foco em mudanças arquiteturais macro (Call0..Call4, GetLocal8 ou jump tables com threaded dispatch).