Affichage des articles dont le libellé est performance. Afficher tous les articles
Affichage des articles dont le libellé est performance. Afficher tous les articles

jeudi 29 août 2013

Le test de performance en JAVA / JEE


But du guide

Ce petit article a pour objectif de guider à travers les tests de performances sur une application JAVA/JEE. Je le rédige pour retranscrire mon expérience et peut être éviter à certains les écueils que j'ai rencontré. La tâche étant ardue, je ne serai pas exhaustif. De plus, ce guide étant rédigé au fur et à mesure, il faut toujours le considérer comme un work in progress.

Optimiser ou valider une capacité ?

Un test de performance est une opération difficile si on ne la prend pas par le bon bout. Il faut d’abord savoir ce que l’on cherche : cherche-t-on des optimisations pour améliorer le temps de réponse d’une application,  ou cherche-t-on à valider la capacité d’une application ?
En règles général, les deux axes sont intéressants, mais il convient de séparer les analyses pour ne pas se perdre.
Optimiser
Pour trouver des optimisations, la représentativité n’est pas nécessaire. Vous pouvez effectuer et valider des optimisations sur votre poste à l'aide de votre eclipse.
Test de capacité
Pour vérifier qu’une application est capable de supporter une charge à X utilisateurs, la représentativité est fondamentale.Il faut obligatoirement disposer de ressources identiques à celles utilisée en production.

Pré-requis

Les moyens

Dans l’analyse de tout phénomène complexe, l’analyse déductive est limitée par de multiples biais. C’est particulièrement vrai pour l’étude des performances d’un programme. 
En effet, l’état du réseau, la le serveur et ses processus en arrière plan, sont autant de biais dans le résultat final. La variabilité d’un résultat peut être grande. Il faut donc:
  • Essayer au maximum de disposer de ressources fraiche qui ne sont pas polluées par de multiples installation. Le mieux est de disposer d'une machine neuve ou fraichement masterisée pour le test. 
  • Répéter plusieurs voir les tests avant de conclure
  • S’assurer que la configuration sur laquelle s'effectue les tests ne varie pas. Il ne faut pas installer de nouveau programme en cours de route.
Statistiquement, l’écart type mesure la dispersion moyenne d’un résultat. On considère que l’écart type caractérise une information valide si elle ne dépasse pas 25% de la valeur moyenne.

Outils

Il existe une bonne quantité d'outils pour l'analyse de performance. Nous nous concentrons sur les gratuits.

JVisualVM:


Est un outil qui permet d'observer la machine virtuelle. Il fournit notamment les indications clés pour la consommation de performance.
- Mémoire
- CPU
- Thread
- Entrée sortie réseau

L'écran à gauche permet de sélectionner l'application que vous souhaiter observer. 



Resources monitor windows :


JMeter :


 

Optimiser

Méthodologie

La méthodologie pour optimiser est classique. A partir d'une observation, nous effectuons une analyse, puis nous effectuons des propositions, ces propositions doivent être implémentées puis testées.

Préparer un test

Dans les environnements de développements normaux, les applications sont plus réactives qu'en production. Il existe plusieurs raison à cela:
- Il n'y a qu'un utilisateur
- Les données en base ne sont pas représentatives forcément représentative d'une volumétrie
- Quand une personne développe un programme, elle est souvent indulgente et tolérante à une réactivité lente.

Recréer l'ensemble de ces conditions peut être compliqué, mais il faut consacrer un minimum d'effort à rendre le phénomène observable. Par exemple, lorsqu'on cherche à améliorer un temps de réponse et que notre poste sert une page en un temps raisonnable. Il faut détériorer la situation pour que la lenteur soit visible.

Observation

Le but de l'observation est de déterminer quelle est la ressource critique. S'il s'afit d'optimiser le temps de réponse, nous observerons particulièrement le CPU, le nombre d'entrée sortie, le nombre de thread en attente.

Observer le CPU: 


Pour observer le CPU, on utilise le moniteur windows. Cette information nous permettent de déterminer quelle est l'élément incriminé dans la consommation excessive. Dans le cas le plus courant, il s'agit de déterminer si la consommation est à imputer à la DB ou au CPU. Nous l'illustrons dans les captures d'écran suivantes:

 Consommation excessive de CPU côté JAVA capture système
Dans cette capture nous voyons que le processus qui consomme le plus de processeur est javaw.exe. Il consomme 30%. 

Consommation excessive de CPU côté DB
Dans cette capture, nous voyons que la consommation excessive de CPU est faite par le process mysqld.exe. Hormis cela, le processus JAVA consomme 1.5% de la puissance totale.

Observer les entrées sorties:

Pour observer les entrées sorties, on utilise l'onglet thread de JVisual VM.

Observer la mémoire:

Pour observer la mémoire on utilise les onglets mémoire de JVisualVM.

Analyser

Si la consommation de CPU est excessive dans le JVisual VM. Cela signifie que l'amélioration est à apporter côté JAVA. Si la consommation CPU est surtout côté DB, cela signifie que l'amélioration est à apporter côté base de données. L'expérience nous apprend que:
La consommation excessive de CPU est souvent lié:
- Mauvaise utilisation de la base de données
- A l'utilisation de boucle inutiles
- A la nécessité de dénormaliser

Mauvaise utilisation de la base de données

Boucles inutiles

A l'utilisation de boucle inutiles
Exemple: 
Pour effectuer un rapprochement dans un tableau, on effectue la jointure par le parcours des deux tableaux résultant en un traitement de complexité nxn.

Solutions: 
Utiliser la base de données pour effectuer le rapprochement des données
- A l'utilisation d'une brique technologique qui n'est pas adéquate dans le contexte.

Dénormalisation
Exemple:
Pour  travailler sur une structure arborescente, on utilise la notion générique de parent. Ces solutions sont performantes pour traiter des arbres de profondeur arbitrairement grande. Cependant,dans l'industrie, nous nous trouvons souvent face à des structures arborescentes de profondeur limitée (<10 p="">TODO: Présenter une structure de données qui utilise un arbre générique. 
Solution:Dans ce cas, il est préférable d'utiliser une seule table pour représenter l'index.
TODO: Présenter une structure de données qui utilise un arbre dénormalisé. 

En se basant sur le code tester et trouver des optimisations en local a partir d’un test sans stimulation excessive (1 utilisateur).
Stimuler unitairement les fonctions du serveur en local




Valider une capacité

Méthodologie

-          Estimer la stimulation de manière réaliste
-          Monter un environnement représentatif de la production
-          Trouver les ressources capables de simuler la charge effectuée par des clients.
Dans les deux cas, il faudra surveiller les ressources :

  • Consommation de CPU
  • Mémoire
  • Débit réseau et nombre de socket ouvertes
  • Vitesse du disque

Tester et trouver des optimisations

Les tests de performance sont souvent entrepris lorsqu’un problème apparait. On sait donc souvent par où il faut commencer.

Identifier la fonction critique

Sans médire, il se trouve que la plupart des utilisateurs vont vous dire: "L'application est lente" et c'est la seule information que vous aurez. Il faudra donc:
Pour décrypter la grogne, voici :

  • Est-ce que une page en particulier ralentit toute l'application en consommant toutes les ressources ou est-ce que la lenteur est générale ?
Pour répondre à cette question, il faut tester unitairement  les différentes fonctions de l'application.

Accentuer le trait

Charger le serveur pour obtenir des résultats plus significatifs. 

Tester unitairement la ressource critique


En lançant le sampler de JVisual VM, nous voyons les ressources qui consomment du temps (self time), et celle qui concernent les ressources processeur (self time CPU).
Dans l’exemple ci-dessous, nous voyons que le processeur d’arrière plan du tomcat, consomme beaucoup de temps (self time), en revanche, il ne consomme pas de temps au niveau du processeur. En revanche, la connexion JDBC (ligne en dessous) consomme à la fois du self time et du self time (CPU). C’est le signe infaillible d’un problème de base de données.

Base de données


  • Vérifier que le nombre de requêtes n’est pas excessif
  •  Vérifier que le processeur n’est pas trop sollicité
  •   Vérifier la longueur des requêtes

Identifier les fonctions goulet d’étranglement qui sont évidents sans charge particulières.
Utiliser un réseau WIFI accentue les lenteurs liée au nombre de requêtes, cela peut être un bon moyen pour constater une amélioration des performances.

mercredi 26 mai 2010

Transaction explicites sous Spring et JPA dans les applications Batch

Il m'a été difficile d'utiliser une application de traitement batch utilisant Hibernate, JPA. En utilisant des transactions explicite.

J'avais le message "org.hibernate.SessionException: Session is closed!"

Pour démmarrer le contexte transactionnel, j'ai utilisé les lignes suivantes


DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("MaTransaction");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
/** pour démarrer le context transactionnel */
transactionManager.getTransaction(def);


Comment économiser de la mémoire :
- Faire des commit intermédiaires

Comment gagner de la vitesse :
- Faire des insertions et des select dans une table est une opération couteuse (car le recalcul des index prend de plus en plus de temps)

jeudi 28 février 2008

Utiliser la JConsole avec tomcat

JConsole est un utilitaire fourni avec le JDK. Il permet de voir l'état d'une machine virtuelle et il est particulièrement utile lorsqu'il s'agit d'effectuer le diagnostic de performance d'une application.

Pour une application Web, il faut observer le tomcat. Pour ce faire, on crée dans le répertoire bin un fichier setenv.sh en ajoutant la ligne suivante :

if [ "$1" = "start" ]; then
export JAVA_OPTS="-Dcom.sun.management.jmxremote \
-Dcom.sun.management.jmxremote.port=50001 \
-Dcom.sun.management.jmxremote.ssl=false \
-Dcom.sun.management.jmxremote.authenticate=false"
fi



Ou bien sous windows dans setclasspath (de Tomcat 6.0)
set JAVA_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=50001 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false"

Ensuite il faut lancer JConsole et se connecter sur la machine à observer sur le port 50000. Bien entendu, il est possible de sécuriser l'accès à ces informations.


-verbose:class permet d'afficher d'ou sont chargée les différentes classes.

mardi 23 octobre 2007

Mesure des performance d'une application WEB

Pour un sujet si complexe, il est pratiquement impossible, d'adresser toutes les problématiques dans un seul exposé. Je m'efforcerais de rester aux exigences les plus courantes que tente de vérifier une étude de performance. Nous nous attachons au cas d'une application WEB à visibilité grand public.

Objectifs

Dans la plupart des cas, une étude de performance vise à ce qu'une application réponde rapidement à un utilisateur. Or cette rapidité est un critère psychologique . Un être humain fonde sa détermination de la rapidité : A partir de la complexité qu'il suppose, du prix qu'il accorde à son action, de son âge. C'est à dire qu'une transaction bancaire peut psychologiquement tarder plus que le visionnage d'une publicité.

Toute hypothèse sur l'utilisateur est donc vaseuse, deux utilisateurs ne font pas la même utilisation de performance, c'est pourtant par là qu'il faut commencer. Un utilisateur n'a généralement pas une utilisation prudente d'un logiciel, il vaut mieux donc supposer qu'il clique n'importe comment. Sur une connexion haut-débit, on considère qu'un utilisateur n'attend pas si le temps de réponse est inférieur à deux secondes et l'application doit fonctionner de manière continue.

A partir de là on détermine en gros les critères objectifs :

Rapidité
2 secondes en moyenne pour que service réponde quelques soit l'action

Charge
2000 visiteurs simultanés

Stabilité
Le système doit être stable

Tester les performances

Bien qu'une étude de performance appelle des réponses essentielement techniques, la mesure des performances d'une application ne constitue pas une fin en soi. En effet, la vitesse de traitement et l'occupation mémoire d'une application (la qualité de la programmation) ne suffit pas à mesurer la qualité dans d'une application. L'étude de la performance d'une application doit donc être menée en veillant à ne pas s'éloigner du réel. Tous les aspects techniques sont considérés en gardant à l'esprit ce fil rouge.

Les critères usuels sont :

  • Stabilité

  • Rapidité

  • Capacité de tenir la charge


Rapidité
La rapidité renseigne sur la vtesse d'un traitement. C'est un critère mesurable qui doit être mis en rapport avec la capacité de charge ( elle influencera grandement ce paramètre)

Chaque temps de réponse sera mis en relation avec une charge. L'utilisateur final est l'étalon pour la rapidité.

Charge

C'est la capacité à traiter simultanément un grand nombre de requêtes. On distingue deux seuils :
  • Le seuil au delà duquel le temps de réponse devient inacceptable

  • Le seuil d'écroulement



Stabilité

C'est la capacité pour l'application de fonctionner longtemps sans être redémarrée. Le java, avec son garbage collector fournit de fortes garanties de stabilité. Cependant, si l'on se sert de concept un peu avancés comme les Threads, ce genre de problème peut survenir.

On peut qualifier l'instabilité


  • Par la charge qui provoque l'écroulement

  • Par le nombre de jours sans redémarrage

Moyens et condition de fonctionnement réel

Un test est d'autant plus pertinent qu'il reproduit les moyens et les conditions réelles de la production.

Serveur production :

  • Mémoire vive : 2 Go

  • Vitesse processeurs : 1,5 GHz

  • Nombre serveurs : 2

  • Nombre d'applications : 4

  • Niveau de log INFO

  • Equilibrage de charge : OUI

  • On suppose que le débit réseau n'est pas problématique

Moyens et condition de fonctionnement de test de charge

Pour les tests de charge, nous ne disposons pas des outils permettant de reconstituer une expérience utilisateur, nous avons quelques restrictions et nous livrant à certaines approximations :

  • Nos moyens nous permettent seulement de faire le test dans un contexte n'incluant pas les étapes d'identification. C'est une hypothèse optimiste que de croire que l'identification ne sera pas pénalisante, d'un autre coté, elle ne dépend pas de l'équipe AIDA.

  • Nous nous baserons sur la requête la plus pénalisante pour le système, nous plaçant dans un cas passimiste. La requête la plus pénalisante est celle qui insterroge tous les partenaires.

  • La requête sera toujours identique, sur du HTTP, portera toujours sur le même utilisateur et le même dossier.

Objectifs techniques

Estimation

Nombre d'utilisateur potentiel

C'est le nombre total d'utilisateurs capable de se connecter sur le site.


Nombre de visiteurs simultanés

C'est le nombre estimé de visiteurs simultanés sur le site en période chargée


Nombre d'actions moyenne d'un utilisateur

C'est le nombre de requête qu'un utilisateur est succeptible de déclencher pendant sa visite sur le site.


Site à pic de charge

Un site à pic de charge est périodiquement plus chargé (En dehors des cycle naturel jour/nuit et hebdomadaires)


Equlibrage de charge

L'équilibrage de charge intervient au niveau de l'exploitation, aussi il nous avons déjà la garantie d'avoir un système scalable.


Le temps moyen d'une session

C'est le temps moyen d'une session estimé. Mieux veut prévoir court.


Facteur de zapping

Plus il est facile de se déplacer dans l'application et de déclencher des actions, plus les actions seront effectivement déclenchées. Donc un site à clics provoquent un surcroit de requêtes.



  • Nombre d'utilisateur potentiel : 200000

  • Nombre de visiteurs simultanés : 2000

  • Nombre d'actions moyenne d'un utilisateur : 4

  • Site à pic de charge : Déclenchement ou pas de pic de charge : oui

  • Le temps moyen d'une session : 5 mn

  • Facteur de zapping : x 2



A l'aide de ces informations, on pourra se faire une idée du nombre de requêtes effectuées chaque unité de temps, cela demeure cependant indicatif.


2000 x 4 x 2 /5 = 3200 requête/mn

soit 3200 /60 = 53 requête/s

Utilisation de Jmeter

Jmeter permet de lancer des requêtes http en spécifiant des contraintes temporelle (Echelon et cycles)

Scénarios

On définit plusieurs scénarios de charge :

Charge instantanée

On envoie 50 requêtes liste dossier en 1 seconde, chaque requête ne répond que lorsque l'ensemble des dossiers est rappatrié.


La requête envoyée au serveur WS est toujours la même. La réponse l'est également.


Charge durant une minute


On envoie 3000 requêtes en 60 secondes (non effectué)

Résultats

Pour chaque résultat on présente :

  • Le temps moyen qui est le temps que met en moyenne une requête pour répondre. Il fait la sytnhèse des bonnes et des mauvaise expériences utilisateurs. Plus les résultats ont une forte dispertion et plus il faut traiter cette donnée avec circonspection.

  • Le temps médian qui est le temps qu'expérimente un utilisateur moyen. Il donne la rapidité d'une requête pour un utilisateur faisant une expérience normale du produit.

  • La déviation (Ecart-type) donne une représentation de la dispersion des résultats. Elle donne une idée des processus(Thread) zombies.

15 itérations de charge instantanée 50 requêtes


    Serveur sur machine bureautique, partenaire réels proxié

  • Temps moyen : 18 sec

  • Temps médian : 17 sec

  • Temps médian : 18 sec





    Configuration : Serveur sur machine bureautique, partenaire bouchons proxié sans latence

  • Temps moyen : 16 secTemps moyen : 16 sec

  • Temps médian : 3,5 sec

  • Deviation 18 sec



15 itérations de charge instantanée 100 requêtes



    Configuration : Serveur sur machine bureautique, partenaire bouchons proxié sans latence

  • Temps moyen : 32 sec

  • Temps median : 3,5sec

  • Deviation : 87 sec





15 itérations de charge instantanée 150 requêtes


    Configuration : Serveur sur machine bureautique, partenaire bouchons proxié sans latence

  • Temps moyen : 32 sec

  • Temps median : 3,5sec

  • Deviation : 87 sec





Conclusion

Dans les situations ou le serveur bouchon est utilisé, ces résultats montrent que la dispersion croit avec la charge, pour autant le temps de réponse médian reste du même ordre de grandeur.


Cette dispersion peut être expliquées par un deadlock dans la partie-core (Qui pourrait être dangereux). Elle peut être également expliquée par une saturation des partenaires, comme nous n'utilisons qu'une simulation de partenaires (Et qu'il est fort probable que les ressources des partenaires ne saturent pas aussi facilement) Il faut donc continuer les test en se servant de partenaires réel plutôt que les bouchons.


Pour ce qui concerne la stabilité : plus le serveur est fragilisé, plus il se fragilise. Il faut donc éviter les zones rouges.


Ces test mettent également en évidence qu'il est nécessaire de mesurer les performances des partenaires depuis le MAP.