RSS
 

Posts Tagged ‘Audit’

Optimiser une application JAVA – Partie 2

20 juin

Avec l’arrivée d’une montée en charge, ou face à une volumétrie croissante, les applications Java peuvent rencontrer des problèmes de performance. A ce moment se pose la question de l’optimisation. Comment optimiser efficacement ?

 

Cet article est la suite de l’article « Optimiser une application JAVA – Partie 1« .

Il présente les différents étapes nécessaires à une optimisation efficace d’une application JAVA.

Pour rappel :

Les étapes de l’optimisation

Une optimisation se réalise de manière cyclique selon les étapes suivantes :

  1. Identifier les processus les plus pénalisants

  2. Cibler et réaliser une optimisation

  3. Vérifier le gain obtenu

  4. Si le gain obtenu est satisfaisant, l’optimisation est terminée. Sinon retour à l’étape 1, en cherchant le nouvel élément le plus pénalisant.

1. Identifier les processus pénalisants

Sans cette étape, il est impossible de réaliser une optimisation efficace. Elle nous permet de focaliser les travaux d’optimisation sur les points les plus bloquants. L’utilisation d’un profiler facilite leur recherche. Il existe de nombreux profiler p our J ava . Les captures d’écran ci-dessous illustre des résultats obtenus avec Your Kit Java Profiler (YJP) , un profiler dont l’utilisation et la mise en place est simple et rapide.

 

Les sources de lenteurs d’une application peuvent avoir de nombreuses origines. Les plus fréquemment rencontrées sont :

  • une utilisation CPU trop importante

  • une saturation de la mémoire

  • les contentions de threads

  • un nombre trop important de requêtes SQL provoquant des latences à cause des appels réseaux

  • ou bien encore des libérations massives d’objets volumineux, provoquant un pique d’activité pour le Garbage Collector.

 

Le profiler nous permet de mesurer l’activité de tous ces éléments, comme l’illustre les capture d’écran ci-dessous :

  • Les méthodes les plus consommatrices en CPU

    Mesures CPU

     

     

  • Les méthodes les plus consommatrices en mémoire

    Mesures mémoire

  • Les contentions de threads

    Etats threads

  • Les requêtes SQL utilisées, avec leurs temps d’exécution et leurs nombres d’invocations

    Requêtes SQL

  • L’activité du Garbage Collector

    Mesures Garbage Collector

     

2. Cibler et réaliser des optimisations

Les résultats du profilage nous permettent maintenant de connaître les méthodes les plus critiques. L’optimisation devra donc se concentrer sur ces méthodes afin de garantir un gain significatif. Il nous reste donc à déterminer quoi faire. Selon les problématiques rencontrées, il existe plusieurs solutions pour améliorer les temps d’exécution. Ci-dessous, une liste présente des problèmes fréquents.

Activité trop importante du CPU

Les pics de CPU sont souvent provoqués par des boucles ou des méthodes dont les traitements durent longtemps. Une solution peut être de découper le traitement :

  • le traitement peut-il être réalisé en plusieurs étapes ?

  • Le traitement peut-il être adapter à un algorithme multithreadé ?

Mémoire saturée

La saturation de la mémoire peut être provoquée par un traitement qui charge en mémoire un nombre trop important de données. Par exemple, une méthode qui crée une liste de tout le contenu d’une table, alors que celle-ci contient plusieurs dizaines de milliers de tuples. Dans un cas comme celui-ci, la solution est soit de récupérer les données par lots de données, ou d’utiliser un curseur pour traiter les données une à une sans charger toute la table d’un coup.

Contention de threads

Une contention de threads provient d’un ensemble de threads qui se retrouvent dans l’état bloqué. Si ce blocage durent trop longtemps, l’application peut subir des latences. Les blocages peuvent être induit à plusieurs niveaux : soit au niveau java à cause de l’utilisation de synchronize, soit au niveau de la base de données à cause de deadlocks. Dans cette situation, la solution provient souvent de l’amélioration de l’algorithme afin de contourner l’utilisation des verrous, ou d’en réduire au maximum l’utilisation.

Requêtes SQL pénalisantes

Les requêtes SQL peuvent être à l’origine de plusieurs problèmes.

Des temps de réponses de requêtes trop longs

Une requête SQL qui met trop longtemps à répondre, par exemple, demandera des optimisations au niveau de la base de données. Ce genre de problème se résous en analysant le plan d’exécution ( EXPLAIN PLAN) de la requête concernée.

Un nombre très important de requêtes

Lorsqu’une application provoque un très grand nombre de requêtes SQL, elle est souvent victime de latence à cause du nombre d’appels répétés à la base de données. Dans cette situation, la solution dépend de l’usage des requêtes SQL.

De nombreuses requêtes SELECT identiques

Un nombre important de requêtes de type SELECT identique peut être résolu par l’utilisation de recherche en lot en utilisant une clause IN. Par exemple, un traitement qui engendre un grand nombre de requêtes du genre suivant :

SELECT * FROM PRODUCT WHERE PRODUCT_ID = ?

Si le traitement le permet, il sera plus efficace de traiter les produits par lots, et de les rechercher en une seule requête :

SELECT * FROM PRODUCT WHERE PRODUCT_ID IN (?, … ,?)

De nombreuses requêtes SELECT hétérogènes

Par ailleurs, le problème provient peut être d’un nombre important de requêtes hétérogènes. Si les requêtes sont toutes de types SELECT et qu’elles proviennent du même processus, alors les données sont peut être liées. Dans ce cas, il est préférables d’utiliser des jointures pour rechercher l’ensemble des données en une seule requête plutôt que de les rechercher indépendamment. Par exemple, un traitement qui recherche les prix d’un ensemble de produits, en effectuant une première recherche pour trouver les informations sur les produits puis leurs prix :

SELECT * FROM PRODUCT WHERE PRODUCT_ID IN (?, … ,?)
SELECT * FROM PRODUCT_PRICE WHERE PRODUCT_ID IN (?, … ,?)

Il sera plus performant de rechercher les données en combinant les deux requêtes :

SELECT *
FROM PRODUCT P
INNER JOIN PRODUCT_PRICE PP ON PP.PRODUCT_ID = P.PRODUCT_ID
WHERE P.PRODUCT_ID IN (?, … ,?)

De nombreuses requêtes hétérogènes et de tous types

Dans des traitements batches par exemple, on peut se retrouver dans une situation qui requière de très nombreuses opérations de mises à jour. Dans une configuration comme celle-ci, l’utilisation du mode JDBC batch-update permet d’améliorer très significativement les performances, en envoyant en une seule fois l’ensemble des opérations à effectuer à la base de données. Deux modes sont disponibles qui répondent à des usages différents :

  1. Mode PREPARED_STATEMENT : on souhaite envoyer un nombre important de mises à jour mais toujours avec la même requête, seul les paramètres de cette requête changent.
    Exemple : On souhaite mettre à jour les noms de produits d’une liste de produits

     
    
    PreparedStatement ps = connection.prepareStatement(
    "UPDATE PRODUCT SET INTERNAL_NAME = ? WHERE PRODUCT_ID = ?");
    ps.setString(1, "Produit1");
    ps.setString(2, "0001");
    ps.addBatch();
    ps.setString(1, "Produit2");
    ps.setString(2, "0002");
    ps.addBatch();
    ps.executeBatch();
    
  2. Mode STATEMENT : on souhaite envoyer un grand nombre de requêtes toutes différentes UPDATE et/ou DELETE mélangés avec des paramètres, des opérations et des clauses différentes.
    Exemple : On souhaite mettre à jour un produit, supprimer un autre et changer un prix, toutes les requêtes seront envoyés en un seul appel bien qu’elles soient toutes différentes.

    Statement st = connection.createStatement() ;
    st.addBatch(
    "UPDATE PRODUCT SET INTERNAL_NAME = 'TUTU' WHERE PRODUCT_ID = '1'");
    st.addBatch("DELETE FROM PRODUCT WHERE PRODUCT_ID = '3'");
    st.addBatch(
    "UPDATE PRODUCT_PRICE SET PRICE = 29.99 WHERE PRODUCT_ID = '5'");
    st.executeBatch();
    

     

    3. Valider l’efficacité des optimisations réalisées

    La dernière étape consiste à profiler à nouveau l’application pour mesurer le gain obtenu. Si l’optimisation réalisée est efficace, le partie optimisée ne devrait plus apparaître comme critique.

    Ensuite, il reste à réitérer les étapes de l’optimisation sur les points critiques suivants jusqu’à obtenir une optimisation globale satisfaisante.

 

PROJETS « ASSURANCE-CREDIT »

01 fév

Organisme Crédit


Nos références dans le domaine de l’assurance et du crédit sont :
___________________________________________________________________________________________________________
Mise en œuvre d’une plate-forme de tests de montée en charge & d’audit « automatisée »
___________________________________________________________________________________________________________
Etude comparative des solutions de persistance Open Source (fonctionnalités, performances) et du plan de migration par rapport à la solution actuelle
___________________________________________________________________________________________________________
Mise en œuvre du framework J2EE sur le premier projet d’envergure (refonte du back Office)
___________________________________________________________________________________________________________
Audit d’organisation => Proposition d’une organisation propre à intégrer une problématique d’urbanisation de système et de réutilisation des composants Définition des flux inter service et des outils à mettre en œuvre pour les gérer
___________________________________________________________________________________________________________
Proof Of Concept « Flex / Air » pour la refonte d’un Front Office de proposition de crédit aux concessionnaires automobile.
___________________________________________________________________________________________________________
Mise en oeuvre d’une plate-forme d’industrialisation des intégrations continues, des tests, etc.

 
Commentaires fermés

Posted in