Profiler, c’est mesurer où une application passe son temps d’exécution, fonction par fonction, requête par requête. L’ennui tient à une condition d’observation : la lenteur qu’on cherche ne se fabrique que sous charge réelle, avec de vraies données et des utilisateurs simultanés. Profiler sur son poste revient à chercher ses clés sous le lampadaire, pour la seule raison qu’il y a de la lumière à cet endroit.

En local, vous travaillez sur trois enregistrements en base, une seule session, des données propres. La production tourne sur des millions de lignes, des centaines de connexions concurrentes, et un historique que personne n’a jamais nettoyé. Le N+1 a besoin de volume pour se manifester ; la contention sur un verrou attend que plusieurs requêtes se marchent dessus. Certains goulots n’existent tout simplement nulle part ailleurs qu’en production, et c’est le genre de constat qu’on approuve poliment avant de l’oublier dès qu’on rouvre son IDE.

Le goulot qui coûte cher n’apparaît qu’en production, sous vraie charge et vraies données : on l’observe sans gêner personne par échantillonnage, en analysant 1 % du trafic, assez pour voir où part le temps, trop peu pour que quiconque le sente.

D’où la réticence à profiler là-bas. Instrumenter chaque requête en détail coûte trop cher, tout le monde le sait, et c’est précisément ce qui fait reculer les équipes. Sauf que rien n’oblige à tout mesurer. On échantillonne : vous n’instrumentez qu’une fraction du trafic, souvent un pour cent, parfois moins. Cette fraction suffit à faire ressortir les fonctions coûteuses et les chemins qui traînent, et elle est bien trop fine pour qu’un utilisateur perçoive quoi que ce soit. Les outils d’APM modernes (la surveillance des performances applicatives) ne procèdent pas autrement.

100% du trafic

Echantillon 1%

Repartition calcul / attente / pics

Ce que cette poignée d’échantillons révèle, c’est d’abord la vraie répartition du temps entre calcul et attente, qui ressemble rarement à celle qu’on imaginait. Puis les requêtes telles que l’application les lance vraiment : pas une requête isolée jouée dans un client SQL, mais celle qui repart trois cents fois dans une boucle qu’on avait oubliée. Et les pics, enfin, ces chemins qui se dégradent à l’heure de pointe sans rien laisser paraître à trois heures du matin.

Reste à brancher tout ça sans dégât. Même léger, un profileur se déploie avec méthode. Vous démarrez à un taux bas, de l’ordre de 0,5 %, vous vérifiez que la latence ne bouge pas, et c’est seulement après que vous montez si le besoin se confirme. Passer d’un coup à 10 % sur un service déjà chargé se lit sur les temps de réponse, et la personne qu’on appellera, ce sera vous. L’autre précaution est moins technique mais plus lourde de conséquences : ce que vous collectez peut renfermer des données personnelles. Une URL avec un identifiant, un paramètre de requête, le corps d’un message. Filtrez-les avant l’envoi vers votre outil, faute de quoi vous aurez transformé un instrument de performance en fuite RGPD.

Le développement sert à formuler des hypothèses, la production à les trancher, et l’échantillonnage reste la seule façon honnête de voir l’application telle qu’elle est réellement vécue. Un exemple pour finir. Un client industriel m’a fait perdre une semaine à optimiser un rendu qui n’avait aucune part dans le problème. On était partis sur une intuition de dev, sans mesure. Le vrai coupable, je l’ai repéré en une après-midi une fois l’agent posé en prod : un appel à un service tiers qui partait en timeout une fois sur dix, invisible sur nos machines parce que ce tiers répondait toujours en moins de cinquante millisecondes depuis le bureau.

À lire aussi