L’interpréteur Windows x86-64 de Python 3.15 devrait être environ 15 % plus rapide
(fidget-spinner.github.io)- L’interpréteur à appels de fin (tail-calling) de CPython affiche sur Windows x86-64 des performances environ 15 % supérieures à la méthode précédente
- Un gain de performances d’environ 5 % a aussi été confirmé sur macOS AArch64 (XCode Clang), tandis que Windows exploite une fonctionnalité expérimentale de MSVC 2026
- Dans les benchmarks pyperformance, la plupart des tests montrent une amélioration de vitesse, certains allant jusqu’à 78 %
- La principale raison de ce gain de performances serait une réinitialisation des heuristiques d’optimisation du compilateur et une amélioration de l’inlining
- Lors de la sortie officielle de Python 3.15, cela devrait être activé par défaut dans les builds basés sur Visual Studio 2026
Amélioration des performances de l’interpréteur à appels de fin
- Il a été mesuré que l’interpréteur à appels de fin de CPython est environ 15 % plus rapide sous Windows x86-64 que l’interpréteur switch-case traditionnel
- Selon pyperformance, la moyenne géométrique progresse de 15 à 16 %
- Certains benchmarks gagnent jusqu’à 78 % en vitesse, tandis qu’un petit nombre deviennent 60 % plus lents
- Sur macOS AArch64 (XCode Clang), un gain de performances d’environ 5 % a été constaté
- Ces résultats restent valables à condition qu’aucun changement n’intervienne pendant le cycle de développement de Python 3.15
Comparaison des structures d’interpréteur
- Les implémentations d’interpréteur en C se répartissent en trois approches : switch-case, computed goto et tail-call threaded
- switch-case : traitement des branchements pour chaque instruction
- computed goto : extension GCC/Clang permettant de sauter directement à l’adresse de branchement
- tail-call threaded : séparation de chaque gestionnaire de bytecode dans une fonction, puis appel de fin vers la fonction suivante
- Par le passé, les compilateurs C ne garantissaient pas l’optimisation des appels de fin, d’où un risque de débordement de pile
- Les attributs
__attribute__((musttail))de Clang et[[msvc::musttail]]de MSVC permettent désormais de forcer les appels de fin
Résultats de build avec MSVC 2026 pour Windows
- Dans un build CPython utilisant une fonctionnalité expérimentale de MSVC, la plupart des benchmarks s’améliorent
- Exemples de résultats :
spectralnorm: 1,48xnbody: 1,35xbm_django_template: 1,18xxdsl: 1,14x
- Exemples de résultats :
- Cela a été officiellement intégré au document « What’s New » de Python 3.15
- L’interpréteur à appels de fin peut être utilisé dans les builds Visual Studio 2026 (MSVC 18)
- Les bibliothèques Python pures gagnent environ 15 % en vitesse, et les petits scripts jusqu’à 40 %
Causes du gain de performances
- Les appels de fin réinitialisent les heuristiques d’optimisation du compilateur, ce qui favorise une génération de code plus efficace
- La boucle d’interpréteur CPython actuelle se compose d’une fonction unique d’environ 12 000 lignes, ce qui entraîne fréquemment un échec de l’optimisation par inlining
- Le compilateur refuse souvent l’inlining pour éviter d’augmenter la taille du code
- Avec l’approche par appels de fin, les fonctions sont séparées, ce qui permet d’inliner les fonctions simples
- Par exemple, une fonction simple comme
PyStackRef_CLOSE_SPECIALIZEDpeut être inlinée
- Par exemple, une fonction simple comme
- Le même phénomène a également été observé dans les builds PGO (optimisation guidée par profil)
Méthode de build et d’utilisation
- Pour l’instant, seul le build depuis les sources est possible
- Dans un environnement Visual Studio 2026, build avec la commande suivante
$env:PlatformToolset = "v145" ./PCbuild/build.bat --tail-call-interp -c Release -p x64 --pgo
- Dans un environnement Visual Studio 2026, build avec la commande suivante
- Une distribution binaire officielle est prévue une fois le développement de Python 3.15 stabilisé
1 commentaires
Commentaires Hacker News
C’est un exemple montrant la différence de définition des attributs
musttailetpreserve_noneentre MSVC et ClangCes attributs doivent être placés sur le déclarateur de fonction et ne fonctionnent pas à l’emplacement des spécificateurs de fonction
Lien vers le code concerné
Cela laissait entendre que Microsoft ne révèle ce genre de fonctionnalités non publiques qu’aux projets qu’elle juge importants
[[msvc::musttail]]était en fait un attribut officiellement documentéJe vais corriger le billet de blog en conséquence
Commentaire HN lié
Après lecture, juge l’approche correcte car elle privilégie la transparence et des retours rapides
Une validation par compilateurs croisés ou un audit indépendant serait encore mieux, mais estime cela fiable grâce à la transparence totale de l’auteur
Comme cela a été publié tôt, Nelson a trouvé le bug de Clang 19, ce qui a permis de le corriger avant la sortie officielle
Cette fois, il est plus confiant car il y a deux améliorations : la logique de dispatch et l’inlining
MSVC peut, dans certaines conditions, transformer un interpréteur
switch-caseen threaded code, mais CPython est trop complexe pour que cette optimisation s’appliqueÀ la place, l’approche par tail call donne davantage de contrôle à l’auteur du code C
Références associées : conditions du threaded code sous MSVC, problème lié à forceinline
Avant, des optimisations comme tail duplication variaient selon les décisions du compilateur, alors que désormais l’interpréteur peut exprimer directement la forme de code machine souhaitée
Lien vers la discussion précédente
A choisi Python parce que l’écosystème VS est bien trop lourd comparé à C#/MAUI
A trouvé Tkinter peu pratique et Qt trop coûteux à apprendre, et utilise donc la combinaison wxGlade + wxPython
N’a besoin que d’une dépendance unique installable via pip, et apprécie le ressenti Pythonic
Se réjouit des améliorations du runtime Windows
Avec QtCreator pour construire rapidement l’UI et Python pour y brancher la logique, la vitesse de développement est très élevée
Contrairement à Tkinter ou Qt, qui sont en retained mode, cela fonctionne en immediate mode, ce qui est particulièrement utile pour l’outillage interne
Projet imgui_bundle
Dit qu’il pensait qu’elle serait écrite en assembleur pour les principales ISA
[[msvc::musttail]]est un attribut tout récent ajouté dans MSVC 14.50, sorti le mois dernier, et l’équipe CPython l’a exploité en quelques semaines pour obtenir un gain de performancesDocumentation MSVC sur musttail
Guido a privilégié la simplicité du code, ce qui a retardé l’arrivée d’un JIT, puis des tentatives comme la PEP 744 (JIT Compilation) sont apparues
Les optimisations en assembleur sont un cauchemar de maintenance, et le vrai goulot d’étranglement de Python, c’est son système de packaging
PyPy est plus rapide grâce au JIT, mais n’est pas compatible avec les extensions C
Le modèle de threading de Python complique aussi l’optimisation
À l’inverse, JS est monothread, donc plus simple
Python pouvait contourner cela via des extensions C, ce qui a réduit la pression pour optimiser CPython lui-même
De plus, CPython ne peut pas casser la compatibilité à cause de son vaste écosystème d’extensions C
À l’inverse, V8 a pu modifier librement sa structure interne
Il doit aussi conserver une ABI C stable, ce qui rend l’analyse de code plus difficile pour un JIT
Mentionne les difficultés rencontrées par PyPy pour respecter ces contraintes
De plus, JS n’a qu’à prendre en charge du pur JS, alors que Python doit préserver tout un écosystème d’extensions externes, ce qui limite les optimisations
Partage qu’il a déjà mesuré les performances de bibliothèques JS avec
mitataPR d’optimisation d’Immer JS
Explication Wikipedia, exemple Matplotlib
Il visualise la distribution de manière symétrique, mais le lissage peut déformer la distribution réelle et certains lui reprochent de gaspiller de l’espace
Dans cette discussion HN, certains estimaient qu’un half-violin plot était préférable
Image d’exemple
Il tourne en dérision les traits typiques des textes IA : paragraphes courts, ton excessivement positif, manque de profondeur, etc.