Bonjour,
Merci pour les remarques. Avant de répondre, je vais commenter une contribution :
Citation:
"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.
Citation:
"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.
Citation:
"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.
Citation:
"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.
Citation:
"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.
Citation:
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.
Citation:
...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.
Citation:
"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.
Citation:
Il manque les parenthèses pour la méthode testValue.
NOté.
Citation:
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.
Citation:
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".
Citation:
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é.
Citation:
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.
Citation:
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.
Citation:
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.
Citation:
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.
Citation:
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.