Retour d’expérience sur le passage de Python à Cython

Contexte

Je suis Leader Technique et mon équipe est en charge de l’évolution ainsi que de la maintenance de distributeurs automatiques de billets. Nous travaillons sur des automates conçus en 2004 et 2007, qui ont aujourd’hui des ressources limitées. Le contexte projet fait que ces automates ont une combinatoire de vente très importante.

Au fur et à mesure des évolutions, la combinatoire des produits vendables est devenue de plus en plus complexe : les temps de calcul sur le plus vieux des automates étaient critiques. J’avais déjà optimisé l’algorithme  en charge de tester la gamme tarifaire associée à une carte de transport. Cette optimisation avait permis de continuer à offrir au client une expérience acceptable.

Quand un usager dépose sa carte de transport sur la machine, toute la gamme tarifaire compatible avec cette carte est vérifiée. Cela implique de nombreuses règles métier à contrôler, et ce par une bibliothèque partagée. Dans certains cas extrêmes, cette bibliothèque peut être appelée plus de 60 fois. Chaque vérification prenant en moyenne 500 millisecondes, nous dépassions les 30 secondes de calcul : une expérience utilisateur bien trop longue et inacceptable.

Contraintes

Cette bibliothèque étant utilisée par plusieurs appareils aux configurations hétérogènes, il fallait que la solution retenue fonctionne sur ces différentes plateformes.

Les contraintes étaient les suivantes :

  • – Compatible python 2.4 32 bits sous GNU Linux Debian 4 ;
  • – Compatible python 2.7 64 bits sous GNU Linux Debian 9 ;
  • – Compatible python 2.4 32 bits sous Windows NT4 ;
  • – Compatible avec les tests fonctionnels automatiques en place.

Des compilations à la volée (JIT) avaient déjà été tentées dans le passé sous Debian 4. Les résultats n’avaient pas été probants et le projet a été abandonné. Nous avons donc directement éliminé ces solutions.

Pour garder les tests fonctionnels opérationnels, nous avons regardé du côté des « compilateurs Python ». Après recherche, Cython nous paraissait être la meilleure solution dans notre cas de figure.

Après un premier test de compilation de la bibliothèque avec Cython sans aucune modification, nous avions un gain de performance de 15%.

Réalisation

Afin de réaliser ces modifications, nous avons utilisé la version 0.20 de Cython, dernière version compatible avec Python 2.4. La transformation du code Python de la bibliothèque en code Cython a alors pu démarrer. Cette transformation consiste principalement à typer le code Python pour permettre à Cython d’optimiser la compilation. Idéalement, nous aurions aimé utiliser le « Pure Python Mode » ou les « Magic Attributes » de Cython, mais ces modes ne sont pas disponibles dans la version 0,20. Ils nous auraient permis de passer facilement et progressivement le code Python en code Cython :

  • – Le « Pure Python Mode » permet de ne pas modifier le code python en ajoutant des fichiers .pxd au projet. Ces fichiers décrivent le typage à appliquer au code python, ils sont l’équivalent des .h en C;
  • – Les « Magic Attributes » sont des décorateurs à ajouter au code python, qui sont utilisés par Cython pour la compilation et ignorés par Python.

N’ayant pas les fonctionnalités de transition simplifiée, nous avons directement typé tout le code en utilisant la syntaxe de Cython.

Cython a « trois niveaux » d’optimisation possible :

  • 1. Compiler du code Python pur. Cela fait gagner le temps JIT de l’interpréteur cpython ;
  • 2. Typage et compilation de méthodes/fonctions avec visibilité dans Python ;
  • 3. Typage et compilation de méthodes/fonctions internes au code Cython, donc non appelables par Python.

Le premier niveau d’optimisation nous a fait gagner 15% de performance; Pour optimiser au maximum au niveau 3, nous avons répertorié la liste des méthodes appelables par Python et qui auront donc une optimisation de niveau 2.

Cette étape de transformation s’est globalement bien déroulée. Nous n’avons rencontré aucune difficulté particulière, le projet compilait correctement.

Intégration

Nous sommes alors passés à l’étape suivante : l’intégration. Pour ce faire, nous avons lancé les tests fonctionnels. Cette phase a pris plus de temps que prévu. En effet, au premier lancement, aucun test ne fonctionnait. Nous avons donc corrigé nos erreurs et après plusieurs ajustements, les tests sont enfin passés avec succès.

Ils ont permis de corriger de nombreuses erreurs faites pendant la transformation : mauvaise utilisation de Cython, mauvais typage, mauvaise adaptation algorithmique, …

Les tests unitaires nous ont causé beaucoup de soucis. Étant en Python, ils étaient très permissifs dans le type des objets utilisés pour tester et des objets « Mock » ont été massivement utilisés.

Comme nous n’avons pas pu utiliser les modes« Pure Python Mode » ou les« Magic Attributes », deux solutions se présentaient à nous :

  • – Réécrire l’intégralité des tests unitaires ;
  • – Coder un outil qui adaptera le code Cython uniquement pour les tests unitaires.

Il n’était pas envisageable de réécrire les tests, parce qu’ils étaient là pour nous garantir le fonctionnement à l’équivalent, sans régression, de la bibliothèque.

Nous avons alors créé un script modifiant le code Cython et transformant la déclaration de toutes les fonctions et méthodes, pour les rendre compatibles avec les tests unitaires. Le code ainsi modifié a été utilisé uniquement pour l’exécution des tests unitaires. Ce script n’a pas altéré les algorithmiques, juste la déclaration des méthodes/fonctions.

Concrètement, le script a modifié toutes les déclarations de fonctions/méthodes pour qu’elles soient exposées à l’interpréteur python avec un typage compatible pour les cas posant un problème. Tous les tests ont été concluants, test fonctionnel et unitaire.

Nous pouvions alors passer à l’intégration de la bibliothèque dans un logiciel d’une machine. Malheureusement, le premier lancement s’est conclu par un plantage de la machine.

Certains mécanismes, habituellement implémentés par défaut dans l’interpreteur Cpython, ne le sont pas dans Cython. C’est le cas de la copie récursive des objets, mécanisme justement utilisé par le code des machines.

Les tests fonctionnels, cette fois de l’automate, ont permis d’identifier tous ces soucis de compatibilité et de finaliser le portage de la bibliothèque. Une fois les tests réussis (test fonctionnel/unitaire de la bibliothèque et test fonctionnel des automates), il nous restait un dernier essai : les tests sur l’appareil sous Windows NT4. Notre plus gros souci fut de compiler pour Python 2.4 sous Windows NT4. Nous devions passer obligatoire par Windows XP.

Grâce à une vieille machine sous Windows XP que nous avions sous la main, nous avons pu compiler la bibliothèque et tester sur machine le résultat. Cependant, pour la mise en place de l’intégration continue, nous ne pouvions pas utiliser ce système d’exploitation. Après quelques essais, nous avons réussi à compiler la bibliothèque avec WINE sous GNU Linux Debian. Le binaire, ainsi créé, était fonctionnel sur la machine cible.

Résultats

Finalement, avec juste un typage du code existant, la performance est au minimum deux fois plus rapide. Dans un test « lourd », le temps d’attente du client est passé de 22 secondes à 9 secondes comme l’attestent les graphiques ci-dessous (5 répétitions du même test) :

Utilisation du CPU avant optimisation

Utilisation du CPU après optimisation

 

 

 

 

 

 

 

Il est encore possible d’améliorer la performance brute, en faisant, par exemple, moins d’appels à des modules Python pures dans la bibliothèque.

Conclusion

Le passage a Cython a répondu à notre besoin d’amélioration des performances avec un temps de calcul réduit d’un facteur d’environ 2.

Les tests automatisés nous ont permis de faire cette transition sereinement et sans accroc sur la mise en production. Ces tests nous ont vraiment aidés et sécurisés pour la réalisation de cette migration. Une grosse évolution fonctionnelle, nous a permis de revoir une partie de l’algorithme pour être plus « Cython ». Nous avons maintenant un facteur 4 fois plus rapide en moyenne.

Nous avons réutilisé Cython pour d’autres projets, mais dans un cadre d’interfaçage de Python avec des bibliothèques C externe.

Article rédigé par Romain, Leader Technique.

Autres articles

Recap’ de notre dernier CODING GAME COMPETITION – Mai 2022

Le mardi 10 mai 2022

Jeudi dernier, Agixis vous a proposé un CODING GAME COMPETITION de haut niveau  ! 

Ce jeudi 05 mai 2022, nous avons été témoins de très belles performances au Meltdown à Lyon lors de notre dernière Coding Game Competition. Ce sont 11 binômes qui se sont affrontés pendant 3 heures sur le jeu Search Race, travaillant sans cesse pour obtenir le score le plus petit possible.

Merci à tous ceux qui étaient présents pour votre participation et votre bonne humeur. Nous espérons que vous avez passé un aussi bon moment que nous ! Et merci également à John P., notre agicien Tech Lead qui a grandement participé à l’organisation de cet événement. Fun fact : nous l’avons rencontré pendant une compétition de Coding Game !

Et bravo, bien entendu, aux deux équipes gagnantes : Lilian Go Skype (14 046 points) et Lucifor (20 968) qui ont pu repartir avec un casque Razer et des e-cartes cadeaux FNAC.

Voici un récap’ photo de la soirée :

 



Webinaire gratuit – Les principes de programmation, productivité et amélioration continue – 17 mai 2022

Le lundi 25 avril 2022

Invitation à notre prochain webinaire 

Nous vous invitons à un webinaire gratuit sur le thème  » Les principes de programmation, productivité et amélioration continue  » animé par Loic, notre agicien expert ! À destination des développeurs et des curieux :).

 » Vous souhaitez développer vos compétences, produire un maximum de valeur pour le client et obtenir la satisfaction d’un travail bien fait ? Découvrez mon retour d’expérience sur les principes de programmation à appliquer au quotidien et leur complémentarité afin de maximiser son travail ». 

Principes de programmation qui seront abordés : TDD, DDD, Egoless Programming et Architecture Hexagonal.

Rendez-vous en ligne le mardi 17 mai à 18h30 sur Teams. Pour vous inscrire et recevoir le lien de connexion, c’est par ICI.

Récap’ de notre dernière soirée portes ouvertes – Conférence Test Unitaire – 14/04/2022

Le vendredi 15 avril 2022

Photos de notre dernière soirée portes ouvertes

Soirée portes ouvertes et conférence : « Test Unitaire : apprivoisé par la théorie »

Le 14 avril dernier, Agixis a ouvert ses portes pendant quelques heures. Ce fut l’occasion d’échanger avec nos collaborateurs, discuter carrière, mais aussi technique ! En effet, nos deux agiciens experts Matthias et Baptiste ont animé une conférence sur le Test unitaire apprivoisé par la théorie. Voici un aperçu du contenu présenté : (suite…)

Logo Agixis

CONTACTEZ-NOUS :
04 27 02 74 49

115 boulevard de Stalingrad 69100 Villeurbanne

Mentions légales - Création : Agence 33 Degrés : Agence de communication lyon - Développement : WebForLyon

Logo Agixis

MENU

Meeting agile Agixis Meeting agile Agixis
Logo Agixis

  • Accueil
  • Agixis
  • Métiers
  • Services
  • Solutions
  • Références
  • Nous rejoindre
  • Postuler
  • Actualités
  • Contact

Meeting agile Agixis Meeting agile Agixis

Recherche


Dernières annonces

  • Chargé.e de communication 360° H/F

    Agixis recrute ! Rejoins-nous dans cette incroyable aventure collective en participant de manière a...

    Découvrir
  • Product Owner H/F

    Product Owner, tu as envie de travailler en environnement technique innovant ? Prendre le lead sur u...

    Découvrir
  • Alternance Ingénieur études et Développement (F/H)

    Tu es à la recherche de ton alternance pour ta dernière année ? Tu as envie de réellement décou...

    Découvrir

AGIXIS
Immeuble Central Parc II
115, boulevard de Stalingrad
69100 Villeurbanne