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

  1. #1
    Expert éminent sénior


    Profil pro
    Inscrit en
    octobre 2003
    Messages
    7 856
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2003
    Messages : 7 856
    Points : 34 252
    Points
    34 252
    Par défaut Ecrire des programmes performants en Java - considérations générales
    Bonjour,

    Ibrahim MOUKOUOP NGUENA nous propose le premier volet d'une série d'articles sur l'écriture de programmes performants en Java :

    Cet article est le premier d'une série de trois articles consacrés à la performance des applications java.
    Il traite de considérations générales applicables au niveau de l'algorithmique et de la programmation.


    Vos avis et remarques sont les bienvenus.

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : mai 2004
    Messages : 1 252
    Points : 1 419
    Points
    1 419
    Par défaut
    Bonjour,


    Je comprends le besoin de cet article pour pas mal de développeurs qui ne se soucient pas trop de gérer les performances, mais qui ont des problèmes avec, mais cet article est, selon moi, trop succint et apporte des éléments réellement contreproductifs, tant pour l'efficacité que pour les performances.

    Je pense essentiellement au fait de prôner l'utilisation des StringBuffer tout au long de l'article, alors que dans 90% des cas, un StringBuilder est plus utile, même s'il en est fait mention... une seule fois. Le terme StringBuffer apparaît 17 fois et dans plusieurs sections, le terme StringBuilder... 3 fois dans une seule section.

    L'auteur parle en outre de la possibilité d'améliorer la vitesse d'exécution dans son item "IV-D-1-d", mais le fait d'utiliser un StringBuffer dans ce cas n'aide en rien la synchronisation dans un contexte multithread, contrairement à ce qu'il laisse penser quelques sections plus bas. Car les données internes du StringBuffer seront toujours consistantes en terme de méthode, mais certainement pas en terme d'utilisation globale de l'objet.

    De plus, tout placer à null n'est pas toujours utile afin de gagner en performance. L'auteur oublie le contexte de l'intérêt de mettre à null, notamment lors de méthodes courtes.

    Enfin, enfoncer le clou et vouloir "singletoniser" toute création d'objet est lui sujet à plus d'erreur. Tant qu'à choisir, je préfère avoir à gérer des performances plus faibles que me retrouver avec des problèmes de concurrence en permanence. Le coût de création d'un objet est toutefois généralement faible, même s'il n'est pas nul.

    Même si les trois quarts de ces règles sont davantage du bon sens qu'autre chose, je suis extrêmement perplexe vis-à-vis de cet article, et je crois que je vais m'en éloigner fissa.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    mars 2007
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2007
    Messages : 24
    Points : 39
    Points
    39
    Par défaut
    Pareil, je trouve que l'article propose des solutions qui vont à l'encontre d'une bonne conception.

    Dire qu'il faut toujours faire un constructeur par défaut, puis faire des set sur tous les champs, puis une méthode init est une mauvaise idée. A quoi sert de faire de l'objet dans ces conditions?
    Un constructeur sert avant tout à contraindre (et paradoxalement, pas à réserver en mémoire, car cela est fait par new).
    C'est à dire je veux forcer que pour créer une instance de Point, j'impose aux utilisateurs de ma classe de me donner une abcisse et une ordonnée.
    La méthode proposée, permet de faire un point sans argument, ce qui est sémantiquement faux.

    Par contre, il est tout à fait vrai qu'il faut au maximum minimiser le nombre d'instanciation, car c'est ce qui est le plus coûteux en temps. Mais il ne faut pas non plus sacrifier une bonne conception sur l'autel de la performance... (car la bonne conception aide à la maintenabilité).

    La partie sur l'Exception est très mal écrite. Si l'attribut badValue est un attribut de la classe, il est instancié lors du constructeur de l'objet qui contient la méthode testValue, ce qui est un peu à l'opposé de la philosophie de l'auteur. Il manque les parenthèses pour la méthode testValue.
    De plus, minimiser la création d'instance pour le cas des exceptions me paraît un peu dérisoire. Car en cas d'exception, il y a de grandes chance que le traitement s'arrête, et donc on est pas à la milliseconde près.

  4. #4
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    décembre 2006
    Messages
    10 061
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : décembre 2006
    Messages : 10 061
    Points : 15 771
    Points
    15 771
    Par défaut
    Petites remarques en vrac:

    Concernant la réutilisation des objets en les definissant comme variable d'instance :

    - Bonne pratique : Les variables d'instances d'une classe représentent soit une composition (= définissent une relation), soit un attribut (= définissent l'état). Ce n'est pas censé être l'équivalent du tas (heap) d'un programme C.

    - Implémentation : Attention car cette approche n'est pas thread-safe ! Si deux threads utilisent le meme objet, les modifications sur les valeurs de cet objet risquent de se télescoper.


    Concernant l'utilisation des StringBuffer :

    - Implémentation : Cette classe est thread-safe. Pour se faire, elle utilise la synchronisation Java sur toutes les methodes append(), ce qui est extrêmement couteux. Dans le cas d'une utilisation mono-thread (c'est généralement le cas), il est préférable d'utiliser la classe StringBuilder.
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2005
    Messages : 9
    Points : 13
    Points
    13
    Par défaut
    Hello,

    Mêmes remarques que les précédentes: la plupart de ces optimisations sont soit du bon sens, soit n'en sont pas vraiment. Le plus grave est qu'elles vont souvent à l'encontre d'une bonne conception.
    En particulier, ça fait belle lurette que les créations d'objets ne coûtent plus cher car la JVM sait réutiliser les instances comme il faut, et de fait les pools d'objets ont davantage tendance à baisser les performances qu'à les améliorer.
    Bref, cet article me fait plutôt penser à une pub pour son framework que de vrais conseils pertinents.

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    mai 2008
    Messages
    55
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations forums :
    Inscription : mai 2008
    Messages : 55
    Points : 50
    Points
    50
    Par défaut
    cet article me fait plutôt penser à une pub pour son framework que de vrais conseils pertinents.
    Pas sympa de dénigrer ainsi l'auteur qui a au moins pris le temps d'écrire cet article...

    Cela dit, je suis d'accord sur le fait qu'il faut revoir certaines choses.
    Je rajoute une couche à ce qui a été dit : dans les structures des données, je vois des objets comme Vector... aie.

    Mais pour un débutant comme moi je trouve qu'il y a quand même des choses intéressantes à savoir.

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    mars 2005
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mars 2005
    Messages : 9
    Points : 13
    Points
    13
    Par défaut
    Tu as raison, et je m'en excuse. Ecrire un tel article prend du temps, et j'apprécie qu'il l'ait fait pour la communauté. Ce que je voulais dire, c'est que je ne comprenais pas bien ce que venait faire son framework maison en début et en fin de l'article.

  8. #8
    Membre régulier
    Profil pro
    Développeur Java
    Inscrit en
    novembre 2008
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : novembre 2008
    Messages : 63
    Points : 106
    Points
    106
    Par défaut
    Moi de même je suis d'accord avec tout ce qui se dit.

    Un des mes livres de chevet du moment est "Effictive java" de Joshua Bloch, et concernant le fait de "nuller", il dit ce que certain ont déjà dit : la plupart du temps, c'est pas la peine de le faire. La jvm sait maintenant bien gérer tout celà, il faut lui faire confiance

    Concernant, IV-B
    "Recherches d'après une clé. Nécessité de connaître l'ordre d'entrée des éléments, mais pas de réorganisation de la structure."
    J'ai une question/remarque. Il me semble que le LinkedHashMap convient à ce genre de cas ? En tout cas, la javacdoc dit :"Hash table and linked list implementation of the Map interface, with predictable iteration order"

    Quant au "DoubleLinkedHashMap" après une recherche sur google, sauf erreur de ma part, il semble que ça n'existe pas ... Même chose pour "DoubleLinkedlist"

    Avec toutes ces critiques, j'espère voir une réaction de l'auteur, pour qu'ils nous explique le pourquoi de certains conseils qui nous laisse perplexe.

  9. #9
    Expert éminent sénior


    Profil pro
    Inscrit en
    octobre 2003
    Messages
    7 856
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : octobre 2003
    Messages : 7 856
    Points : 34 252
    Points
    34 252
    Par défaut
    Citation Envoyé par tomtomJ Voir le message
    Ce que je voulais dire, c'est que je ne comprenais pas bien ce que venait faire son framework maison en début et en fin de l'article.
    C'est bien suspicieux. Des auteurs de livre ont généreusement publié des articles sur Developpez.com et personne ne s'est offusqué de voir un morceaux de bio ou une référence à leur ouvrage

    Patience, l'objectif de ce sujet "à commentaires" est justement de mettre en relation les auteurs avec leurs lecteurs.

  10. #10
    NoP
    NoP est déconnecté
    Membre du Club
    Profil pro
    Inscrit en
    octobre 2005
    Messages
    35
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : octobre 2005
    Messages : 35
    Points : 44
    Points
    44
    Par défaut
    Cette "optimisation" me fait tiquer :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for(int i=0 ; i<n ; i++){
    	double y=2*i+4
    	//??
    }
    //Faire 
    double y;
    for(int i=0 ; i<n ; i++) {
    	y=2*i+4
    	//??
    }
    Je ne voit pas vraiment le gain. En quoi est couteux de déclarer une variable dans une boucle ? La variable ne sera pas déclaré n fois mais bien une seule fois quoiqu'il arrive. De plus, une bonne pratique java lu dans "Effective Java" (désolé j'ai pas le livre sous la main pour cité le numero du tip) dit exactement l'inverse : il faut réduire au maximum la portée de nos variables (pour des raisons de design, pas de perf).

    Cet article est une bonne idée mais il est à améliorer

  11. #11
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    décembre 2006
    Messages
    10 061
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : décembre 2006
    Messages : 10 061
    Points : 15 771
    Points
    15 771
    Par défaut
    Citation Envoyé par NoP Voir le message
    Je ne voit pas vraiment le gain.
    Il n'y en a pas Myth - Defining loop variables inside the loop is bad for performance
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  12. #12
    Membre régulier
    Profil pro
    Développeur Java
    Inscrit en
    novembre 2008
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : novembre 2008
    Messages : 63
    Points : 106
    Points
    106
    Par défaut
    A la section, IV-D-1-b
    je lis
    "Par exemple, si vous utilisez jbuilder et que vous voulez parcourir un dataset "

    Je ne vois pas du tout de quoi parle l'auteur :
    - d'ou vient cette classe (je ne la trouve pas dans la javadoc) ?
    - pourquoi parler de code par rapport à jbuilder ? Cette classe dataset est telle spécifique à du dev type plugin ou je ne sais quoi ? (je ne connais pas jbuilder)


    Concernant la partie sur les tris, j'aurais bien aimé un exemple où justement un tri alternatif est plus performant.

    Il aurait aussi été pratique d'avoir une petite partie sur les objets qui ne sont pas thread-safe pour y gagner en performance : StringBuilder, ArrayList, HashMap, ... vs StringBuffer, Vector, HashTable, ....

  13. #13
    Membre habitué

    Inscrit en
    janvier 2003
    Messages
    11
    Détails du profil
    Informations forums :
    Inscription : janvier 2003
    Messages : 11
    Points : 138
    Points
    138
    Par défaut
    Bonjour,

    Merci pour les remarques. Avant de répondre, je vais commenter une contribution :

    "mais cet article est, selon moi, trop succint et apporte des éléments réellement contreproductifs, tant pour l'efficacité que pour les performances.......
    Même si les trois quarts de ces règles sont davantage du bon sens qu'autre chose, je suis extrêmement perplexe vis-à-vis de cet article, et je crois que je vais m'en éloigner fissa."
    Il y a quelqu'un qui a dit qu'il y a deux types de personnes dans le monde. Les gagnants et les perdants. Les gagnants trouvent les solutions à tous les problèmes et les perdants des problèmes à toutes les solutions.
    Le meilleur moyen de réduire sa propre progression (et peut-être celle des autres), c'est de ne regarder les contributions des autres que sous l'angle de ce qui n'irait pas. C'est bien dommage.

    Je préfère les remarques techniques précises, qui ouvrent lieu à un débat scientifique. Ce qui semble relever du bon sens pour les uns peu être inconnu pour les autres (et même d'eux mêmes des fois). Revenons donc à la science.


    "Je pense essentiellement au fait de prôner l'utilisation des StringBuffer tout au long de l'article, alors que dans 90% des cas, un StringBuilder est plus utile, même s'il en est fait mention... une seule fois. Le terme StringBuffer apparaît 17 fois et dans plusieurs sections, le terme StringBuilder... 3 fois dans une seule section."
    Quand StringBuffer apparaîtrait 1000 fois, si l'article a précisé qu'il faut lui préferer StringBuilder dans certains contextes, où serait le problème? Le bon sens du lecteur pourrait justement lui permettre de comprendre dans quels contextes il faudrait remplacer les occurences de StringBuffer dans l'article par StringBuilder, le plus important étant la logique de concaténation efficace des chaînes de caractères en utilisant des buffers adaptés.

    "L'auteur parle en outre de la possibilité d'améliorer la vitesse d'exécution dans son item "IV-D-1-d", mais le fait d'utiliser un StringBuffer dans ce cas n'aide en rien la synchronisation dans un contexte multithread, contrairement à ce qu'il laisse penser quelques sections plus bas. Car les données internes du StringBuffer seront toujours consistantes en terme de méthode, mais certainement pas en terme d'utilisation globale de l'objet."
    Pour l'exemple du "IV-D-1-d", on doit effectivement être en monothread.
    A defaut il faudrait synchroniser toString() (ce qui ne garantit pas le gain de performances), ou utiliser un pool de StringBuffer à la place d'un seul StringBuffer (ce qui se justifierait s'il y a effectivement un très grand nombre d'appels à toString()). Je rappelle que j'ai d'abord dit que l'optimisation des performances n'est pas une fin en soi. En profiling pourrait avoir montré qu'on y perd du temps, ce qui justifierait cette optimisation.


    Ce que j'ai dit plus bas (V-J-3) est tout à fait correct et ThreadSafe dans l'implémenation. Voici de manière un peu plus détaillée ce qui se passe.

    Le StringBuffer n'est pas un attribut de l'objet, mais bien une variable non partagée, locale à une méthode.

    Chaque objet web contient d'autres objets web et des méthodes getCode avec plusieurs signatures différentes.

    L'appel externe par un processus web se fait sur une méthode getCode() qui n'a aucun paramètre. C'est dans cette méthode qu'est alors crée le StringBuffer comme variable locale de la méthode. Ensuite, il est passé comme paramètre pour les appels récursifs aux objets contenus dans l'objet principal.
    Ainsi, il n'y a aucune chance que deux processus distincts utilisent le même StringBuffer et que par conséquent les pages s'entremêlent.

    "De plus, tout placer à null n'est pas toujours utile afin de gagner en performance. L'auteur oublie le contexte de l'intérêt de mettre à null, notamment lors de méthodes courtes."
    Les questions importantes sont plutôt: Est ce souvent utile? Est ce que cela fait souvent perdre en performances? Je pense que les réponses sont oui et non. D'où l'intérêt de cette partie. Cela dit, si vous souhaitez apporter des précisions complémentaires, ce n'est pas mauvais.


    "Enfin, enfoncer le clou et vouloir "singletoniser" toute création d'objet est lui sujet à plus d'erreur. Tant qu'à choisir, je préfère avoir à gérer des performances plus faibles que me retrouver avec des problèmes de concurrence en permanence. Le coût de création d'un objet est toutefois généralement faible, même s'il n'est pas nul."
    C'est dommage que vous ayez oublié le préambule de l'article. Relisez le. La performance n'est pas une fin en soi, et il faut optimiser lorsque cela se justifie. Je n'ai jamais dit de "singletoniser" toute création d'objet. Mais lorsque cela se justifie il faut le faire. Dans plusieurs cas, le gain en performances vaudra vraiment la peine de faire l'effort de gérer la concurrence.

    Dire qu'il faut toujours faire un constructeur par défaut, puis faire des set sur tous les champs, puis une méthode init est une mauvaise idée. A quoi sert de faire de l'objet dans ces conditions?
    Un constructeur sert avant tout à contraindre (et paradoxalement, pas à réserver en mémoire, car cela est fait par new).
    C'est à dire je veux forcer que pour créer une instance de Point, j'impose aux utilisateurs de ma classe de me donner une abcisse et une ordonnée.
    La méthode proposée, permet de faire un point sans argument, ce qui est sémantiquement faux.
    Je ne crois pas avoir utilisé le terme "toujours". Néanmoins, l'utilisation des contructeurs vides est loin d'être une mauvaise idée du point de vue conceptuel. C'est même très pratique dans les composants (beans) et dans la possibilité de créer les objets sans utilisation explicite du constructeur new, ce qui est très utile pour la flexibilité du logiciel (voir l'inversion de contrôle). Il y a d'autres manières de contrôler la sémantique que par les arguments de constructeurs.

    ...Mais il ne faut pas non plus sacrifier une bonne conception sur l'autel de la performance... (car la bonne conception aide à la maintenabilité).
    Tout à fait d'accord (voir préambule article). Néanmoins ne pas utiliser new rend le logiel plus maintenable dans pas mal de cas.

    "La partie sur l'Exception est très mal écrite. Si l'attribut badValue est un attribut de la classe, il est instancié lors du constructeur de l'objet qui contient la méthode testValue, ce qui est un peu à l'opposé de la philosophie de l'auteur. "
    Voir préambule article. Je n'ai pas dit de ne jamais utiliser new.

    Il manque les parenthèses pour la méthode testValue.
    NOté.

    De plus, minimiser la création d'instance pour le cas des exceptions me paraît un peu dérisoire. Car en cas d'exception, il y a de grandes chance que le traitement s'arrête, et donc on est pas à la milliseconde près.
    Un programme bien écrit n'est pas censé être coupé par une exception. Un traitement oui. Mais dans un environnement serveur, il peut y avoir plusieurs exceptions provenant du grand nombre d'utilisateurs, d'où une grande création d'objets. Mais je rappelle encore qu'en préambule j'ai dit qu'il faut s'assurer que l'optimisation vaut la peine.


    En particulier, ça fait belle lurette que les créations d'objets ne coûtent plus cher car la JVM sait réutiliser les instances comme il faut, et de fait les pools d'objets ont davantage tendance à baisser les performances qu'à les améliorer.
    Ce serait bien d'essayer une telle idée avec des pools de connexion pour apprécier les capacités de la JVM. Cela dit, il se pourrait que dans certains cas la JMV s'en sorte bien, mais je voudrais savoir depuis quelle version, question juste de refaire certains de mes tests où j'ai du "venir au secours de la JVM".

    Concernant, IV-B
    "Recherches d'après une clé. Nécessité de connaître l'ordre d'entrée des éléments, mais pas de réorganisation de la structure."
    J'ai une question/remarque. Il me semble que le LinkedHashMap convient à ce genre de cas ? En tout cas, la javacdoc dit :"Hash table and linked list implementation of the Map interface, with predictable iteration order"
    Exact, c'est une implémentation par défaut de ce qui est proposé.

    Quant au "DoubleLinkedHashMap" après une recherche sur google, sauf erreur de ma part, il semble que ça n'existe pas ... Même chose pour "DoubleLinkedlist"
    Je l'avais trouvé dans un package pas du java standard (je vais essayer de retrouver). L'idée essentielle est de coupler une table de hashage (hashmap ou hashtable) à une liste doublement chainée.


    réduire au max la porté des variables pour le design
    Pourquoi pas? Performance pas une fin en soi. A chacun de definir ses priorités.

    A la section, IV-D-1-b
    je lis "Par exemple, si vous utilisez jbuilder et que vous voulez parcourir un dataset "

    Je ne vois pas du tout de quoi parle l'auteur :
    - d'ou vient cette classe (je ne la trouve pas dans la javadoc) ?
    - pourquoi parler de code par rapport à jbuilder ? Cette classe dataset est telle spécifique à du dev type plugin ou je ne sais quoi ? (je ne connais pas jbuilder)
    La remarque est specifique à Jbuilder.


    Concernant la partie sur les tris, j'aurais bien aimé un exemple où justement un tri alternatif est plus performant.
    Si on veut trier un ensemble d'individus d'après leur âge, si on veut trier les noeuds d'un graphe d'après le nombre de leurs voisins, un tri dénombrement (qui est un tri linéaire) peut êter bien plus performant qu'un tri fusion.

    Il aurait aussi été pratique d'avoir une petite partie sur les objets qui ne sont pas thread-safe pour y gagner en performance : StringBuilder, ArrayList, HashMap, ... vs StringBuffer, Vector, HashTable, ....
    Exact. A integrer dans une version corrigée de l'article.
    Mon Tutoriel java Écrire des programmes performants en java - N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  14. #14
    Rédacteur

    Profil pro
    Inscrit en
    juin 2003
    Messages
    4 184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : juin 2003
    Messages : 4 184
    Points : 4 977
    Points
    4 977
    Par défaut
    Salut,

    Je trouve également que l'article ne rentre pas dans les détails, il ressemble plus à une liste d'anti-patterns de développement java.

    Je constate aussi qu'il manque vraiment une partie de classes Thread-Safe et non thrad-safe, surtout que les exemples présentent plus souvent les classes non thread-safe.

    Pour la performance, on ne distingue pas les problèmes de fuites de mémoires des problèmes d'utilisation de CPU.

  15. #15
    Membre expérimenté
    Profil pro
    Inscrit en
    mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : mai 2004
    Messages : 1 252
    Points : 1 419
    Points
    1 419
    Par défaut
    Citation Envoyé par mongui Voir le message
    Quand StringBuffer apparaîtrait 1000 fois, si l'article a précisé qu'il faut lui préferer StringBuilder dans certains contextes, où serait le problème? Le bon sens du lecteur pourrait justement lui permettre de comprendre dans quels contextes il faudrait remplacer les occurences de StringBuffer dans l'article par StringBuilder, le plus important étant la logique de concaténation efficace des chaînes de caractères en utilisant des buffers adaptés.
    Je ne suis pas d'accord sur deux points.

    Le terme "certains contextes" devrait s'appliquer à StringBuffer et non à StringBuilder. StringBuilder devrait être la règle et StringBuffer l'exception ! Je cite la javadoc (de la classe StringBuffer) : "The StringBuilder class should generally be used in preference to this one, as it supports all of the same operations but it is faster, as it performs no synchronization."

    Ensuite, le lecteur lit les remarques et les assimile, mais souvent le lecteur oublie le détail et revient peu de temps après lire l'article, cherche la section qui l'intéresse et ne copie/colle que le code qui l'intéresse, sans particulièrement re-lire le reste de l'article. Dans ce contexte, le lecteur se fourvoiera et utilisera erronément un code qu'il pense performant, mais qui s'avérera contre-productif. Je parle d'expérience, tant personnelle que celle de collègues.

    Citation Envoyé par mongui Voir le message
    Ce serait bien d'essayer une telle idée avec des pools de connexion pour apprécier les capacités de la JVM. Cela dit, il se pourrait que dans certains cas la JMV s'en sorte bien, mais je voudrais savoir depuis quelle version, question juste de refaire certains de mes tests où j'ai du "venir au secours de la JVM".
    Si on parle de la JVM de Sun, depuis la JVM 1.5, la rapidité a été améliorée et encore avec la JVM 1.6.

    Si vous dites que vous proposez des astuces pour Java et que vous n'avez pas essayé celles-ci sur les JVM récentes, je suis stupéfait. Il est de notoriété que les performances depuis la JVM 1.5 se sont drastiquement améliorées par rapport aux versions 1.4 et antécédentes.

    Peut-être serait-ce un point à ajouter à votre document : "assurez-vous d'utiliser une JVM récente". Là, je suis à 100% d'accord, les performances seront bien meilleures.

    Enfin, en ce qui concerne la création d'objets à proprement parler, ne testez pas les connexions qui sont des cas à part : elles sont lourdes à la création, non pas parce qu'elles contiennent beaucoup d'objets et de traitement dans le constructeur, mais parce qu'elles ouvrent une connexion réseau. Et ça, c'est lourd, que l'on soit en Java, en C, en C++ ou n'importe. Tester les performances de la JVM sur les connection pools est complètement non-significatif. Les connexions sont créées au sein d'une connection pool, les autres objets s'instancient à la volée.

    Plus loin, vous parlez DoubleLinkedHashMap et des DoubleLinkedList qui n'existent effectivement pas. Ceci lié à ces non-tests sur des JVM récentes, vous me donnez l'impression (mais j'espère me tromper lourdement) d'avoir écrit des généralités et de ne pas les avoir testées.

    Je vais en rester là, et prendre ma référence en matière de performances.

  16. #16
    Membre régulier
    Profil pro
    Développeur Java
    Inscrit en
    novembre 2008
    Messages
    63
    Détails du profil
    Informations personnelles :
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : novembre 2008
    Messages : 63
    Points : 106
    Points
    106
    Par défaut
    C'est vrai qu'il est dommage d'avoir cité des classes hors jdk sans l'avoir précisé ni même référencé l'implémentation dont il est question.
    Une autre remarque est qu'il est vrai que certaines régles comme le singleton, le bean, nuller des variables, les pools .... s'emploient dans des cas bien précis. Il aurait été donc intéressant d'en préciser le contexte : le débutant va vouloir utiliser voir sur-utiliser certaines des règles décrites et s'en servir à mauvais escient.
    Et aussi, de bons conseils de performances s'appuie sur un exemple illustré :
    pour certains il aurait été intéressant d'avoir un exemple de code (bon et mauvais) avec son temps d'exécution. Le lecteur se rend mieux compte de l'intérêt de la bonne pratique.

    dingoth, je vois que le livre dont tu parles date quand même un peu, il reste assez valable ?

  17. #17
    Membre expérimenté
    Profil pro
    Inscrit en
    mai 2004
    Messages
    1 252
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : mai 2004
    Messages : 1 252
    Points : 1 419
    Points
    1 419
    Par défaut
    Ce livre contient des bonnes pratiques liées aux performances que l'on peut améliorer via le code. Il y a certes des recommandations obsolètes au vu des nouveautés proposées depuis dans le JDK, mais dans l'ensemble, ce livre apprend à réfléchir aux performances, plutôt que de donner des éléments plic-ploc et ne pas présenter au moins des arguments.

  18. #18
    Membre habitué
    Profil pro
    Inscrit en
    novembre 2006
    Messages
    156
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : novembre 2006
    Messages : 156
    Points : 187
    Points
    187
    Par défaut
    J'ai l'impression que l'auteur a récupéré un article d'il y a 8ans qu'il a vaguement mis au gout du jour.

  19. #19
    Membre confirmé
    Inscrit en
    mai 2007
    Messages
    334
    Détails du profil
    Informations forums :
    Inscription : mai 2007
    Messages : 334
    Points : 492
    Points
    492
    Par défaut
    Je trouve la partie "principale erreurs" bien écrite: il faut trouver un juste milieu entre performance et pragmatisme, et savoir quand rechercher l'optimisation.

    Donc j'attendais avec impatience les règles proposées, et malheureusement, comme dit précédemment certaines ressemblent à des anti-pattern:

    La gestion d'exception sans instanciation est tout simplement fausse: on ne peut pas accéder à une variable d'instance, donc potentiellement partagée entre plusieurs Thread, sans synchronisation. Ce problème ne se posant pas lorsqu'on crée l'exception.

    Vouloir économiser des objets à tout prix est une fausse bonne idée, et dans ce cas précis c'est utilisé à mauvais escient (un gain minime dans une gestion d'exception dont le cout est probablement supérieur)

    De plus sauf cas particulier on ne doit plus utiliser Hashtable, Vector, Stringbuffer, justement pour des raisons de performance puisque ces classes sont synchronisées (ce qui a un cout), donc à utiliser uniquement lors de partage de données en écriture entre Thread (cas particulier donc)

    En conclusion, je trouve l'article intéressant, mais les inexactitudes citées risquent d'induire en erreur faute de davantage de précision, et seraient à corriger AMHA.

    En fait, je pense que certaines considérations datent des problèmes antérieurs du Java, qui n'ont plus cours: problème de gestion mémoire, du garbage, du scope des variables (qui n'étaient pas optimisées par le ocmpilateur avant)

  20. #20
    Membre habitué
    Profil pro
    Inscrit en
    mars 2004
    Messages
    104
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : mars 2004
    Messages : 104
    Points : 135
    Points
    135
    Par défaut
    Il y a 2 ou 3 choses qui m'ont un peu troublé.

    Dans le paragraphe IV-D-1-g sur les collections, il est conseillé de vider les collections. On évite la création de tableaux mais cette opérations à un coût linéaire (O(n)) car on passe en revue chaque référence pour les mettre à null. Alors entre la création d'un tableau bien dimensionné et un parcours linéraire, mon coeur balance vu que le GC va faire le même boulot...

    Dans le paragraphe V-I, il est conseillé de faire des choses qu'on ne doit pas faire : les appels à System.gc() ou runtime.gc() doivent être proscrits car cela provoque un full GC très couteux en temps (cela peut freezer l'application suivant le nombre de processeurs). Le GC sait se débrouiller tout seul pour passer quand il le faut.
    Il vaut mieux configurer les zones mémoire de la JVM : agrandir l'eden space et les survivor spaces si on a beaucoup de création d'objets à courte durée de vie. Le GC fait le ménage dans ces zones très rapidement (qq ms). Explications du tuning

    J'ai pas trop compris le message du paragraphe IV-D-1-h. La classe StringTokenizer est maintenant déconseillée au profit de la méthode split() de String.

Discussions similaires

  1. editeur pour ecrire des programmes en cobol
    Par othman22222 dans le forum z/OS
    Réponses: 1
    Dernier message: 25/11/2012, 23h03
  2. ecrire des programme console avec VB6
    Par sofiane80 dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 19/06/2009, 11h52
  3. Ecrire des programmes compatibles DEP
    Par hardballer dans le forum Windows
    Réponses: 5
    Dernier message: 03/04/2007, 16h02

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