- O interpretador com tail-calling do CPython apresentou desempenho cerca de 15% superior ao método anterior no ambiente Windows x86-64
- Também foi confirmado um ganho de desempenho de cerca de 5% no macOS AArch64 (XCode Clang), e no Windows são usados recursos experimentais do MSVC 2026
- Nos benchmarks do pyperformance, a maioria dos testes mostrou aumento de velocidade, com alguns chegando a 78% de melhoria
- A principal causa do ganho de desempenho foi analisada como sendo o reset das heurísticas de otimização do compilador e melhorias de inlining
- No lançamento oficial do Python 3.15, isso deverá ser aplicado por padrão em builds baseadas no Visual Studio 2026
Melhoria de desempenho do interpretador com tail-calling
- Foi medido que o interpretador com tail-calling do CPython é cerca de 15% mais rápido no Windows x86-64 do que o interpretador switch-case tradicional
- Segundo o pyperformance, a média geométrica melhorou entre 15% e 16%
- Alguns benchmarks tiveram ganho de velocidade de até 78%, enquanto poucos casos ficaram 60% mais lentos
- No macOS AArch64 (XCode Clang), também foi confirmado um ganho de desempenho de cerca de 5%
- Esses resultados são válidos sob a premissa de que não haja mudanças durante o ciclo de desenvolvimento do Python 3.15
Comparação da estrutura do interpretador
- As implementações de interpretador em C podem ser divididas em três tipos: switch-case, computed goto e tail-call threaded
- switch-case: trata o desvio de acordo com cada instrução
- computed goto: extensão de GCC/Clang que salta diretamente para o endereço de desvio
- tail-call threaded: separa cada manipulador de bytecode em uma função e faz tail call para a próxima função
- No passado, como os compiladores C não garantiam otimização de tail call, havia risco de stack overflow
- Os atributos
__attribute__((musttail)) do Clang e [[msvc::musttail]] do MSVC agora permitem forçar tail call
Resultados do build com MSVC 2026 para Windows
- No build do CPython usando recursos experimentais do MSVC, a maioria dos benchmarks mostrou ganho de velocidade
- Exemplos de resultados:
spectralnorm: 1,48x
nbody: 1,35x
bm_django_template: 1,18x
xdsl: 1,14x
- Isso foi oficialmente refletido na documentação “What’s New” do Python 3.15
- Em builds com Visual Studio 2026 (MSVC 18), será possível usar o interpretador com tail-calling
- Bibliotecas Python puras terão ganho de cerca de 15%, e scripts pequenos podem ficar até 40% mais rápidos
Causa do ganho de desempenho
- O tail-calling reinicializa as heurísticas de otimização do compilador, induzindo uma geração de código mais eficiente
- O loop tradicional do interpretador do CPython é composto por uma única função com cerca de 12.000 linhas, o que causa falhas frequentes na otimização por inlining
- Há muitos casos em que o compilador recusa o inlining para evitar aumento do tamanho do código
- No método com tail-calling, as funções são separadas, permitindo que funções simples sejam tratadas com inline
- Como exemplo, funções simples como
PyStackRef_CLOSE_SPECIALIZED passam a ser inline
- O mesmo fenômeno também foi relatado em builds com PGO (otimização guiada por perfil)
Como compilar e usar
- No momento, só é possível fazer build a partir do código-fonte
- Quando o desenvolvimento do Python 3.15 estiver mais estável, está prevista a distribuição oficial de binários
1 comentários
Comentários do Hacker News
É um exemplo que mostra a diferença na definição dos atributos
musttailepreserve_noneentre MSVC e ClangEsses atributos precisam ser colocados no declarador da função e não funcionam na posição de especificador da função
Link para o código relacionado
Passa a impressão de que a Microsoft só informa esse tipo de recurso não público a projetos que considera importantes
[[msvc::musttail]]era de fato um atributo oficialmente documentadoVou atualizar o post do blog para refletir isso
Comentário relacionado no HN
Ao ler o texto, conclui que a abordagem priorizou transparência e feedback rápido, então parece aceitável
Seria melhor ainda com validação entre compiladores ou auditoria independente, mas considera confiável graças à transparência total do autor
Como foi divulgado cedo, Nelson encontrou o bug do Clang 19, e isso permitiu corrigir antes do lançamento oficial
Desta vez, há mais confiança porque existem duas melhorias: lógica de dispatch e inlining
O MSVC pode transformar um interpretador com switch-case em threaded code sob certas condições, mas o CPython é complexo demais para que essa otimização seja aplicada
Em vez disso, a abordagem com tail call dá mais controle ao autor do código C
Referências relacionadas: condições do threaded code no MSVC, issue sobre forceinline
Antes, otimizações como tail duplication variavam conforme a decisão do compilador, mas agora o próprio interpretador consegue expressar diretamente a forma de código de máquina desejada
Link para discussão anterior
Escolheu Python porque o ecossistema do VS é pesado demais em comparação com C#/MAUI
Achou Tkinter incômodo, e Qt exigia curva de aprendizado alta, então está usando a combinação wxGlade + wxPython
Só precisa de uma dependência única instalável via pip, e gosta da sensação mais Pythonic
Fica feliz com as melhorias no runtime do Windows
Com o QtCreator dá para montar a UI rapidamente e ligar a lógica em Python, então a velocidade de desenvolvimento é muito alta
Em vez do modelo retained mode de Tkinter ou Qt, usa a abordagem immediate mode, o que é especialmente útil para ferramentas internas
projeto imgui_bundle
Diz que achava que já estaria escrito em assembly para as principais ISAs
[[msvc::musttail]]é um atributo novíssimo, adicionado no MSVC 14.50 (lançado no mês passado), e a equipe do CPython o aproveitou em poucas semanas para obter ganhos de desempenhoDocumentação do musttail no MSVC
Guido priorizou a simplicidade do código, por isso a adoção de JIT demorou, e depois surgiram tentativas como a PEP 744 (JIT Compilation)
Otimização em assembly é um pesadelo de manutenção, e o verdadeiro gargalo do Python é o sistema de empacotamento
O PyPy é rápido graças ao JIT, mas não é compatível com extensões em C
O modelo de threads do Python também dificulta otimizações
Já o JS é mais simples por ser single-threaded
Como Python pode contornar isso com extensões em C, houve menos pressão para otimizar o próprio CPython
Além disso, o CPython não pode quebrar compatibilidade por causa do vasto ecossistema de extensões em C
Já o V8 pôde mudar livremente sua estrutura interna
Além disso, precisa manter uma ABI C estável, o que dificulta para um JIT analisar o código livremente
Cita o caso do PyPy, que sofreu para atender essas restrições
Além disso, JS só precisa suportar JS puro, enquanto Python precisa manter o ecossistema de extensões externas, o que impõe muitas limitações de otimização
Compartilha que já usou
mitatapara medir desempenho de bibliotecas JSPR de otimização do Immer JS
Explicação na Wikipedia, exemplo no Matplotlib
Ele visualiza a distribuição de forma simétrica, mas há críticas de que o suavizamento pode distorcer a distribuição real e desperdiçar espaço
Na discussão do HN, também houve quem defendesse que o half-violin plot é melhor
Imagem de exemplo
E satiriza características típicas de texto gerado por IA, como parágrafos curtos, tom excessivamente positivo e pouca profundidade