JRat " Java Runtime Analysis Toolkit " - Analyser pour optimiser

Démonstration de l'outils JRat d'analyse de programme Java

JRat est un outils Opensource dont le but est d'aider les développeurs à comprendre le déroulement de leur programme Java. Il permet pour cela :

Et enfin, JRat permet de faire tout ceci sans avoir à ajouter une seule ligne de code !

1. Fonctionnement de JRat

Le fonctionnement de JRat se base sur 4 choses :

architecture de JRat

Pour comprendre plus en détail ce qu'il se passe voici un schéma du flux de données :

architecture de JRat

Comme on peut le voir, le point de départ est toujours notre application java d'origine qui va être compilée normalement pour générer du Java Bytecode. C'est une fois ce bytecode généré que JRat va intervenir pour générer une 2eme version du Java bytecode dans lequel il aura injecté de quoi le monitorer. Lors de l'exécution les librairies de JRat vont donc pouvoir percevoir toutes les informations nécessaires pour générer des fichiers de log de l'exécution. Il ne restera donc plus qu'à utiliser le JRat desktop ou un autre outils capable d'interpréter les fichiers de log pour lire l'analyse.

2. Installation et utilisation de JRat

Ces quelques aides à l'installation de JRat sont valables pour Java 1.4 ou ultérieur et ont été réalisés sous eclipse. Pour de plus amples informations se reporter au tutorial d'installation de JRat ici.

La première chose à faire pour utiliser JRat est d'inclure les librairies bcel et jrat :

librairies JRat

En ce qui concerne l'installation ... ben c'est tout :)
La suite relève de l'utilisation. Pour cela vous aurez besoin du JRat Desktop. Celui-ci est tout simplement dans la librairie shiftone-jrat.jar que vous avez inclus sur votre projet, et comme c'est un exécutable, vous n'avez qu'à le lancer (double-click ou java -jar shiftone-jrat.jar). Une fois que JRat Desktop est lancé, il va falloir lui spécifier vos fichiers compilés (.class) à analyser :

menu desktop

Je conseille le choix récursif afin de tout inclure tout simplement.

A ce stade la, et en indiquant vos fichiers compilés à JRat, vous lui avez permis de 
générer une deuxième version du Java bytecode dans lequel il a intégré ses outils
de monitoring (cf partie 2). Il ne faut donc surtout pas oublier cette étape ;)

Il ne reste plus qu'à exécuter votre programme. Pour cela, un paramètre pour la JVM est nécessaire :

paramètres

C'est lui qui va permettre de déclencher la saisie des logs et d'en spécifier le format. En effet, JRat vous permet d'afficher vos vos données selon différents modes, il faudra donc lui spécifier le paramètre correspondant :

Voila vous pouvez désormais lancer votre application, JRat is watching you.
Une fois terminé, vous aurez à la racine de votre projet un répertoire JRatOutput dans lequel vous trouverez des répertoires datés contenant vos logs générés. Vous pouvez désormais les ouvrir avec JRat Desktop pour faire votre analyse...

3. Un exemple d'utilisation : le voyageur de commerce

Pour illustrer l'utilisation de JRat, voici l'exemple du voyageur de commerce. Cet exemple utilise un algorithme dit génétique. Les algorithmes génétiques se basent sur la théorie de l'évolution de l'espèce (Darwin). Pour résumer brièvement leur fonctionnement, on commence avec des couples de solutions potentielles qui constituent une "population" et à laquelle on fait suivre le cycle suivant :

Et on recommence ce cycle un certain nombre de fois ...

J'ai choisi cet exemple car il est utilisé pour résoudre des problèmes dont on ne sait pas trouver une solution autrement qu'en testant toutes les solutions possibles. C'est donc un algorithme sensible que l'on utilise en vue d'obtenir les performances les meilleurs possibles. C'est pourquoi il est très intéressant d'étudier ses performances avec un outils comme JRat.

Supposons maintenant que je sois en train de travailler pour une grande compagnie d'aéroports disposant de plein d'aéroports dans le monde entier. Cette société m'emploie pour résoudre un problème bien connu : celui du voyageur de commerce. En effet, la société souhaite souvent programmer des voyages d'aéroports en aéroports pour atteindre un destination lointaine, mais cela en étant garantie de faire le trajet le plus court possible.
A première vue, seule l'intuition et un aperçu générale de toutes les étapes permettraient d'avoir une vague une idée du meilleur chemin à employer. Mais cela revient au final à tester toutes les solutions possibles pour en être sûr. Donc si vous faisiez un programme testant toutes les solutions possibles, alors tester le meilleur chemin pour plus de 100 villes seraient tout simplement impossible pour votre programme en un temps raisonnable.

C'est pourquoi, vous faites un super programme utilisant les algorithmes génétiques pour répondre au besoin de l'entreprise. Ce programme utilise tout de même un bon nombre d'itération et utilise un algorithme particulier pour l'étape de reproduction, de mutation et éventuellement de sélection. C'est pourquoi, votre conscience professionnelle et votre volonté d'obtenir une prime de résultat pour les performances de votre application vous pousse à effectuer une analyse de performance sur votre programme afin d'en étudier son comportement.

Vous installez donc JRat, lancez JRate Desktop en lui donnant les binaires de votre programe, et lancez votre programme tranquillement :

Exécution du Voyageur de commerce

Votre programme s'est bien exécuté, et vous pouvez ouvrir le fichier de log généré avec JRat Desktop. Voici le résultat :

Résultat 1

Premier retour d'information, vous savez désormais que votre programme a mis environ 7,187 secondes pour résoudre votre problème. On peut ensuite constater que JRat indique en rouge les endroits ayant été les plus visités, et donc ceux étant le plus susceptibles de nous intéressez. Analysons :

Cette première analyse est donc assez riche puisque notre programme, bien qu'il marchait très bien et trouvait la bonne solution, adopte un répartition de sa charge de travail assez bizarre.
A ce stade nous savons donc grâce à notre analyse qu'il serait beaucoup plus judicieux d'aller regarder le code de notre fonction de reproduction que de notre fonction de mutation... De plus, nous savons qu'au sein même de la méthode de reproduction il faut faire particulièrement attention à la méthode de tri, qui mange la plupart du temps. Au final on peut donc même affirmer que soit notre algorithme de reproduction est mal fait soit notre méthode de tri est très mauvaise.

bug 1

En regardant le code de la reproduction et de ses appels à la méthode de tri on constate finalement dans notre exemple que c'était une erreur algorithmique. En effet, pour chaque reproduction un nouvel élément était ajouté et la population était tout de suite retriée, alors que l'on peut trier une seule et unique fois après avoir ajouté tous les nouveaux éléments.

bug 2

Pour vérifier la validité de notre correction, la même analyse est refaite, en prenant bien soin de spécifier les nouvelles classes binaires puisqu'elles ont été modifiées. Voici le résultat :

Résultat 2

Le résultat est flagrant :

On peut donc maintenant être beaucoup plus au clair sur les performances de notre programme. Mais on pourrait encore pousser les analyses et tenter de l'optimiser. En effet, si l'on regarde bien les analyses, on voit parfaitement que notre programme passe finalement beaucoup de son temps à trier les données. C'est tout à fait logique et normal dans le cadre de notre algorithme génétique, JRat nous le confirme et ce serait donc sur une méthode de tri plus efficace que nous travaillerons finalement pour toucher notre prime de résultat ...


Valid XHTML 1.0!