URL: https://linuxfr.org/users/windu2b/journaux/optimisez-votre-code Title: Optimisez votre code ! Authors: windu.2b Date: 2017年12月07日T12:24:57+01:00 License: CC By-SA Tags: sql, mysql, python et optimisation Score: 75 Cher journal, Je voudrais te raconter une histoire, qui n'est peut-être pas encore finie d'ailleurs, qu'on pourrait résumer en 1 mot : OPTIMISATION ! Tout commence en tout début d'année : je suis embauché chez [Chacun cherche son Film](http://chacuncherchesonfilm.fr/), une toute petite (5, moi inclus) boite qui développe un site Web faisant la promotion du cinéma indépendant. Cette boite a fait le (très mauvais, comme on va le voir) choix de faire développer son site par une boite de prestation parisienne, qui a mis des mois à livrer son travail et qui, en plus, était bâclé ! Ils devaient notamment gérer l'import hebdomadaire des horaires de séances : tous les mardis soirs, nous recevons un fichier XML (35Mo, 400.000 lignes) contenant les 3.300 cinémas de France métropolitaine, les centaines de films projetés dans la semaine (du blockbuster au vieux film projeté 1 fois par un petit cinéma Art & Essai, dans le cadre d'une rétrospective d'un réalisateur), les 15.000 événements (1 événement = toutes les infos concernant la projection de 1 film dans 1 cinéma : VF/VO, 3D ou pas, projection 35mm/numérique/...) et les 100.000-150.000 horaires de séances. Leur import reposait sur le système de Queue de Drupal (avec lequel ils avaient développé le site Web). Mais il était tellement mal optimisé que cela prenait jusqu'à 18 heures (!) pour tout traiter ! De plus, leur script plantait souvent en cours de traitement, nécessitant de le relancer manuellement (et quand il plante dans la nuit de mardi à mercredi, il faut donc attendre que quelqu'un s'en rende compte le matin, et relance). Bref, les horaires de cinéma pour la semaine, qui commence le mercredi, n'étaient parfois pas totalement disponibles avant... le jeudi dans la journée ! Une de mes premières missions fut donc de corriger et d'optimiser tout ça. Première optimisation : ne pas traiter les cinémas ou les films dont la date de dernière modification (incluses dans les attributs XML de chacun) est plus ancienne que le flux hebdomadaire précédent. Si rien n'a changé, y a rien à traiter ! Deuxième, et principale, optimisation : réécrire les 2 requêtes XPath (servant à chercher des infos sur les cinémas et films auxquels se rattache chaque horaire). Leurs requêtes XPath cherchaient dans TOUT le fichier XML, au ;lieu de ne chercher que dans les blocs des cinémas/des films. Résultat : de 18h, on arrive à 3h. Quelques :ois plus tard, le choix fut fait de recoder totalement le site. Les bugs étaient trop nombreux, et la boite de presta n'avait pas l'air de s'en sortir pour déboguer tout ça. Je recode donc tout en PHP (framework Laravel, mais ça n'a pas d'importance ici). Il me faut donc aussi réécrire le script d'import. Je décide alors de le faire en Python. Résultat : de 3h, on passe à 1h30. On a donc les horaires de séances de la nouvelle semaine disponibles dès le mardi vers 19h. Parfait ! Je décide alors d'en rester là, et de me concentrer sur d'autres priorités. Le temps passe, les autres priorités sont traitées, et me revoilà à repenser à ce script. Ne pourrait-on pas l'améliorer encore ? Après tout, ces 15.000 événements et ces 100.000-150.000 horaires qu'on insère en autant de requêtes, c'est vraiment pas top, quand même. Ça donnerait quoi, si je faisais des INSERT multi-lignes ? Disons... 2 INSERT par cinéma, 1 pour tous les événements, l'autre pour tous les horaires. Résultat : de 1h30, on passe à... 10 minutes ! Bref, on ne le dira jamais assez : OPTIMISEZ VOTRE CODE ! Ce n'est pas parce que ça tourne sur un serveur avec 8 cœurs que ça dépotera. Surtout quand votre script n'est absolument pas parallélisé ! Et même si je suis très fier de ce gain (d'un rapport de plus de 100 pour 1, au final), je ne peux que me désespérer de voir des codes absolument pas optimisés parce que "bof, de toute façon, le processeur en a sous la pédale !". PS : ma modification du script n'ayant consisté qu'à stocker dans un tableau les données à insérer, et à passer ce tableau d'un coup à la requête d'insertion, la seule autre cause possible de gains de temps que je vois est l'écriture des logs (à raison d'une ligne par INSERT), qui a diminué dans les mêmes proportions que le nombre de requêtes SQL.