Un de mes collègues a engagé aujourd'hui une classe appelée ThreadLocalFormat
, qui a essentiellement déplacé des instances de classes au format Java dans un thread local, car elles ne sont pas thread-safe et sont "relativement coûteuses" à créer. J'ai écrit un test rapide et calculé que je pouvais créer 200 000 instances par seconde. Je lui ai demandé s'il en créait autant, ce à quoi il a répondu "loin de tout cela". C'est un excellent programmeur et tous les membres de l'équipe sont extrêmement compétents. Nous n'avons donc aucun problème à comprendre le code résultant, mais il s'agissait clairement d'optimiser là où il n'y a pas de réel besoin. Il a annulé le code à ma demande. Qu'est-ce que tu penses? S'agit-il d'une "optimisation prématurée" et quelle est sa gravité?
la source
Réponses:
Il est important de garder à l'esprit la citation complète:
Cela signifie qu'en l'absence de problèmes de performance mesurés, vous ne devez pas optimiser, car vous pensez obtenir un gain de performance. Il y a des optimisations évidentes (comme ne pas faire de concaténation de chaînes dans une boucle étroite), mais tout ce qui n'est pas une optimisation triviale doit être évité jusqu'à ce qu'il puisse être mesuré.
Le plus gros problème avec "l'optimisation prématurée" est qu'il peut introduire des bogues inattendus et peut être une perte de temps énorme.
la source
HashSet
plutôt queList
optimisée. Le cas d'utilisation en question était une collection initialisée de manière statique dont le seul but était de servir de table de recherche. Je ne pense pas que je me trompe en disant qu'il y a une différence dans la sélection du bon outil pour l'optimisation du travail par rapport à l'optimisation prématurée. Je pense que votre message confirme cette philosophie:There are obvious optimizations...anything that isn't trivially clear optimization should be avoided until it can be measured.
l’optimisation d’un HashSet a été minutieusement mesurée et documentée.Set
est aussi plus sémantiquement correct et informatif que ne l'estList
donc l'optimisation.Les micro- optimisations prématurées sont la racine de tout mal, car les micro-optimisations omettent le contexte. Ils ne se comportent presque jamais comme ils sont attendus.
Quelles sont les bonnes optimisations précoces dans l'ordre d'importance:
Quelques optimisations en milieu de développement:
Quelques optimisations de fin de cycle de développement
Toutes les optimisations initiales ne sont pas mauvaises, mais les micro-optimisations sont mauvaises si elles sont effectuées au mauvais moment du cycle de vie du développement , car elles peuvent affecter négativement l'architecture, peuvent affecter négativement la productivité initiale, peuvent nuire aux performances ou même avoir un effet néfaste à la fin. développement en raison de conditions environnementales différentes.
Si la performance est une préoccupation (et devrait toujours l'être), pensez toujours grand . La performance est une image plus grande et ne concerne pas des choses comme: devrais-je utiliser int ou long ? Choisissez Top Down lorsque vous travaillez avec des performances plutôt que de bas en haut .
la source
l'optimisation sans mesure préalable est presque toujours prématurée.
Je crois que c'est vrai dans ce cas, et vrai aussi dans le cas général.
la source
L'optimisation est "pervers" si
Dans votre cas, il semble qu’un peu de temps de programmation ait déjà été dépensé, le code n’était pas trop complexe (votre devin devrait pouvoir être compris par tout le monde de l’équipe), et le code est un peu plus fiable thread safe maintenant, si j'ai bien compris votre description). Cela ressemble à un peu mal. :)
la source
Je suis surpris que cette question ait 5 ans et pourtant, personne n'a écrit plus de ce que Knuth avait à dire que quelques phrases. Les quelques paragraphes entourant la célèbre citation l'expliquent assez bien. Le document cité s'appelle " Programmated Structured with go to Statements ". Bien qu'il existe depuis près de 40 ans, il traite d'un sujet controversé et d'un mouvement pour le logiciel qui n'existe plus, et contient des exemples dans des langages de programmation que beaucoup de gens n'ont jamais connus. entendu parler, une quantité étonnamment grande de ce qu'il dit est toujours valable.
Voici une citation plus grande (à partir de la page 8 du pdf, page 268 de l'original):
Un autre bon point de la page précédente:
la source
J'ai souvent vu cette citation utilisée pour justifier un code ou un code manifestement mauvais qui, même si ses performances n'ont pas été mesurées, pourrait probablement être rendu plus rapide, sans augmenter la taille du code ni en compromettre la lisibilité.
En général, je pense que les premières micro-optimisations peuvent être une mauvaise idée. Cependant, les macro-optimisations (telles que le choix d’un algorithme O (log N) au lieu de O (N ^ 2)) sont souvent utiles et devraient être effectuées tôt, car il peut être inutile d’écrire un algorithme O (N ^ 2) et puis le jeter complètement en faveur d'une approche O (log N).
Notez que les mots peuvent être : si l’algorithme O (N ^ 2) est simple et facile à écrire, vous pouvez le jeter plus tard sans trop de culpabilité s’il s’avère trop lent. Toutefois, si les deux algorithmes sont aussi complexes ou si la charge de travail attendue est si importante que vous savez déjà que vous aurez besoin du plus rapide, l'optimisation anticipée est une bonne décision d'ingénierie qui réduira à terme votre charge de travail totale.
Ainsi, en général, je pense que la bonne approche consiste à déterminer quelles sont vos options avant de commencer à écrire du code et à choisir consciemment le meilleur algorithme pour votre situation. Plus important encore, l'expression "l'optimisation prématurée est la racine de tout le mal" n'est pas une excuse pour l'ignorance. Les promoteurs de carrière devraient avoir une idée générale du coût des opérations courantes; ils devraient savoir, par exemple,
Et les développeurs doivent être familiarisés avec une boîte à outils de structures de données et d'algorithmes afin de pouvoir facilement utiliser les bons outils pour le travail.
Avoir beaucoup de connaissances et une boîte à outils personnelle vous permet d’optimiser presque sans effort. Il est diabolique de consacrer beaucoup d’efforts à une optimisation qui pourrait ne pas être inutile (et j’admets avoir été pris au piège plus d’une fois). Mais lorsque l'optimisation est aussi simple que de choisir un ensemble / hashtable au lieu d'un tableau ou de stocker une liste de nombres dans double [] au lieu de string [], pourquoi pas? Je ne suis peut-être pas d'accord avec Knuth mais je pense qu'il parlait de l'optimisation de bas niveau alors que je parle de l'optimisation de haut niveau.
N'oubliez pas que cette citation date de 1974. En 1974, les ordinateurs étaient lents et la puissance de calcul coûteuse, ce qui donnait à certains développeurs une tendance à l'optimisation excessive, ligne par ligne. Je pense que c'est ce que Knuth a poussé. Il ne disait pas "ne t'inquiète pas du tout pour la performance", car en 1974, ce ne serait que des paroles folles. Knuth expliquait comment optimiser; En bref, il convient de se concentrer uniquement sur les goulots d'étranglement et avant de le faire, vous devez effectuer des mesures pour trouver les goulots d'étranglement.
Notez que vous ne pouvez pas trouver les goulots d'étranglement avant d'avoir écrit un programme à mesurer, ce qui signifie que certaines décisions de performance doivent être prises avant que quoi que ce soit n'existe à mesurer. Parfois, ces décisions sont difficiles à changer si vous vous trompez. Pour cette raison, il est bon d’avoir une idée générale du coût de la chose afin de pouvoir prendre des décisions raisonnables en l’absence de données fiables.
L'optimisation et le degré d'inquiétude lié aux performances dépendent du travail à effectuer. Lorsque vous écrivez des scripts que vous n'exécuterez que quelques fois, vous soucier de la performance est généralement une perte de temps totale. Mais si vous travaillez pour Microsoft ou Oracle et que vous travaillez sur une bibliothèque que des milliers d'autres développeurs vont utiliser de mille façons différentes, il peut être rentable de l'optimiser, de façon à pouvoir couvrir tous les aspects divers. utiliser les cas efficacement. Même dans ce cas, le besoin de performance doit toujours être mis en balance avec le besoin de lisibilité, de maintenabilité, d’élégance, d’extensibilité, etc.
la source
Personnellement, comme indiqué dans un précédent fil , je ne pense pas que l'optimisation précoce soit mauvaise dans les situations où vous savez que vous rencontrerez des problèmes de performances. Par exemple, j'écris des logiciels de modélisation et d'analyse de surface, où je traite régulièrement avec des dizaines de millions d'entités. Planifier pour une performance optimale au stade de la conception est de loin supérieur à l'optimisation tardive d'une conception faible.
Une autre chose à considérer est la manière dont votre application évoluera dans le futur. Si vous considérez que votre code aura une longue durée de vie, optimiser les performances au stade de la conception est également une bonne idée.
D'après mon expérience, l'optimisation tardive fournit de maigres récompenses à un prix élevé. L’optimisation au stade de la conception, grâce à la sélection d’algorithmes et à l’ajustement, est bien meilleure. Le fait de savoir comment fonctionne votre code n’est pas un excellent moyen d’obtenir un code hautes performances, vous devez le savoir au préalable.
la source
En fait, j'ai appris que la non-optimisation prématurée est le plus souvent la racine de tout mal.
Lorsque des personnes écrivent un logiciel, il rencontrera d’abord des problèmes tels que l’instabilité, des fonctionnalités limitées, une mauvaise utilisation et des performances médiocres. Tous ces problèmes sont généralement corrigés lorsque le logiciel arrive à maturité.
Tous, sauf la performance. Personne ne semble se soucier de la performance. La raison est simple: si un logiciel tombe en panne, quelqu'un le corrigera et c'est tout, si une fonctionnalité est manquante, quelqu'un l'implémentera et le fera. Si le logiciel présente des performances médiocres, ce n'est souvent pas à cause d'une microoptimisation manquante. en raison de la mauvaise conception et personne ne va toucher à la conception du logiciel. DÉJÀ.
Regardez Bochs. C'est lent comme l'enfer. Cela ira-t-il un jour plus vite? Peut-être, mais seulement de l'ordre de quelques pour cent. Ses performances ne seront jamais comparables à celles d’un logiciel de virtualisation tel que VMWare, VBox ou même QEMU. Parce que c'est lent par conception!
Si le problème d'un logiciel est qu'il est lent, c'est parce qu'il est TRÈS lent et que cela ne peut être corrigé qu'en améliorant les performances d'une multitude. + 10% ne feront tout simplement pas un logiciel lent rapidement. Et vous n'obtiendrez généralement pas plus de 10% avec les optimisations ultérieures.
Donc, si les performances sont TOUTES importantes pour votre logiciel, vous devez en tenir compte dès le début, lors de la conception, au lieu de penser "ah oui, c'est lent, mais nous pouvons améliorer cela plus tard". Parce que tu ne peux pas!
Je sais que cela ne correspond pas vraiment à votre cas particulier, mais cela répond à la question générale "L'optimisation prématurée est-elle vraiment la racine de tout le mal?" - avec un NON clair.
Toute optimisation, comme toute fonctionnalité, etc. doit être soigneusement conçue et implémentée avec soin. Et cela inclut une évaluation appropriée des coûts et des avantages. N'optimisez pas un algorithme pour économiser quelques cycles ici et là, s'il ne crée pas un gain de performance mesurable.
À titre d’exemple, vous pouvez améliorer les performances d’une fonction en l’alignant, en économisant éventuellement quelques cycles, mais en même temps, vous augmentez probablement la taille de votre exécutable, ce qui augmente les risques de défaillances de TLB et de cache coûtant des milliers de cycles voire opérations de pagination, qui vont tuer complètement les performances. Si vous ne comprenez pas ces choses, votre "optimisation" peut s'avérer mauvaise.
Une optimisation stupide est plus diabolique qu'une optimisation "prématurée", mais les deux sont toujours mieux que la non optimisation prématurée.
la source
PO pose deux problèmes: premièrement, le temps de développement utilisé pour un travail non essentiel pouvant être utilisé pour écrire plus de fonctionnalités ou pour corriger plus de bugs, et deuxièmement, le faux sentiment de sécurité selon lequel le code est exécuté efficacement. Le bon de commande implique souvent l'optimisation d'un code qui ne sera pas le goulot d'étranglement tout en ne remarquant pas le code qui le fera. Le bit "prématuré" signifie que l'optimisation est effectuée avant qu'un problème ne soit identifié à l'aide de mesures appropriées.
Donc, en gros, oui, cela ressemble à une optimisation prématurée, mais je ne la soutiendrais pas nécessairement sauf si cela introduisait des bogues - après tout, cela a été optimisé maintenant (!)
la source
Je crois que c'est ce que Mike Cohn appelle le code «plaqué or»: c’est-à-dire passer du temps sur des tâches qui pourraient être intéressantes mais qui ne sont pas nécessaires.
Il a déconseillé.
Le «placage d’or» du PS pourrait être une fonctionnalité très spécifique. Lorsque vous examinez le code, il prend la forme d'une optimisation inutile, de classes "évolutives", etc.
la source
Comme il n’ya aucun problème à comprendre le code, ce cas peut être considéré comme une exception.
Mais en général, l'optimisation conduit à un code moins lisible et moins compréhensible et ne devrait être appliquée que lorsque cela est nécessaire. Un exemple simple - si vous savez que vous ne devez trier que quelques éléments - utilisez BubbleSort. Mais si vous pensez que les éléments pourraient augmenter et que vous ne savez pas dans quelle mesure, optimiser avec QuickSort (par exemple) n’est pas un mal, mais un must. Et cela devrait être pris en compte lors de la conception du programme.
la source
J'ai constaté que le problème de l'optimisation prématurée se produit généralement lorsque la réécriture du code existant est plus rapide. Je peux voir à quel point l'écriture d'une optimisation compliquée pourrait poser problème, mais la plupart du temps, je vois une optimisation prématurée s'élever pour réparer ce qui n'est pas (connu pour être) brisé.
Et le pire exemple est lorsque je vois quelqu'un réimplémenter des fonctionnalités à partir d'une bibliothèque standard. C'est un drapeau rouge majeur. Par exemple, j'ai déjà vu quelqu'un implémenter des routines personnalisées pour la manipulation de chaînes, car il craignait que les commandes intégrées ne soient trop lentes.
Il en résulte un code plus difficile à comprendre (mauvais) et une perte de temps considérable sur un travail qui n’est probablement pas utile (mauvais).
la source
D'un point de vue différent, mon expérience montre que la plupart des programmeurs / développeurs ne prévoient pas le succès et que le "prototype" devient presque toujours la version 1.0. J'ai une expérience directe de 4 produits originaux distincts dans lesquels une interface frontale élégante, sexy et très fonctionnelle (essentiellement l'interface utilisateur) a entraîné une adoption et un enthousiasme généralisés des utilisateurs. Dans chacun de ces produits, des problèmes de performances ont commencé à apparaître dans des délais relativement courts (1 à 2 ans), en particulier à mesure que des clients plus importants et plus exigeants commençaient à adopter le produit. Très vite, les performances ont dominé la liste des problèmes, bien que le développement de nouvelles fonctionnalités ait dominé la liste des priorités de la direction. Les clients devenaient de plus en plus frustrés à mesure que chaque version ajoutait de nouvelles fonctionnalités qui semblaient géniales mais étaient presque inaccessibles en raison de problèmes de performances.
Ainsi, des défauts de conception et de mise en œuvre très fondamentaux, peu ou pas préoccupants dans le "type prototype", sont devenus des obstacles majeurs au succès à long terme des produits (et des entreprises).
Votre démo client peut sembler très performante sur votre ordinateur portable avec des DOM XML, SQL Express et de nombreuses données en cache côté client. Le système de production plantera probablement une brûlure si vous réussissez.
En 1976, nous débattions encore sur les moyens optimaux de calculer une racine carrée ou de trier un grand nombre. L'adage de Don Knuth disait qu'il fallait se concentrer sur l'optimisation de ce type de routine de bas niveau au début du processus de conception plutôt que sur la résolution du problème. puis en optimisant les régions de code localisées.
Quand on répète l'adage comme une excuse pour ne pas écrire de code efficace (C ++, VB, T-SQL ou autre), ou pour ne pas concevoir correctement le magasin de données, ou pour ne pas prendre en compte l'architecture de travail réseau, alors IMO montre simplement une compréhension très superficielle de la nature réelle de notre travail. Rayon
la source
Je suppose que cela dépend de la façon dont vous définissez le terme "prématuré". Rendre la fonctionnalité de bas niveau rapide lorsque vous écrivez n'est pas fondamentalement mauvais. Je pense que c'est un malentendu de la citation. Parfois, je pense que cette citation pourrait faire avec plus de qualification. Je ferais cependant écho aux commentaires de m_pGladiator sur la lisibilité.
la source
La réponse est: ça dépend. Je soutiens que l'efficacité est un gros problème pour certains types de travail, tels que les requêtes de base de données complexes. Dans de nombreux autres cas, l'ordinateur passe le plus clair de son temps à attendre l'entrée de l'utilisateur. L'optimisation de la plupart des codes est au mieux une perte de temps et au pire une contre-production.
Dans certains cas, vous pouvez concevoir en fonction de l'efficacité ou de la performance (perçue ou réelle) - en sélectionnant un algorithme approprié ou en concevant une interface utilisateur afin que certaines opérations coûteuses soient effectuées en arrière-plan, par exemple. Dans de nombreux cas, le profilage ou d'autres opérations visant à déterminer les points chauds vous procurent un avantage de 10/90.
Un exemple de ceci que je peux décrire est le modèle de données que j'ai déjà utilisé pour un système de gestion d'instance comprenant environ 560 tables. Tout a commencé normalisé («magnifiquement normalisé» comme le dit le consultant d'une certaine entreprise big-5) et nous n'avons eu à y insérer que quatre données dénormalisées:
Une vue matérialisée pour supporter un écran de recherche
Une table maintenue par déclencheur pour prendre en charge un autre écran de recherche qui ne pouvait pas être créé avec une vue matérialisée.
Une table de rapport dénormalisée (cela n'existait que parce que nous devions traiter certains rapports de débit lorsqu'un projet d'entrepôt de données était mis en attente)
Une table maintenue par déclencheur pour une interface qui devait rechercher le plus récent parmi un assez grand nombre d'événements disparates dans le système.
C’était (à l’époque) le plus grand projet J2EE en Australasie - bien plus de 100 ans de temps de développement - et il y avait 4 éléments dénormalisés dans le schéma de base de données, dont un n’y appartenait pas vraiment.
la source
L'optimisation prématurée n'est pas la racine de TOUS les maux, c'est certain. Il y a cependant des inconvénients:
Au lieu d'une optimisation prématurée, on pourrait effectuer des tests de visibilité précoces afin de déterminer s'il était réellement nécessaire d'améliorer encore l'optimisation.
la source
La plupart de ceux qui adhèrent à "PMO" (la citation partielle, par exemple) disent que les optimisations doivent être basées sur des mesures et que celles-ci ne peuvent être effectuées qu'à la toute fin.
D'après mon expérience acquise dans le développement de grands systèmes, les tests de performance sont effectués à la toute fin, alors que le développement est presque terminé.
Si nous suivions les "conseils" de ces personnes, tous les systèmes seraient extrêmement lents. Ils seraient également coûteux, car leurs besoins en matériel sont beaucoup plus importants que prévu à l’origine.
Je préconise depuis longtemps de faire des tests de performance à intervalles réguliers dans le processus de développement: cela indiquera à la fois la présence d'un nouveau code (là où il n'y en avait pas auparavant) et l'état du code existant.
Une autre idée favorite consiste à instrumenter un logiciel au niveau du bloc fonctionnel. Lors de son exécution, le système recueille des informations sur les temps d'exécution des blocs de fonction. Lorsqu’une mise à niveau du système est effectuée, il est possible de déterminer les blocs de fonction exécutés comme dans la version précédente et ceux qui se sont détériorés. Sur l'écran d'un logiciel, les données de performance sont accessibles à partir du menu d'aide.
Découvrez cet excellent article sur ce que le cabinet du premier ministre pourrait ou non vouloir dire.
la source