samedi 9 février 2008

Optimisation de la mémoire de la JVM pour Eclipse

En voila un sujet qui fache !! La mémoire utilisée par Eclipse. Et c'est légitime que ce sujet déchaine les passions tant il est important de se pencher sur ce problème pour augmenter la productivité des utilisateurs eclipse.

En effet, avec une configuration par défaut, Eclipse est parfaitement adapté pour des projets simple de taille moyenne diront nous, cad sans dépendances complexes, sans avoir besoin de 1000 et 1 plugins et frameworks en tout genre.

Dès qu'il sagit de developper dans un environnement projet complexe (+ de 10 projets, + de 5 frameworks, RCP + WTP + Hibernate + Spring + Junit + BIRT + etc...) une configuration adaptée s'impose ! Car sinon on frole le drame ! Un environnement de développement instable et une machine qui "rame" comme jamais...
Symptomes: Des temps de chargement, de lancement, de build, de compilation ou de déploiement extrèmement longs et surtout une floppée de messages d'erreurs désagréables indiquant grossomodo qu'Eclipse manque de mémoire et vous incitant à redémarrer Eclipse (et la JVM par la même occasion).
Et quand on voit des popup "Eclipse need more memory... Do you want to exit the workbench now ? Yes. No." ou des OutOfMemoryException toutes les 2 heures d'utilisation, il y a de quoi s'arracher les cheveux !!!
Car redémarrer Eclipse implique premièrement d'arreter la tache en cours, d'attendre 2 minutes qu'il redémarre puis accessoirement de relancer le serveur d'application en cours (environ 2 minutes) et de redémarrer le client RCP puis de se remettre dans la configuration avant le re-démarrage "forcé"... Environ 5 minutes de perdu seulement diront certains... mais a raison de 4 fois par jour, ca représente 20 minutes minimum par développeur au sein d'un équipe ! Charge non négligeable AMHA !

Premièrement, il n'y a pas de secret, dans une configuration complexe il faudra un minimum de 1Go de RAM, 2Go de préférence voir 3 à 4Go pour les plus gourmands ! (Ceux qui font de la médélisation UML + des jeux en LAN + Eclipse...) Sans oublier une machine performante tant au niveau processeur (Intel Core 2 Duo / AMD Athlon 64) que pour le reste...

Deuxièment, le lanceur Eclipse (raccourci ou bat ou cmd) doit comporter des arguments spécifiques à la JVM pour paramètrer l'utilisation de la mémoire vive. Pour cela on peut ajouter le paramètre "-vmargs" suivi de propriétés à passer à la machine virtuelle java.

Pour info, dans "vmargs" on trouve "vm" soit "virtual machine" et "args" soit "arguments"... rien de bien compliqué.

Ensuite les propriétés que l'on peut passer à la machine virtuelle dépendent de votre configuration matérielle et de votre utilisation d'Eclipse... Voici des préconisations qui correspondent à un besoin particulier (le mien)... à vous d'adapter et de tester si cela vous convient au mieux ou pas.

On a pour habitude d'utiliser la propriété "-Xmx256m" pour augmenter la mémoire maximum utilisable par la JVM (Mx = Max et 256m = 256Mo de mémoire) mais il y est des cas ou cela ne suffit pas comme vu ci dessus.

Il est aussi possible de spécifier à la JVM la mémoire minimum allouée par la propriété "-Xmx256m" par exemple.

Et pour finir on peut imposer la taille du permGen Space* avec les propriétés "-XX:PermSize=64m" et "-XX:MaxPermSize=64m" par exemple, respectivement la taille par défaut allouée pour le permGen Space et sa taille maximum. (* terme défini et expliqué à la fin de cet article)

EDIT: Après étude, il faut ajouter "-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled" à la liste des paramètres afin d'autoriser le garbage collector à décharger des classes dynamiquement et de nettoyer les objets...

Toutes ces propriétés combinées permettant d'optimiser la gestion de la mémoire par la JVM en charge de faire fonctionner Eclipse ! Ce ne sont pas les seules existantes... mais les seules dont on parle dans cet article.

Voici quelques préconisation fonction de la mémoire RAM de votre machine.

Pour 512Mo de Ram: -vmargs -Xms256m -Xmx256m -XX:PermSize=64m -XX:MaxPermSize=64m -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

Pour 1Go de Ram: -vmargs -Xms512m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=128m -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

Pour 2Go de Ram: -vmargs -Xms768m -Xmx768m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled

Après, n'ayant pas testé les configurations supérieures à 2Go, il vaut mieux ne pas se mouiller ! Chacun son opinion sur la question... on a tous des sensibilités différentes quand aux réactions de sa machine.

Qu'est ce que le heap space de la JVM:
Les propriétés -Xms768m et -Xmx768m permettent de spécifier la taille du heap space de la JVM, la taille de la mémoire utilisée pour faire vivre les objets java, la taille du dépot où sont stockés les objets en vie, les objets morts et la mémoire libre. C'est le Garbage Collector (GC) de la JVM qui s'occupe de nettoyer tout ca en fonction de la taille allouée à la mémoire. Un objet inutilisé (aucun pointeur (variable) qui y fait référence) est théoriquement supprimé de la mémoire par le GC quand celui ci se charge de nettoyer la mémoire.

Qu'est ce que le permGen space de la JVM:
Spécifique à la JVM Sun, cette zone mémoire contient tout ce qui n'est pas géré par le GC; tout ce qui est relatif au classes (leur structure: méthodes, champs, annotations...), les champs static, les chaines littérales... On spécifie le permGen space avec les propriétés -XX:PermSize=256m et -XX:MaxPermSize=256m par exemple. Plus on a de classes différentes plus il faut augmenter la taille de cette zone mémoire.

-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled ?


Ressources:
http://www.eclipsezone.com/eclipse/forums/t61618.html
http://edocs.bea.com/wls/docs61/perform/JVMTuning.html
http://www.developpez.net/forums/showthread.php?t=438282
http://java.sun.com
http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html
http://java.sun.com/docs/hotspot/HotSpotFAQ.html
http://java.sun.com/performance/reference/whitepapers/6_performance.html
http://wiki.eclipse.org/FAQ_How_do_I_increase_the_permgen_size_available_to_Eclipse%3F
etc...