- El intérprete con tail calling de CPython muestra un rendimiento aproximadamente un 15% superior al método anterior en entornos Windows x86-64
- También se confirmó una mejora de rendimiento de alrededor del 5% en macOS AArch64 (XCode Clang), y en Windows se aprovecha una función experimental de MSVC 2026
- En los benchmarks de pyperformance, la mayoría de las pruebas mostraron mejoras de velocidad, y algunas mejoraron hasta un 78%
- Se analiza que las principales causas de la mejora son el reinicio de las heurísticas de optimización del compilador y la mejora del inlining
- Cuando se lance oficialmente Python 3.15, se aplicará por defecto en compilaciones basadas en Visual Studio 2026
Mejora de rendimiento del intérprete con tail calling
- Se midió que el intérprete con tail calling de CPython es aproximadamente un 15% más rápido que el intérprete switch-case en Windows x86-64
- Según pyperformance, la media geométrica mejora entre un 15% y un 16%
- Algunos benchmarks mejoraron la velocidad hasta un 78%, mientras que unos pocos fueron un 60% más lentos
- En macOS AArch64 (XCode Clang) se confirmó una mejora de rendimiento de alrededor del 5%
- Estos resultados son válidos bajo el supuesto de que no haya cambios durante el ciclo de desarrollo de Python 3.15
Comparación de la estructura del intérprete
- Las formas de implementación de intérpretes en C se dividen en tres tipos: switch-case, computed goto y tail-call threaded
- switch-case: manejo de bifurcaciones por instrucción
- computed goto: extensión de GCC/Clang que salta directamente a la dirección de bifurcación
- tail-call threaded: separa cada manejador de bytecode en una función y hace tail call a la siguiente función
- En el pasado, los compiladores de C no garantizaban la optimización de tail call, por lo que existía riesgo de desbordamiento de pila
- Los atributos
__attribute__((musttail)) de Clang y [[msvc::musttail]] de MSVC permiten forzar el tail call
Resultados de compilación con MSVC 2026 para Windows
- En una compilación de CPython usando funciones experimentales de MSVC, la mayoría de los benchmarks mejoraron su velocidad
- Resultados de ejemplo:
spectralnorm: 1.48x
nbody: 1.35x
bm_django_template: 1.18x
xdsl: 1.14x
- Se reflejó oficialmente en el documento “What’s New” de Python 3.15
- En compilaciones con Visual Studio 2026 (MSVC 18), ya se puede usar el intérprete con tail calling
- Las bibliotecas puras de Python son aproximadamente un 15% más rápidas, y los scripts pequeños hasta un 40%
Causas de la mejora de rendimiento
- El tail calling reinicia las heurísticas de optimización del compilador, induciendo una generación de código más eficiente
- El bucle tradicional del intérprete de CPython estaba compuesto por una sola función de unas 12,000 líneas, lo que hacía frecuentes los fallos en la optimización de inlining
- Hubo muchos casos en los que el compilador rechazó hacer inlining para evitar aumentar el tamaño del código
- Con el enfoque de tail calling, las funciones se separan y las funciones simples pueden procesarse con inline
- Por ejemplo, una función sencilla como
PyStackRef_CLOSE_SPECIALIZED puede ser inlineada
- También se reportó el mismo fenómeno en compilaciones con PGO (optimización guiada por perfil)
Cómo compilar y usarlo
- Por ahora, solo es posible compilar desde el código fuente
- En el futuro, cuando el desarrollo de Python 3.15 se estabilice, se distribuirán binarios oficiales
1 comentarios
Comentarios en Hacker News
Es un ejemplo que muestra la diferencia en la definición de los atributos
musttailypreserve_noneentre MSVC y ClangEstos atributos deben colocarse en el declarador de la función, y no funcionan en la posición de especificador de función
Enlace al código relacionado
Da la impresión de que Microsoft solo informa de este tipo de funciones no públicas a los proyectos que considera importantes
[[msvc::musttail]]en realidad era un atributo documentado oficialmenteVa a corregir la entrada del blog para reflejarlo
Comentario relacionado en HN
Después de leer el texto, considera que está bien porque el enfoque priorizó la transparencia y la retroalimentación rápida
Sería aún mejor con validación de compiladores cruzados o una auditoría independiente, pero cree que se puede confiar gracias a la transparencia total del autor
Como se publicó temprano, Nelson encontró el bug de Clang 19 y eso permitió corregirlo antes del lanzamiento oficial
Esta vez tiene más confianza porque hay dos mejoras: la lógica de dispatch y el inlining
MSVC puede convertir un intérprete basado en switch-case en threaded code bajo ciertas condiciones, pero CPython es demasiado complejo para que esa optimización aplique
En cambio, el enfoque con tail call le da más control al autor del código C
Referencias relacionadas: condiciones de threaded code en MSVC, issue sobre forceinline
Antes, optimizaciones como tail duplication variaban según el criterio del compilador, pero ahora el intérprete puede expresar directamente la forma de código máquina que quiere
Enlace a una discusión anterior
Eligió Python porque el ecosistema de VS es demasiado pesado frente a C#/MAUI
Tkinter le resultó incómodo, y Qt tenía una curva de aprendizaje alta, así que usa la combinación wxGlade + wxPython
Solo necesita una única dependencia instalable con pip y le gusta la sensación Pythonic
Le alegran las mejoras en el runtime de Windows
Si haces la UI rápido con QtCreator y luego conectas la lógica en Python, la velocidad de desarrollo es muy alta
A diferencia de Tkinter o Qt, no usa retained mode sino immediate mode, así que es especialmente útil para herramientas internas
Proyecto imgui_bundle
Dice que pensaba que ya estaría escrito en ensamblador para las principales ISA
[[msvc::musttail]]es un atributo muy reciente, añadido en MSVC 14.50 (lanzado el mes pasado), y el equipo de CPython lo aprovechó en cuestión de semanas para mejorar el rendimientoDocumentación de MSVC musttail
Como Guido priorizó la simplicidad del código, la adopción de un JIT llegó tarde, y después aparecieron intentos como PEP 744 (JIT Compilation)
La optimización en ensamblador es una pesadilla de mantenimiento, y el verdadero cuello de botella de Python es el sistema de empaquetado
PyPy es rápido gracias al JIT, pero no es compatible con extensiones en C
El modelo de hilos de Python también dificulta las optimizaciones
En cambio, JS es monohilo y más simple
Como Python puede evitar parte del problema con extensiones en C, ha habido menos presión para optimizar el propio CPython
Además, CPython no puede romper compatibilidad por su enorme ecosistema de extensiones en C
En cambio, V8 pudo cambiar libremente su estructura interna
Además, debe mantener un ABI C estable, lo que dificulta que un JIT analice el código con libertad
Menciona el caso de PyPy, que sufrió bastante para ajustarse a esas restricciones
Además, JS solo necesita soportar JS puro, mientras que Python tiene que mantener su ecosistema de extensiones externas, lo que impone muchas restricciones a la optimización
Comparte que ha medido rendimiento de librerías JS con
mitataPR de optimización de Immer JS
Explicación en Wikipedia, ejemplo en Matplotlib
Visualiza la distribución de forma simétrica, pero se critica que el suavizado puede distorsionar la distribución real y que desperdicia espacio
En esta discusión de HN también hubo opiniones de que el half-violin plot es mejor
Imagen de ejemplo
Satiriza rasgos típicos de textos de IA, como párrafos cortos, tono demasiado positivo y poca profundidad