Imaginez quâun utilisateur soulĂšve un rapport de bug dĂ©clarant que le calculateur de taille de selle de dragon prenait trop de temps pour estimer la taille de selle correcte. Les dompteurs de dragons sont des personnes occupĂ©es, et un tel dĂ©lai est inacceptable au souverain rĂ©gnant sur les Huit Royaumes. đ MĂȘme si vous nâavez pas peur de la colĂšre de ce souverain, il est important de demander : «âPourquoi est-ce que notre logiciel se mettrait tout Ă coup Ă ralentir ? »
De nombreux facteurs peuvent avoir un impact sur les temps de trajet. Avez-vous déjà pris les transports publics et eu le choix entre différents itinéraires ? Le choix du mauvais itinéraire peut vous faire perdre une heure ! Les applications qui déterminent les itinéraires sont efficaces pour vous donner des options sur la durée que nécessiteraient les différents chemins.
Pensez maintenant Ă votre code en exĂ©cution sur la JVM avec toutes les branches ou mĂ©thodes diffĂ©rentes quâil pourrait prendre en fonction des donnĂ©es et arguments que vous lui donnez. Votre logiciel est Ă©galement vulnĂ©rable Ă la dĂ©gradation des performances à chaque fois que vous ajoutez une nouvelle mĂ©thode ou branche oĂč le code pourrait devoir se rendre. Pourquoi cela ? Lorsque votre code est en exĂ©cution, la JVM effectue gĂ©nĂ©ralement un voyage de classe en classe, de mĂ©thode en mĂ©thode, et essaie dâatteindre son but. De façon interne, elle fait de son mieux pour rendre lâexĂ©cution de votre code la plus rapide possible, un peu comme ces applications qui trouvent des itinĂ©raires.
Les problĂšmes liĂ©s Ă la performance de Java sont gĂ©nĂ©ralement causĂ©s par des dĂ©veloppeurs. Nous concevons souvent des logiciels que mĂȘme la JVM ne peut pas accĂ©lĂ©rer, car soit les algorithmes rĂ©solvent les problĂšmes de la maniĂšre la plus lente possible, soit ils comportent une autre erreur.
Lorsque vous rencontrez un problÚme de performance dans votre code, essayez de le résoudre en :
Mesurant votre code pour dĂ©terminer quelle action le ralentit et oĂč cela se produit dans le code.
EnquĂȘtant sur le code non performant et questionnant ce quâil essaie dâaccomplir et pourquoi.
Supprimant ou simplifiant le code si cela peut ĂȘtre fait immĂ©diatement.
Mesurant votre code Ă nouveau pour voir si vous lâavez amĂ©liorĂ© !
Est-ce que vous ĂȘtes en train de dire que je ralentis peut-ĂȘtre mon application ? Comment cela est-il possible ?
Vous pouvez faire de nombreuses choses pour ralentir votre logiciel sans vous en rendre compte. Les causes les plus courantes impliquent lâĂ©criture dâalgorithmes inefficaces et de code qui empĂȘche un autre code de sâexĂ©cuter aussitĂŽt quâil le pourrait.
Regardons plusieurs causes Ă tour de rĂŽle !
Pour rappel, un algorithme est une sĂ©rie dâĂ©tapes qui vous permettent de dĂ©finir la façon dont vous traiterez les donnĂ©es entrantes et arriverez au rĂ©sultat escomptĂ©.
Lorsque vous Ă©crivez des mĂ©thodes et des fonctions, vous liez gĂ©nĂ©ralement une sĂ©rie de dĂ©clarations les unes aux autres dans votre langage de programmation. Ces dĂ©clarations rĂ©solvent certains problĂšmes en inspectant vos donnĂ©es et en appliquant des rĂšgles que vous jugez utiles pour rĂ©soudre une partie spĂ©cifique de votre problĂšme. En dĂ©cidant comment implĂ©menter ces rĂšgles en tant que code, vous dĂ©finissez un algorithme ou une sĂ©rie dâĂ©tapes que votre code devra exĂ©cuter.
En fonction de lâalgorithme, vous implĂ©menterez du code diffĂ©rent qui impactera la vitesse Ă laquelle il gĂšre diffĂ©rentes informations entrantes. Par exemple, si vous aviez une rangĂ©e de girafes en ordre de taille, comment dĂ©termineriez-vous laquelle est la plus grande ? Vous pourriez commencer avec la premiĂšre de la sĂ©rie et mesurer chaque girafe. Cela pourrait aller vite sâil y en a deux, mais ralentirait avec un troupeau plus important. Le fait de mesurer trente girafes prendrait beaucoup plus longtemps, et les perturberait probablement. Ătant donnĂ© quâelles sont dĂ©jĂ placĂ©es en ordre, il serait plus efficace de se rendre Ă la fin de la rangĂ©e. Cet algorithme ne ralentira jamais !
Prendre le temps de rĂ©flĂ©chir Ă la façon dont votre code se met Ă lâĂ©chelle pour gĂ©rer efficacement diffĂ©rentes donnĂ©es entrantes peut le maintenir performant. Ce nâest pas toujours Ă©vident ou facile, surtout si vous pensez que vous ne verrez jamais plus de deux girafes !
Nous disons que cet algorithme a une complexitĂ© temporelle dâO.(n) (Prononcez «âOrdre N »).
La majoritĂ© de ce que vous Ă©crivez en tant que dĂ©veloppeur est du code sĂ©quentiel. Câest-Ă -dire que vous Ă©crivez des algorithmes qui prennent une Ă©tape Ă la fois, dans lâordre. Pour quâune Ă©tape dĂ©marre, la prĂ©cĂ©dente doit ĂȘtre terminĂ©e. Toute dĂ©claration que dâautres dĂ©clarations attendent est appelĂ©e une dĂ©claration bloquante.
Les logiciels sont tellement rapides que cela ne pose pas de problĂšmes en gĂ©nĂ©ral. NĂ©anmoins, imaginez ce qui pourrait se produire si votre dĂ©claration bloquante impliquait une opĂ©ration lente, comme lâouverture dâun fichier ou lâexĂ©cution dâun algorithme inefficace, qui prend plusieurs secondes. Eh bien, la prochaine dĂ©claration devrait attendre que ce soit terminĂ©.
Attendez, est-ce que chaque étape ne dépend pas de la précédente ? Comment éviter cela ?
Dans de nombreux cas, une dĂ©claration dĂ©pend dâune dĂ©claration prĂ©cĂ©dente, mais pas toujours. Par exemple, pensez Ă lâĂ©quation de Pythagore pour calculer la surface dâun triangle, aÂČ + bÂČ = cÂČ. Devez-vous attendre de calculer le cĂŽté a au carré avant de calculer le cĂŽté b au carrĂ© ? Si les calculs de aÂČ et bÂČ Ă©taient des opĂ©rations lentes, vous pourriez mĂȘme les effectuer en mĂȘme temps ; câest ce quâon appelle une solution concurrente (ou parallĂšle).Â
Et maintenant, comment savoir si une mĂ©thode a Ă©tĂ© si mal Ă©crite quâelle a ralenti votre application entiĂšre ? MĂȘme si vous ne pouvez pas utiliser dâapplication de calcul dâitinĂ©raire pour naviguer dans les portions moins performantes de votre code, vous pouvez surveiller la façon dont il sâexĂ©cute pour trouver quels algorithmes le ralentissent â un peu comme si vous regardiez diffĂ©rents indicateurs de circulation qui montrent les bouchons sur des trajets spĂ©cifiques. Vous utilisez un outil de profilage de code.
Quâest-ce que le profilage ?
Le profilage correspond Ă tenir un chronomĂštre devant vos mĂ©thodes et Ă mesurer le temps quâelles prennent Ă renvoyer un rĂ©sultat. â±ïž Il vous permet de trouver les mĂ©thodes lentes dans votre code en mesurant et comparant vos appels pour trouver les moins performants. Il peut aussi capturer dâautres mĂ©triques concernant votre application. Il vous permet de trouver des problĂšmes affectant la vitesse Ă laquelle votre application se comporte et avec quelle efficacitĂ© elle utilise sa mĂ©moire disponible. Voyons comment faire cela dans la section suivante !
Pour profiler votre application, vous pouvez utiliser VisualVM, un outil de profilage Java dĂ©veloppĂ© par Oracle (les constructeurs de Java), et fourni avec leur JDK. Entre autres, il vous permet de mesurer les mĂ©thodes de vos applications Java et leur temps dâexĂ©cution. Vous pouvez utiliser VisualVM pour vous connecter Ă toute application Java en marche.
Vous pouvez tĂ©lĂ©charger la derniĂšre version de VisualVM depuis ce lien, ou vous pouvez utiliser celle qui est fournie avec le JDK. Essayez de dĂ©marrer jvisualvm sâil est dĂ©jĂ installĂ©.
Trouvez vos informations de distribution Java.
Vous pouvez gĂ©nĂ©ralement trouver jvisualvm en affichant votre variable dâenvironnement JAVA_HOME et en regardant dans le dossier bin qui y est stockĂ©. Cela varie en fonction de la distribution. Essayez de regarder dans les emplacements suivants :
sur un Mac avec OS-X, vous trouverez votre distribution Java sous  /Library/Java/JavaVirtualMachines;
sous Windows, vous trouverez généralement vos installations Java sous  c:\Program Files\Java;
avec les distributions Debian Linux, vous verrez que votre dpkg a installĂ© JDK sous  /usr/lib/jvm.Â
Localisez le fichier.
Entrez dans le rĂ©pertoire JDK et naviguez jusquâau rĂ©pertoire bin.
Sous celui-ci, vous trouverez un fichier nommé  jvisualvm. Par exemple, dans une installation Windows, il ressemblera Ă :Â

Démarrez le fichier en double-cliquant dessus.
Ta-da! đ à prĂ©sent, vous ĂȘtes prĂȘt Ă commencer Ă profiler.
Commençons par vĂ©rifier du code qui comporte des bugs. Pour regarder la version du projet de calculateur de tour de taille de dragon comportant un bug de performance, vous pouvez utiliser le mĂȘme rĂ©pertoire que vous avez clonĂ© en partie 2. Cette fois, consultez la branche performance-bug.
Vous pouvez utiliser le menu VCS dâIntelliJ pour consulter cela ou utiliser la commande Git CLI :
git checkout performance-bug
Ensuite, exĂ©cutez le programme DragonSaddleSizeGuesser et constatez le temps dâexĂ©cution de plusieurs secondes.
Pour enquĂȘter sur les raisons dâune telle lenteur de lâapplication DragonSaddleSizeGuesser, vous devez dĂ©marrer VisualVM. Le volet Applications sur la gauche affiche les applications Java en exĂ©cution que vous pouvez immĂ©diatement commencer Ă profiler.

Cliquez dessus pour voir toute application Java en exĂ©cution sur votre ordinateur. En cliquant sur le process VisualVM, vous pouvez explorer les volets fournis. Nous rechercherons le code lent, mais je vais tout dâabord vous donner une vue dâensemble rapide.
Faisons cela ensemble. VisualVM comporte beaucoup de fonctionnalitĂ©s, et nous nous concentrerons uniquement sur la surveillance du temps pris par nos mĂ©thodes. Pour vous donner une vue dâensemble rapide, jâutiliserai VisualVM pour quâil se connecte Ă lui-mĂȘme, car il sâagit simplement dâun autre process Java, et je vous ferai une visite guidĂ©e en deux minutes.
Vous avez vu la façon dont cliquer sur CPU sous la vue du moniteur a affiché le temps total passé dans chaque méthode ? Nous allons utiliser ceci pour trouver notre méthode lente.
Voici un dĂ©fi : pouvez-vous dĂ©marrer votre DragonSaddleSizeGuesser et vous y connecter avec VisualVM ? Nây passez pas plus de cinq minutes.
Avez-vous dĂ©jĂ abandonnĂ© ? Je parie que vous vous demandez pourquoi le DragonSaddleSizeGuesser nâarrĂȘte pas de disparaĂźtre. Le problĂšme de notre programme, câest que, mĂȘme avec son bug de performance, il sâagit toujours dâune application rapide qui calcule une taille de selle et arrĂȘte de sâexĂ©cuter, en gĂ©nĂ©ral en moins de 15 secondes. Câest peut-ĂȘtre trop lent pour nous, mais cela rend difficile de le trouver et sây connecter dans VisualVM.
Heureusement pour vous, il existe un plug-in dans VisualVM qui vous permet de profiler une application Ă partir du moment oĂč elle dĂ©marre. Laissez-moi vous montrer comment lâinstaller :
Comme vous lâavez vu, nous avons suivi le process suivant :
PremiĂšrement, cliquez sur Tools et sĂ©lectionnez lâoption Plugins.
Maintenant, défilez vers le bas et sélectionnez le plug-in Startup Time Profiler.
Défilez vers le bas et acceptez les modalités et conditions.
Cliquez sur Installer !
Cela a maintenant ajouté une icÎne supplémentaire dans VisualVM avec un petit chronomÚtre.

Comment utiliser ceci pour trouver la méthode qui ralentit mon application ?
Pour trouver la mĂ©thode qui a ralenti notre DragonSaddleSizeGuesser, nous devons lâexĂ©cuter avec VisualVM. Contrairement Ă lâexemple prĂ©cĂ©dent, nous allons paramĂ©trer VisualVM pour quâil attende notre programme, afin quâil puisse commencer le profilage dĂšs le moment oĂč il dĂ©marre.
Faisons-le ensemble :
Nous savons dĂ©sormais quelle mĂ©thode est notre coupable, mais comment lâavons-nous dĂ©couvert ? DĂ©taillons ce quâil sâest passĂ© ici.
Nous avons cliquĂ© sur lâicĂŽne chronomĂštre de notre profileur startup et sĂ©lectionnĂ© la bonne JVM pour notre application. Nous utilisons JDK 8, car câest la version utilisĂ©e par DragonSaddleSizeGuesser.
Nous avons sélectionné un port de 5130, qui aide notre JVM à envoyer des données à VisualVM.
Sous Start profiling from classes, nous avons entré le nom de paquet com.openclassrooms.debugging.**. Le double « * » fait que VisualVM profile toutes les méthodes des classes et sous-classes de ce paquet.
VisualVM nous a alors donné quelques commandes à copier en utilisant le bouton Copy to Clipboard (Copier vers le presse-papiers).
Nous avons ensuite ouvert une console et nous nous sommes placĂ©s Ă le rĂ©pertoire build/libs de notre projet (si le rĂ©pertoire nâexiste pas, exĂ©cuter la commande gradlew build).
Ainsi, nous pouvions exécuter notre application via le JAR qui est généré grùce à la commande : java <option copiée de VisualVM> -noverify -jar dragon-saddle-size-checker-1.0-SNAPSHOT.jar.
VisualVM nous a prĂ©venus que lâapplication avait dĂ©jĂ terminĂ© et a demandĂ© si nous voulions voir le rĂ©sultat. En sĂ©lectionnant Oui, nous avons pu prendre notre temps pour enquĂȘter sur le problĂšme.
Nous avons appris que la méthode que nous recherchons est :
com.openclassrooms.debugging.DragonSaddleSizeEstimator.enterAProgrammaticTrance()
.
Comment savons-nous que câest bien la cause ?
Dans VisualVM, nous avons cliqué sur  Hot Spots, et cela nous a montré une vue contenant ce qui suit :

La vue  Hot Spots montre une liste ordonnĂ©e de mĂ©thodes, classĂ©es selon la quantitĂ© de temps passĂ© dans la mĂ©thode. Comme un prĂ©sentateur mĂ©tĂ©o qui vous dit quâil fait 40° C Ă Tenerife â, si vous regardez la ligne supĂ©rieure du tableau ci-dessus et que vous regardez sous Self Time (Temps personnel), vous pouvez voir que nous avons un point critique (ou hot spot) de performance de 10 531 millisecondes. La premiĂšre colonne vous montre quâil sâagit du temps total passĂ© dans la mĂ©thode enterAProgrammaticTrance().
Si vous regardez la valeur entre parenthĂšses, elle montre que 99,8 % du temps de notre programme a Ă©tĂ© consacrĂ© Ă cette mĂ©thode. La derniĂšre colonne, Invocations, montre quâelle nâa Ă©tĂ© appelĂ©e quâune fois.
Comme vous pouvez le voir dans le cas demain(String arg[]), Ă la deuxiĂšme ligne ci-dessus, le fait de regarder le temps total dâune mĂ©thode peut vous induire en erreur. Il inclut tous les appels de mĂ©thodes amenant jusquâĂ Â un appel du coupable rĂ©el.
main(String arg[])a le temps total le plus lent, car il sâagit de la premiĂšre mĂ©thode appelĂ©e lorsque lâapplication dĂ©marre. Ce nâest pas la mĂ©thode qui a en fait introduit notre bug de performance, mais celle qui est Ă lâorigine lointaine de son appel !
Et maintenant, quâest-ce que cette mĂ©thode pourrait ĂȘtre en train de faire ? Souvenez-vous que ce programme a Ă©tĂ© interprĂ©tĂ© Ă partir de sorts anciens dâalchimistes. En bref, nâattendez pas trop de logique derriĂšre certaines de nos rĂšgles business. Lisons les commentaires et regardons le code.
private void enterAProgrammaticTrance() {
// Slows down the magic
Instant before = Instant.now();
Instant end = before.plus(Duration.ofSeconds(10));
while (Instant.now().isBefore(end)) {
for (int j = 0; j < Integer.MAX_VALUE; j++) {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
// TODO - implement
}
}
}
}Vous voyez ce quâil fait ? Ou plutĂŽt, ce quâil ne fait pas ?
Le code a une boucle while à la ligne 6, qui vérifie constamment si 10 secondes se sont écoulées depuis le calcul de Instant end à la ligne 4. Il y a deux grandes boucles for imbriquées aprÚs cela aux lignes 7 et 8, mais elles ne font rien ! Il y a un commentaire TODO inutile à la ligne 9.
Fondamentalement, cela tourne juste en boucle pendant 10 secondes !
Ce que ce code devrait faire nâest pas clair non plus. En demandant Ă nos experts au sujet des dragons (SME pour « subject matter experts »), on nous dit quâils nâont pas besoin dâune rĂšgle business comme celle-ci. Nous pouvons retirer ce code sans nuire Ă lâapplication. Il vaut mieux obtenir des estimations de selle en moins de 10 secondes que dâentrer dans une transe programmatique.Â
Nous avons besoin dâune solution !
Essayez de reproduire nos étapes ci-dessus. Vous devriez voir le  enterAProgrammaticTrance dans la vue  Hot Spots.
Retirez cette méthode et son appel.
Une fois ceci effectuĂ©, vous pouvez essayer de profiler vous-mĂȘme, comme nous lâavons fait ci-dessus.
Lorsque vous vous trouvez dans la vue Hot Spots, vous devriez remarquer que  enterAProgrammaticTrance() ne se trouve plus dans la partie supérieure.
Consultez la brancheperformance-bug-fixpour voir la solution :
git checkout performance-bug-fix
Lorsque jâexĂ©cute lâapplication avec la vue Hot Spots de VisualVM, la mĂ©thode lente a visiblement Ă©tĂ© retirĂ©e et la mĂ©thode principale est la nouvelle mĂ©thode la plus lente avec environ 19 ms.

Le profilage vous permet de recueillir et dâexaminer des mĂ©triques sur la performance des classes et des mĂ©thodes dans votre programme.Â
En utilisant VisualVM, vous pouvez profiler vos applications et capturer des vues classées de hot spots de performance dans votre code.
Avec le plug-in Startup Profiler, vous pouvez inspecter des programmes de courte durée.
Dans le chapitre suivant, nous allons explorer un autre excellent outil : JConsole !