Facebook open source Cinder, un fork de CPython utilisé par Instagram

Facebook a publié le code source du Project Cinder, un fork de CPython 3.8.5, la principale implémentation de référence du langage de programmation Python. Cinder est utilisé dans l'infrastructure de production de Facebook pour alimenter Instagram et inclut des optimisations pour améliorer les performances.

Le code est publié pour discuter de la possibilité de porter les optimisations préparées sur le framework CPython principal et pour aider d'autres projets impliqués dans l'amélioration des performances de CPython. Facebook n'a pas l'intention de prendre en charge Cinder sous la forme d'un projet open source distinct et le code est présenté tel qu'il est utilisé dans l'infrastructure de l'entreprise, sans examen ni documentation supplémentaires. Ils n'essaient pas non plus de promouvoir Cinder comme alternative à CPython - l'objectif principal du développement est le désir d'améliorer CPython lui-même.

Le code Cinder est considéré comme assez fiable et testé dans des environnements de production, mais si des problèmes sont identifiés, vous devrez les résoudre vous-même, car Facebook ne garantit pas qu'il répondra aux messages d'erreur externes et aux demandes d'extraction. Dans le même temps, Facebook n'exclut pas une coopération constructive avec la communauté et est prêt à discuter des idées sur la manière de rendre Cinder encore plus rapide ou d'accélérer le transfert des modifications préparées vers la partie principale de CPython.

Principales optimisations implémentées dans Cinder :

  • Mise en cache en ligne du bytecode (« shadow bytecode »). L'essence de la méthode est d'identifier les situations dans lesquelles un opcode typique est exécuté et peut être optimisé, et de remplacer dynamiquement un tel opcode par des options spécialisées plus rapides (par exemple, en remplaçant les fonctions fréquemment appelées).
  • Évaluation impatiente de la coroutine. Pour les appels de fonction asynchrone qui sont traités immédiatement (wait n'entraîne pas d'attente et la fonction atteint l'instruction return plus tôt), le résultat de ces fonctions est directement substitué sans créer de coroutine ni impliquer de boucle d'événement. Dans le code Facebook qui utilise fortement async/await, l'optimisation entraîne une accélération d'environ 5 %.
  • Compilation JIT sélective au niveau des méthodes et fonctions individuelles (méthode à la fois). Activé via l'option « -X jit » ou la variable d'environnement PYTHONJIT=1 et vous permet d'accélérer l'exécution de nombreux tests de performances de 1.5 à 4 fois. Étant donné que la compilation JIT n'est pertinente que pour les fonctions fréquemment exécutées, il est déconseillé de l'utiliser pour des fonctions rarement utilisées, dont la surcharge de compilation ne peut que ralentir l'exécution du programme.

    Via l'option « -X jit-list-file=/path/to/jitlist.txt » ou la variable d'environnement « PYTHONJITLISTFILE=/path/to/jitlist.txt » vous pouvez spécifier un fichier avec une liste de fonctions pour lesquelles JIT peut être utilisé (format de chemin .to.module:funcname ou path.to.module:ClassName.method_name). La liste des fonctions pour lesquelles JIT doit être activé peut être déterminée en fonction des résultats du profilage. À l'avenir, la prise en charge de la compilation JIT dynamique est attendue sur la base d'une analyse interne de la fréquence des appels de fonction, mais compte tenu des spécificités du lancement des processus sur Instagram, la compilation JIT convient également à Facebook au stade initial.

    JIT convertit d'abord le bytecode Python en une représentation intermédiaire de haut niveau (HIR), qui est assez proche du bytecode Python, mais est conçue pour utiliser une machine virtuelle basée sur des registres au lieu d'une machine basée sur une pile, et utilise également des informations de type et des informations supplémentaires. détails critiques pour les performances (tels que le comptage de références) . Le HIR est ensuite converti au format SSA (static single assignation) et passe par des étapes d'optimisation qui prennent en compte les résultats du comptage de références et les données de consommation de mémoire. En conséquence, une représentation intermédiaire de bas niveau (LIR) est générée, proche du langage assembleur. Après une autre phase d'optimisations basées sur LIR, les instructions d'assemblage sont générées à l'aide de la bibliothèque asmjit.

  • Mode strict pour les modules. La fonctionnalité comprend trois composants : Tapez StrictModule. Un analyseur statique qui peut déterminer que l'exécution d'un module n'a aucun impact sur le code en dehors de ce module. Un chargeur de module qui détermine que les modules sont en mode strict (le code spécifie « import __strict__ »), vérifie l'absence d'intersections avec d'autres modules et charge les modules stricts dans sys.modules en tant qu'objet StrictModule.
  • Static Python est un compilateur de bytecode expérimental qui utilise des annotations de type pour générer un bytecode spécifique au type qui s'exécute plus rapidement grâce à la compilation JIT. Dans certains tests, la combinaison de Static Python et JIT démontre des améliorations de performances jusqu'à 7 fois par rapport au CPython standard. Dans de nombreuses situations, les résultats sont estimés proches de ceux obtenus avec les compilateurs MyPyC et Cython.

Source: opennet.ru

Ajouter un commentaire