février
2008
Sur l’application surlaquelle je travaille actuellement au boulot, j’ai été amené à réaliser quelques tests de profiling, histoire de débusquer les goulots d’étranglement et les optimiser (si possible).
L’application en question est une application Web tournant sur Tomcat et qui utilise les technos suivantes:
- JSF: La Sun RI 1.2_07 (Mojarra)
- Richfaces 3.1.3
- Facelets
- Spring framework 2.5.1: pour la DI et pour l’abstraction JDBC
- De nombreuses commons de jakarta (dbcp, pooling, collections, logging, etc.)
- Log4j
- MySQL 5
L’IHM est assez complexe avec de l’Ajax à gog, des images complexes générées dynamiquement, et bien sûr, pour combler le tout, le volume des données traitées est imposant.
Donc, avant de lancer les tests, j’etais presque sûr que les goulots d’étranglement etaient dans la couche DAO, la couche services (à cause de calculs complexes) et peut être aussi dans la génération dynamique des images.
Vous vous en doutez déjà, j’avais complètement tort …
Voici un extrait des résultats du profiling (temps d’exécution) (réalisé avec TPTP):
Pour résumer, ou encore textuellement, ça donne:
- 32% du temp processeur passé dans ajax4jsf, plus précisément dans le package component
- 28% du temp processeur passé dans Mojarra, plus précisément dans le package component
- 22% du temp processeur passé dans Richfaces, plus précisément dans le package component
- Ensuite la couche JDBC ave 8%
- 3% dans la génération dynamique des images (notre propre code, enfin)
Effrayant … 82% du temps processeur est consumé dans la couche présentation et est partagé par Mojarra, Richfaces et Ajax4jsf.
La logique métier, aussi complexe soit elle, n’apparait pas dans le top 10, donc consomme moins de 0.5% du temps processeur.
Même la couche JDBC, le usual suspect dans les problèmes de performances ne s’accapare que de 8% du gateau.
Il se peut que je refasses des tests vec MyFaces au lieu de Mojarra, car il est facile d’interchanger les implémentations JSF.
Par contre, il est trop tard pour ce qui est de Richfaces/Ajax4jsf.
Là, je me poses des questions … Est ce que ça vient de notre IHM complexe et/ou style de codage ou est ce que c’est plutôt de la faute des librairies utilisées ?
Et est ce spécifique à JSF ou est ce que ça touche d’autres frameworks ?
N’hésitez pas à faire part de vos propres expériences
adumont>Salut,
Non, pas vraiment, la différence constatée était minime au plus …
On a du plutôt opter pour une stratégie de mise en cache agressive pour pallier à ce problème de performance.
De toute façon, nous avons eu une grosse montée au niveau du volume de données traités, de sorte que le rapport a changé (entre le temps de calcul/génération et le temps de rendu). Donc, même si le rendu prenait plusieurs secondes, le traitement lui prenait des dizaines de secondes, donc …
Et là, on envisage de mettre en place un cluster (ou du moins séparer le serveur d’applications et la BD sur deux machines).
Bonjour,
J’ai un problème similaire sur une application de gestion de contenu (notamment écriture d’articles par des journalistes).
Votre refactoring, notamment en utilisant des régions, a-t-il donné des résultats positifs ?
Je suis vraiment intéressé, car à partir de 20 utilisateurs simultanés la lenteur de notre application devient vraiment génante (sur un serveur avec processeur quadri-coeurs quand même…)
Merci d’avance !
Bonjour,
article intéressant.
êtes-vous allé plus loin dans vos investigations ?
Avez-vous quelques retours d’expérience à nous fournir ?
G.
Bonjour,
En fait, comme le problème venait surtout de Richfaces+ajax4jsf, je n’ai pas encore effectué le profiling en utilisant MyFaces.
De plus, dans mon cas au moins, le profiling est terriblement pénible et lourd, et prend un temps monstre
On est en train de faire un refactoring monstre sur une nouvelle branche de l’application, et je comptes la profiler dès qu’une version stable et fonctionnele soit sur pied.
Bonjour,
j’ai développé et maintiens actuellement une application Web basée sur MyFaces.
Ton étude des perfs avec cette implémentation de JSF m’intéresse. Auras-tu l’occasion d’en faire une bientôt ?
Je serais également amené à faire la même chose sur mon appli. Ca sera une bonne occasion de confronter nos résultats.
Merci de me tenir au courant.
As tu regardé du coté des logs des framework ? Tester avec des logs en niveau DEBUG dégrade fortement les performance. J’ai l’expérience d’un taglib (dysplaytag je crois) qui consommait énormément de ressources en DEBUG.
@Christophe> Oui en effet, on utilise les regions et c’est vrai que ça améliore un peu les choses … et pourtant …
Je pense que c’est la phase de rendu qui consomme tant de ressources. A vérifier.
A tout hasard, je suppose que vous avez utilisé les notion de region de a4j.
on teste cette librairie en ce moment et les régions permettent d’accelerer grandement les choses.
@cedric> Naturellement, toute application JSF de taille décente est forcément noyé dans les EL. Mais tout de même, 82% du temps processeur ?
Je vais approfondir l’étude bientôt pour retrouver qui au juste est en cause, et peut être filer un Bugreport aux concernés.
Une implémentation EL qui n’utilise pas le caching est un bon candidat au fait, vu qu’elle utilise intensivement la reflection.
Tu as beaucoup d’expressions EL sur tes pages? Ça pourrait expliquer une partie du temps passé dans la couche de présentation.
Je ne le crois pas … notre application ne fait qu’attendre gentillement que Tomcat récupère une requête pour que le show commence.
De plus, comme tu l’as dit, on a exactement aucun contrôle sur la chose, à moins de recoder une implémentation JSF + les jeux de composants Richfaces et ajax4jsf en assembleur, puis de créer le wrapper C et JNI au dessus
Je serais curieux de voir les résultats d’autres frameworks dans des applications complexes … Je parle surtout de frameworks orientés composants comme Wicket ou Tapestry.
J’avais lu, il y a quelques temps, qu’un groupe de développeur avais trouvé que 80% de son code passé par quelques instructions. Ils ont mis les moyen pour l’optimiser, et finalement, ils l’ont fait en assembleur. Le seul hic, c’est que c’était la boucle d’attente (vous savez celle qui sert à dispatcher les messages windows).
Je ne connais pas du tout jsf,et ton appli est en web, mais peut être que ton problème est le même.
Est-ce que ce ne serait pas causé par les latences du web, ou de l’ajax (par exemple une boucle qui lit ce qu’on lui envoie, et donc consomme beaucoup)
Hello,
@fabszn> C’est indiqué juste avant la figure: TPTP, un plugin eclipse de profiling.
@adiGuba> Oui et non … Le temps de réponse est en quelque sorte une fonction linéaire du nombre d’entités sélectionnés. Donc, plus le nombre de données augmente, plus le temps de répons augmente, ce qui est logique.
Mais à partir d’un certain seuil, ça devient gênant en fait.
C’est pour cela qu’on voudrait gagner le moindre microseconde.
Hello,
Effectivement, très intéressant comme étude!
Quel outil as tu utilisé pour les tests de profiling?
@+
Intéressant tout cela !
Une question : as-tu des problèmes de performance avec cette application ? (tu ne le précises pas).
a++