IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

bonnes pratiques liées à la performance ?


Sujet :

Java

  1. #1
    Membre averti
    Inscrit en
    Novembre 2004
    Messages
    53
    Détails du profil
    Informations forums :
    Inscription : Novembre 2004
    Messages : 53
    Par défaut bonnes pratiques liées à la performance ?
    Bonjour à tous.

    Je dois dans le cadre de mon travail réaliser une doc sur les normes de développement JAVA. Celle-ci doit traiter entre autres des conventions de nomenclatures, formatage du code, bonnes pratiques de programmations, etc.

    Je rédige actuellement une partie sur les bonnes pratiques liées à la performance. J'ai abordé les sujets suivants :

    Utilisation des String (dans quel cas utiliser Stringbuffer plutôt que stringbuilder)
    Utilisation des collections (dans quel cas utiliser telle ou telle implémentation)
    Utilisation de Integer.valueOf plutôt que new Integer

    Auriez vous des idées à me soumettre en vrac sur les bonnes pratiques liées à la performance?

    Merci d'avance.

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Eviter les méthode synchronized (donc éviter StringBuffer) si ce n'est pas intéressant, surtout dans les environnement multi-CPU ou le synchronized a un surcoût.
    Utiliser des méthodes "final" (attention c'est moche) ou "private" (même effet) pour les méthodes critique: Diminue la durée de branchement car calcul fait à la compilation (early binding)
    Comme toujours, éviter les boucles inutiles, faire attention aux algos
    Regarder la javadoc, pour beaucoup de classes utilitaire, java explique l'algo et son temps de calcul.
    Eviter la création inutile d'objet (comme tu le mentionne avec integer, mais pour toutes les autres jouyeuseté assimilées)

  3. #3
    Membre expérimenté
    Avatar de JHelp
    Inscrit en
    Octobre 2002
    Messages
    185
    Détails du profil
    Informations forums :
    Inscription : Octobre 2002
    Messages : 185
    Par défaut
    Bonjour,
    Ne pas oublié de mettre à null une reference devenue inutile (pour aider le garbage collector). Faire des méthodes de destructions. (Toujours pour le garbage collector)
    Un petit exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    public void myMethod()
    {
          MyClass oneInstance;
          //
          //Construction de oneInstance, par exemple :
          oneInstance = new MyClass();
          //
          // Faire quelque chose
          // ....
          //
          //Detruit la réfance pour aider le gabage collector
          oneInstance.freeRam();
          oneInstance = null;
    }
    Et mettre dans la méthode freeRam toutes les variables de la classes à null (en détruisant proprement les instances)

    En procédant on gagne en performance car le garbage collector à moins de travail à faire pour déterminer qui il doit détruire. Il fera sont travail par petits bout au lieu de tout faire d'un block quand la mémoire viens à manquer. De plus on évite pas mal de outOfMemory et une consommation de la mémoire vive inutile.

    JHelp

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    JHelp: ce que tu dit est vrai dans un jme, où l'implémentation du garbage collector est soumise à des contraintes spécifique qui l'empêche d'être aussi bon pour l'analyse de la heap. Le fonctionnement du garbage collector est assez complexe, mais coder une methode "nettoyage" dans un objet s'avère complexe au point de vue du code (faut rajouter la méthode, s'arranger qu'elle appelle la méthode sur les autres aobjets etc, jouer avec du type casting). De plus, si tu veux appeler freeRam() au 'bon moment' , tu dois faire un comptage de tes instance et c'est justement ce qu'on veux éviter avec le garbage collector.

    Par contre, çà coute rien de libérer une grosse variable locale dès qu'on en a plus besoin.

    Ex: t'as une liste de 500000 éléments, tu a besoin, dans une boucle, de faire une liste dérivée, çà paie pas de mine de faire un =null avant de faire le new suivant (la mémoire occupé par la précédent sera "libérable" avant de faire le new, tandis que si tu fais x = new MonGrosX(), je pense qu'il n'est libérable qu'après l'assignation.

  5. #5
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    En Java, à mon humble avis, la meilleure solution serait de laisser ce chapitre vide.

    La plate-forme se débrouille très bien pour les optimisations courantes, sans la moindre intervention du programmeur.

    Après, on peut faire intervenir le contexte propre de l'appli.

    Effectivement, une des bases serait de distinguer si on est en Java Me ou JRE ! Si on applique les règles d'optimisation d'un environnement Java Me à un environnement JRE... on arrivera évidemment à l'inverse de ce que l'on veut obtenir.

    Donc, peut être, juste un mot dans ce chapitre : Réfléchissez.

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    D'accord avec toi, cependant, préciser aux lecteur que les méthode synchronized on un surcout et rappeler que, par définition, elles sont un goulot d'étranglement en multi threading, c'est pas du luxe

    Après tout, c'est pas pour rien que java 5 a introduit stringbuilder, les perfs de stringbuffer étaient catastrophiques sur les multi core. Et toujour du bon sens dans l'utilisation des apis de sun, me souviens avoir du intervenir dans un code "lent", tout çà pour me rendre compte que, à chaque "touche du clavier appuyée", il y avait une requête réseau qui sérialisait un bon 50.000 communes avec leur codes postaux et le désérialisait de l'autre coté. Donc voilà, en général, un peu de bon sens

    Sinon, les profilers, çà aide ^^, car dans un environnement objet, on ne vois pas toujours directement les conséquence d'une mauvvaise utilisation d'un objet

  7. #7
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Peut être, mais alors pourquoi le même java 5 a introduit Synchronization optimizations in Mustang, qui rend quasi inutile les distinguos subtils entre StringBuilder et StringBuffer, du point de vue du synchronized s'entend ?

  8. #8
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    j'ai plus les liens sous la main, mais je me souviens de tests de comparaison au niveau de stringbuilder / stringbuffer , dans une machine dual core dans laquelle le gars avait d'abord désactivé le dual core puis ensuite activé le dual core. Les résultat était assez explicite, quand tu activais les dual core, soit présence de 2 cpu, le stringbuffer allait 3 fois moins vite. C'est du au fait que, pour avoir le lock, t'es obligé de passer par lock du bus mémoire le temps de tester et changer la valeur du semaphore qui protège le lock. Cette opération est plus couteuse qu'une simple lecture mémoire.

  9. #9
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Parce que quelqu'un utilise des StringBuffer en accés multi-thread sur des dual core ?? Certainement une expérience pleine d'enseignements !

    Bon, allé, je retourne à mes oignons...

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 132
    Par défaut
    Je dirai que tout le monde à raison

    Car oui, c'est mieux d'utiliser synchronized si on en a pas besoin. Mais je me poserai plutôt la question de savoir si la personne sait à quoi sert synchronized.
    Car synchronized sert aussi aux autres à savoir que cette partie de code est partagée et donc qu'il faut faire attention avant d'y fait le moindre changement.

    Sinon pour les optimisations je dirai qu'il n'y a pas trop de règles et surtout que la plupart du temps en utilisant un profiler on les trouve

    Par exemple une fois en voulant optimiser une partie de code, on s'est aperçu que la méthode qui prenait le plus de temps c'était la concaténation de chaine.

    on voyait partout du: String s = "X"+"y"+"Z";
    ...
    Et bien en utilisant un petit Stringbuilder on a complement enlevé le problème.

    Du même genre, mettre des traces de debug c'est bien mais éviter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    logger.debug("la string est "+object.toString());
    Car on perd du temps a essayer d'afficher une chaine qui ne sert peut-être pas et donc lui préferait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (logger.isDebugEnabled()){
    logger.debug("la string est "+object.toString());
    }
    Sinon il y a le projet findbugs qui donne déjà un bon premier aperçut des dégâts.

  11. #11
    Membre expérimenté Avatar de mOuLi
    Homme Profil pro
    Développeur Java
    Inscrit en
    Avril 2008
    Messages
    170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Avril 2008
    Messages : 170
    Par défaut
    Comme dit précédemment, il existe des outils qui analysent le code source pour pointer certains mauvaises pratiques.
    PMD fait partie de ces outils, et il détaille les tests qu'il fait concernant la partie Optimization Rules
    Du coup ça te donne quelques pratiques.

  12. #12
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par elmor Voir le message
    on voyait partout du: String s = "X"+"y"+"Z";
    ...
    Et bien en utilisant un petit Stringbuilder on a complement enlevé le problème.
    Petite nuance sur ce point !

    L'opérateur + n'est pas à bannir et doit être privilégier au StringBuffer/StringBuilder car nettement plus lisible. Il suffit de comparer les deux codes pour s'en convaincre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    String s = "X"+"y"+"Z";
     
    String s = new StringBuilder("X").append("y").append("Z").toString();
    En effet au pire l'opérateur + génèrera un code équivalent avec un StringBuffer/StringBuilder (selon la version de Java) ce qui reviendrait strictement au même. Mais il peut également bénéficier d'optimisation du compilateur qui effectuera la concaténation des constantes, ce qui reviendrait dans le cas présent à écrire ceci :



    Ce qui faut bannir c'est l'opérateur += ou tout code assimilé destiné à modifier une chaine existante, c'est à dire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    String s = "a" + uneVariable; // Cette ligne seule c'est OK
    // Mais pas les lignes suivantes :
    s += "c";
    s = s + "d";
    En effet le code ci-dessus revient à faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    String s = new StringBuilder("a").append(uneVariable); // Cette ligne seule c'est OK
    // Mais pas les lignes suivantes :
    s = new StringBuilder(s).append("c").toString();
    s = new StringBuilder(s).append("d").toString();
    A chaque ligne on crée un nouveau StringBuilder que l'on modifie pour transformer enfin en String. Ce qui donne deux créations et deux destructions d'objets par ligne

    Avec de "petites" chaines c'est presque insensible, mais avec des chaines de taille imposante cela revient à allouer une quantité faramineuse d'objets temporaire...






    En ce qui concerne le final, je suis plutôt d'accord pour l'utiliser massivement sur les paramètres et variables locales lorsque c'est possible.
    Par contre sur les méthodes c'est différents car cela aura un impact sur les possibilité d'héritage offerte pas la classe...



    a++

  13. #13
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par gifffftane Voir le message
    Parce que quelqu'un utilise des StringBuffer en accés multi-thread sur des dual core ?? Certainement une expérience pleine d'enseignements !

    Bon, allé, je retourne à mes oignons...
    J'ai jamais dit çà Juste que sur un multicore, les stringbuffer sont plus lent à cause du fait que ses méthodes sont synchronized. Alors que justement, les cas d'utilisations par des threads multiples sont extrèmement rares -> apparition du stringbuilder qui, lui, n'est pas synchronized et donc plus performant en environnement multi-cpu (pas de lock nécessaire au niveau du bus mémoire)

  14. #14
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Donc, j'ai raison, non ?...

    Quelqu'un programme en environnement mono-thread en se disant que s'il était sur un dual core multi-thread il ne faudrait pas employer abusivement de synchronized ??

    (troll en vue, sur ce coup là, ai-je l'impression)

  15. #15
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    non non t'y est pas, ton objet n'est utilisé que par un thread, ton application, éventuellement, n'a qu'un Thread voir, pour les tests que j'ai vu, un seul main avec une loop suffisait à montrer la différence.

    Qu'il y aie ou non plusieurs thread accédant à ton stringbuffer, la règle est que la jvm dois obtenir un lock sur l'objet stringbuffer avant d'appeler la méthode synchronized. (Regarde les specs JVM si tu me crois pas) Dans un OS type x86 multi cpu, en arrière plan, ce lock ne peut s'obtenir que de la manière suivante:

    1) lock du bus mémoire
    2) accès à l'octet mémoire contenant la valeur du lock
    3) si lock non encore obtenu par un autre thread, mise en place du lock, sinon delock du bus, attente légère, retour en 1, eventuellement mise en place de système de wait plus avancé.
    4) libération lock bus, la donnée mémoire à été modifiée atomiquement.

    Si tu ne lock pas le bus, l'autre cpu (ou core) pourrais modifier la valeur du lock en cours de route, et tu risque d'avoir deux threads, sur 2 CPUs différents qui "lockent" le même sémaphore en même temps. Ce n'est le but recherché.
    La différence ce situe dans le fait que, pour un mono cpu, tu n'as pas besoin du lock bus mémoire, t'es certain qu'aucun autre cpu n'accèdera à la mémoire en même temps. Donc, sur nos machine de bureau, avant l'apparition des dual core, hyper threadings ou autre, le problème ne se posais pas (on avait pas besoin de système de sémaphore compliqué)

    En résumé, le problème du synchronized se résume à un problème de synchronisation de cpu, obligatoire pour rentrer dans une bloc synchronized. Certes, mustang améliore les synchronized en détectant les synchronized inutiles, mais dans le cas présent, pour le stringbuffer, il n'est pas considéré comme inutile. C'est la raison de l'apparition de Stringbuilder, qui lui n'a pas besoin de la lourdeur des locks et est donc plus performants en machine multi-cpus.

    Si t'es en machine single-cpu, le synchronized a vraiement un surcout négligeable par contre.

  16. #16
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Bon, admettons.

    Donc, en résumé, dans le chapitre Performance Java on mettrait :

    1. Utilisez les StringBuilder
    2. Réfléchissez

    Cela va ?

  17. #17
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 483
    Par défaut
    Citation Envoyé par gifffftane Voir le message
    Bon, admettons.

    Donc, en résumé, dans le chapitre Performance Java on mettrait :

    1. Utilisez les StringBuilder
    2. Réfléchissez

    Cela va ?
    J'aurais plutot mis
    Réflechissez
    Lisez la javadoc

Discussions similaires

  1. Réponses: 0
    Dernier message: 23/10/2011, 11h45
  2. Réponses: 0
    Dernier message: 24/09/2011, 11h39
  3. Bonnes pratiques liées au cryptage
    Par hugo123 dans le forum Sécurité
    Réponses: 19
    Dernier message: 12/06/2008, 10h23

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo