JRat " Java Runtime Analysis Toolkit " - Analyser pour optimiser
L'analyse d'un programme java en vue de l'optimiser
1. Analyser les performances d'un programme - Pourquoi ?
La première problématique que l'on rencontre lorsque l'on développe un application est de savoir si elle est suffisamment performante pour le client à qui elle est destinée.
- Le temps d'ouverture de l'application est-il raisonnable ? acceptable ?
- L'application nécessite-t-elle des temps de chargement en cours d'utilisation ? régulièrement ? localement ? sont-ils raisonnables ?
Ensuite, lors de l'analyse technique de l'application, un certains nombre de choix doivent être fait. Choisir une structure de données, un type de support ou encore une méthode de tri, sont autant de choix difficiles car dépendants de l'utilisation que l'on en fait. Il serait donc très intéressant de pouvoir mesurer les temps de réponses d'une fonction comparativement à la même fonction mais implémentée avec un algorithme différent.
Enfin, comme on peut le voir, une analyse de performance vise souvent à valider un comportement ou faire des choix sur des parties bien ciblées d'une application. Mais que faire s'il on ne sait pas quelle partie optimiser ? En effet, il n'est a priori pas évident de savoir qu'elle partie du code doit être optimiser. Une analyse parfaite de performance permettrait donc de suivre le comportement d'une application afin d'en analyser les points faibles.
2. Conditions d'analyse de performance ?
Cela paraît parfois évident, mais il n'est pas inutile de rappeler un certain nombre de conditions à satisfaire pour prétendre pouvoir analyser et tester du code :
- La première évidence est que l'implémentation doit être complètement finie et le code doit être correctement testé en terme de fonctionnalité. En effet, on ne peut pas prétendre vouloir tester les performances d'un fonction si celle-ci ne répond pas à son rôle premier. Cela ne nous empêche pas de limiter notre analyse à une package unique et non pas a l'application entière, l'essentiel étant que le package soit fermé, c'est à dire testé et validé.
- Il faut ensuite garder en tête qu'avant d'optimiser soit même du code, le compilateur le fera au maximum. Ainsi, il faut donc prendre soit de pousser les options de compilations au maximum pour ne pas fausser les analyses.
- Il faut enfin s'assurer de tout l'environnement de test afin d'être au maximum fidèle aux conditions d'utilisation finales de l'application chez le client.
3. Principe de l'optimisation
Voici comment on pourrait schématiser le cycle d'optimisation dans lequel nous allons faire notre analyse de performance :
Comme on peut le voir celui-ci est découpé en cinq parties :
- Measurement : c'est la partie d'analyse de performance dont nous avons parler et dont nous verrons la démonstration un peu plus loin.
- Locate bottleneck : c'est la toute l'utilité de notre analyse. On va pouvoir, en vue des résultats, déterminer et surtout localiser les goulots d'étranglement de notre programme.
- Modify code : c'est ici que l'on intervient pour faire les modifications adéquates. C'est la que l'on va réellement intervenir pour corriger les problèmes de performances.
- Check for improvement : ici on relance une autre batterie de tests liée aux modifications effectuées.
- Improvement satisying : et on valide ou non l'optimisation effectuée.
4. Comment optimiser ?
Comme on a pu le voir lors du cycle d'optimisation, la partie la plus difficile est la modification du code. En effet, si
notre analyse de performance nous permet de localiser très précisément nos goulots d'étranglement, elle ne nous dit pas
comment les corriger ;)
La difficulté réside donc sur la causalité des goulots d'étranglement. Pourquoi mon code passe-t-il autant de temps à cet endroit là ? Il est la plupart du temps intéressant de se pencher sur trois types de problèmes :
- L'algorithme utilisé : c'est la la différence entre le bon et le mauvais codeur :) Les problèmes d'algorithime peuvent se révéler parfois assez complexe. Il est donc très important de maîtriser son comportement du début à la fin et surtout être capable d'évaluer sa complexité en o(1) o(n) o(nlog(n)) ou encore o(n²).
- Les structures de données utilisées : elles sont indispensables et donc extrêmement importantes à choisir. Suivant leur type et leur utilisation, elles peuvent considérablement altérer les performances d'un algorithme. C'est pourquoi il faut les choisir avec habilité et bien étudier leur complexité lors d'insertion/suppression/accès/etc...
- Les entrées/sorties utilisées : cela reste un gros problème en terme de performance. Les temps d'accès d'un cd-rom ou d'une disquette sont énormes comparés aux accès mémoires et cpu. Les optimisations à ce niveau là relève donc souvent du miracle.
5. Les règles d'optimisation
Pour finir voici quelques règles d'optimisation basiques mais importantes à suivre :
- Utiliser au maximum des librairies déjà implémenter : avec l'avènement du monde libre, on cherche souvent à développer des outils déjà disponible librement. Il faut donc au maximum se renseigner pour utiliser des outils déjà testé, validé et surtout optimisé.
- Choix des structures et algorithmes classiques : comme on l'a vu précédemment, les choix effectués lors des analyses techniques d'un projet sont parfois primordiaux pour les performances d'une application. Il faut donc bien respecter cette phase et justifier ses choix.
- Toujours penser que le compilateur est la pour nous aider et faire ses propres optimisations. Il faut donc bien se renseigner sur le compilateur qu'on utilise pour savoir qu'elles optimisations ils proposent afin d'adapter son code. Exemples : favoriser les variables final, favoriser les fonctions inline, etc ...
6. Les outils du marché
Pour faire les analyses de performances, quelques outils sont disponibles. C'est un marché qui n'est pas encore très abondant. On trouve trois types d'outils :
- JVMPI "Java Virtual Machine Profiling Interface" : c'est la solution de sun intégrée à sa JVM, mais qui utilise une API native et qui nécessite le développement d'un agent pour écouter les comportements de la JVM (ex: hprof)
- Les payants : Borland Optimizeit Enterprise 6, JProbe Suite, etc ...
- Les projets OpenSource : JTreeProfiler et JRat essentiellement.