Quand l'optimisation n'est-elle pas prématurée et donc pas diabolique?


75

"L'optimisation prématurée est la racine de tout mal" est quelque chose que nous avons presque tous entendu / lu. Ce que je suis curieux de savoir quel type d’optimisation n’est pas prématuré, c’est-à-dire à chaque étape du développement logiciel (conception de haut niveau, conception détaillée, implémentation de haut niveau, implémentation détaillée, etc.), quelle est l’ampleur de l’optimisation que nous pouvons envisager sans passer du côté obscur.



Réponses:


116

Quand vous vous basez sur l'expérience? Pas mal. "Chaque fois que nous avons utilisé X, nous avons subi un choc brutal en termes de performances. Prévoyez d'optimiser ou d'éviter X complètement cette fois-ci."

Quand c'est relativement indolore? Pas mal. "Implémenter ceci en tant que Foo ou Bar demandera tout autant de travail, mais en théorie, Bar devrait être beaucoup plus efficace. Barons-nous."

Lorsque vous évitez des algorithmes de merde qui vont terriblement évoluer? Pas mal. "Notre responsable technique indique que notre algorithme de sélection de chemin proposé fonctionne en temps factoriel; je ne suis pas sûr de ce que cela signifie, mais elle suggère que nous engagions le seppuku à le considérer même. Voyons autre chose."

Le mal vient de passer beaucoup de temps et d’énergie à résoudre des problèmes dont vous ignorez l’existence. Lorsque les problèmes existent vraiment ou lorsque les problèmes pseudo-fantômes peuvent être résolus à moindre coût, le mal disparaît.


Steve314 et Matthieu M. soulèvent des points dans les commentaires à prendre en compte. Fondamentalement, certaines variétés d’optimisations «indolores» ne sont tout simplement pas rentables, non plus parce que la mise à niveau de performances triviale qu’elles proposent ne vaut pas l’obscurcissement du code, elles dupliquent les améliorations déjà effectuées par le compilateur, ou les deux. Voir les commentaires pour de beaux exemples de non-améliorations trop ingénieuses.


22
Parfois, résoudre facilement un problème de fantôme est encore légèrement pervers, car il peut en résulter des difficultés de lecture et de maintenance du code. Pas beaucoup plus difficile (ou ce ne serait pas une solution facile), mais peut-être parfois toujours pertinent. Un exemple pourrait être une astuce astucieuse au niveau des bits que certaines personnes ne reconnaîtront pas, et que le compilateur appliquera probablement de toute façon si cela est utile.
Steve314

26
Je suis d'accord avec Steve ici, parfois "l'optimisation" ne vaut tout simplement pas la peine, surtout parce que les compilateurs sont vraiment bons. Exemple ? si iest non signé, i / 2peut être remplacé par i >> 1. C'est plus rapide. Mais c'est aussi plus cryptique (tout le monde ne verra pas l'effet, même ceux qui le font risquent de perdre du temps). Mais le pire, c'est que le compilateur le fera quand même, alors pourquoi masquer le code source;)?
Matthieu M.

19
@ Larry: Je n'ai pas, alors je suppose que c'est un bon exemple.
Joris Meys

18
À mon avis, les optimisations, même les plus simples, devraient également être considérées comme néfastes si elles ont un impact sur la lisibilité / la maintenance du code et ne sont pas basées sur des mesures de performances réelles.
Bart van Ingen Schenau

14
@ Matthew: Apprenez-leur quoi? Trucs sales et inutiles? Pourquoi? Si le profilage montre que a i/2est effectivement un point chaud et que (incroyable, mais supposons) i>>1accélère les choses, faites-le, et mettez un commentaire pour dire que ce profilage a montré que c'est plus rapide. Si cela est effectivement nécessaire quelque part (ce dont je doute, car, comme l'a dit Matthieu, les compilateurs devraient être assez intelligents pour le faire eux-mêmes), les novices apprendront quelque chose, si ce n'est pas le cas (ce qui est probable), pourquoi voulez-vous brancher leurs têtes avec un folklore inutile?
sbi

38

Le code de l'application ne doit être que de la meilleure qualité possible , mais le code de la bibliothèque doit l'être le plus possible, car vous ne savez jamais comment votre bibliothèque sera utilisée. Ainsi, lorsque vous écrivez du code de bibliothèque, il doit être bon dans tous les aspects, que ce soit les performances, la robustesse ou toute autre catégorie.

En outre, vous devez penser aux performances lorsque vous concevez votre application et choisissez des algorithmes . S'il n'est pas conçu pour être performant, aucun degré de piratage ne peut le rendre performant par la suite et aucune micro-optimisation ne l'emportera sur un algorithme supérieur.


5
Le code de la bibliothèque doit indiquer s'il essaie d'être "aussi bon que possible" ou quel est son objectif. Le code n'a pas besoin d'être absolument optimal pour être utile, à condition que les consommateurs ne l'utilisent que lorsque cela est approprié.
Supercat

1
Désolé, mais "soyez bon dans tous les aspects" ressemble étrangement à une ingénierie excessive. De plus, ce n'est probablement pas réaliste - la vie est toujours une affaire de compromis.
jeudi

1
+1 pour souligner la phase de conception; si vous pesez délibérément ses avantages, ce n'est pas prématuré.
Nathan Tuggy

Inversement, si vous ne savez jamais comment votre bibliothèque va être utilisée, vous ne savez pas si passer du temps à l’améliorer a une valeur commerciale. Donc, ce n'est guère un argument.
RemcoGerlich

25

quel type d'optimisation n'est pas prématuré

Ceux qui résultent de problèmes connus.


17

Quand l'optimisation n'est-elle pas prématurée et donc pas diabolique?

Il est difficile de dire ce qui est bien et ce qui est mal. Qui a ce droit? Si nous regardons la nature, il semble que nous sommes programmés pour la survie avec une définition large de "survie" qui inclut la transmission de nos gènes à la progéniture.

Je dirais donc, du moins en fonction de nos fonctions de base et de notre programmation, que l’optimisation n’est pas mauvaise quand elle s’aligne sur l’objectif de la reproduction. Pour les gars, il y a les blondes, les brunes, les rousses, beaucoup de belles. Pour les filles, il y a des mecs, et certains semblent aller bien.

Peut-être devrions-nous optimiser pour atteindre cet objectif, et il est utile d’utiliser un profileur. Le profileur vous permettra de hiérarchiser vos optimisations et votre temps plus efficacement en plus de vous donner des informations détaillées sur les points chauds et la raison de leur apparition. Cela vous donnera plus de temps libre consacré à la reproduction et à sa poursuite.


3
C'est rafraîchissant de voir quelqu'un apporter une nouvelle prise à cette vieille châtaigne. Il suffit de lire toute la citation de Knuth, et pas seulement une phrase, hein?
Robert Harvey

1
@RobertHarvey J'y ai un peu peur, car beaucoup semblent ne citer que cette phrase et que tant d'informations importantes sur le contexte finissent par être perdues au cours du processus. Je ne suis pas sûr que ce soit une si bonne réponse depuis que j'ai un peu peur. :-D

14

La citation complète définit quand l'optimisation n'est pas prématurée:

Un bon programmeur ne se laissera pas aller à la complaisance par un tel raisonnement, il sera sage de regarder attentivement le code critique; mais seulement après que ce code a été identifié . [c'est moi qui souligne]

Vous pouvez identifier le code critique de nombreuses manières: des structures de données critiques ou des algorithmes (par exemple, fortement utilisés ou "essentiels" du projet) peuvent donner des optimisations majeures, de nombreuses optimisations mineures sont identifiées par le biais de profileurs, etc.


6
Ouais ... C'est bien beau de gagner 90% de temps sur un appel de fonction aléatoire, mais vous auriez peut-être un impact plus important en examinant le code dans lequel votre application passe 80% de son temps et en économisant du temps. quelques pour cent là-bas.

11

Vous devez toujours choisir une solution "assez bonne" dans tous les cas, en fonction de vos expériences.

Le dicton de l'optimisation fait référence à l'écriture "de code plus complexe que" suffisamment bon pour le rendre plus rapide "avant de savoir qu'il est nécessaire, rendant ainsi le code plus complexe que nécessaire. La complexité est ce qui rend les choses difficiles, alors ce n'est pas une bonne chose.

Cela signifie que vous ne devez pas choisir un super complexe "qui peut trier des fichiers de 100 Go en effectuant un basculement transparent sur un disque" lorsqu'un tri simple suffit, mais vous devez également faire un bon choix pour le tri simple. Choisissez aveuglément Bubble Sort ou "choisissez toutes les entrées au hasard et voyez si elles sont en ordre. Répétez l'opération". est rarement bon.


3

Ma règle générale: si vous n'êtes pas sûr d'avoir besoin de l'optimisation, supposez que ce n'est pas le cas. Mais gardez cela à l'esprit lorsque vous avez besoin d'optimiser. Vous pouvez toutefois connaître certains problèmes à l’avance. Cela implique généralement de choisir de bons algorithmes et structures de données. Par exemple, si vous devez vérifier l'appartenance à une collection, vous pouvez être certain que vous aurez besoin d'un type de structure de données définie.


3

D'après mon expérience, à la phase de mise en œuvre détaillée, la réponse réside dans le profilage du code. Il est important de savoir ce qui doit être plus rapide et ce qui est acceptable rapidement.

Il est également important de savoir exactement où se situe le goulot d'étranglement des performances: optimiser une partie du code ne prenant que 5% du temps total d'exécution ne servirait à rien.

Les étapes 2 et 3 décrivent l’optimisation non prématurée:

  1. Fais-le fonctionner
  2. Tester. Pas assez rapide? Profilez-le .
  3. En utilisant les données de l'étape 2, optimisez les sections les plus lentes du code.

Vous avez oublié l'étape 0, à savoir: architecturez correctement l'application afin de pouvoir vous attendre à des performances raisonnables dès le départ.
Robert Harvey

Je parlais seulement de la phase de mise en œuvre détaillée.
Gorgi Kosev

1
Je remets en question l’étape 3 - très souvent, la meilleure solution consiste à définir une approche différente afin que vous ne fassiez pas le code le plus lent en premier lieu.
Loren Pechtel le

1
Choisissez les bonnes structures de données.
jasonk

3

Il ne s’agit pas d’optimisation lorsqu’il s’agit de choisir des éléments difficiles à modifier, par exemple: une plate-forme matérielle.

La sélection de structures de données est un bon exemple - essentielle pour répondre aux exigences fonctionnelles et non fonctionnelles (performances). Ce n'est pas facile à changer et pourtant cela pilotera tout le reste de votre application. Vos structures de données changent quels algorithmes sont disponibles etc.


3

Je ne connais qu'une façon de répondre à cette question, à savoir acquérir de l'expérience en matière de réglage des performances. Cela signifie - écrivez des programmes, et après les avoir écrits, trouvez-leur des accélérations et faites-le de manière itérative. Voici un exemple.

Voici l'erreur que la plupart des gens commettent: ils essaient d'optimiser le programme avant de l' exécuter. S'ils ont pris un cours de programmation , ils auront grand-O verres de couleur, et ils penseront (d'un professeur qui ne fait pas beaucoup d' expérience pratique) qui est ce qu'il est tout au sujet . C'est tout le même problème, l'optimisation préalable. **

Quelqu'un a dit: Commencez par faire les choses correctement, puis faites vite. Ils avaient raison.

Mais passons maintenant au kicker: si vous avez déjà fait cela à quelques reprises, vous reconnaissez les bêtises que vous avez commises précédemment qui causent des problèmes de vitesse, vous les évitez donc instinctivement. (Des choses comme rendre votre structure de classe trop lourde, être submergé de notifications, confondre taille des appels de fonction avec leur coût en temps, la liste s'allonge encore et encore ...) Vous les évitez instinctivement, mais devinez à quoi cela ressemble expérimenté: optimisation prématurée!

Donc, ces débats idiots continuent encore et encore :)

** Une autre chose qu'ils disent, c'est que vous n'avez plus à vous en soucier, car les compilateurs sont tellement bons et les machines sont si rapides de nos jours. (KIWI - Kill It With Iron.) Il n'y a pas d'accélération exponentielle du matériel ou du système (réalisée par des ingénieurs très intelligents et assidus) pouvant éventuellement compenser les ralentissements exponentiels des logiciels (effectuée par les programmeurs qui pensent de cette façon).


2

Lorsque les exigences ou le marché le demande spécifiquement.

Par exemple, les performances sont une exigence dans la plupart des applications financières car une faible latence est cruciale. Selon la nature de l'instrument commercialisé, l'optimisation peut aller de l'utilisation d'algorithmes non verrouillables dans un langage de haut niveau à l'utilisation d'un langage de bas niveau et même extrême: implémenter les algorithmes de correspondance d'ordre dans le matériel lui-même (avec FPGA par exemple). )

Un autre exemple serait certains types de périphériques intégrés. Prenons par exemple le frein ABS; Premièrement, il y a la sécurité, lorsque vous frappez la pause, la voiture devrait ralentir. Mais il y a aussi la performance, vous ne voudriez pas de retards quand vous frappez la pause.


0

La plupart des gens appellent l'optimisation prématurée, si vous optimisez quelque chose qui n'entraîne pas une "panne logicielle" (cela fonctionne mais reste inutile) du système en raison des performances.

Exemples du monde réel.

  • Si mon type de bulle prend 20 ms à exécuter, son optimisation à 1 ms quicksort n'améliorera pas l'utilité globale de manière significative, malgré une augmentation de performance de 2000%.

  • Si le chargement d’une page Web prend 20 secondes et que nous la diminuons à 1, l’utilité du site Web peut augmenter de 0 à pratiquement l’infini. Fondamentalement, quelque chose qui a été cassé parce que c'était trop lent, est maintenant utile.


Il est important de noter que si votre type s'appelle 1000 fois au cours de votre programme, l'optimisation de 20 ms à 1 ms est un gros problème.
Beefster

0

Quel type d'optimisation n'est pas prématuré?

Une optimisation qui résout un problème de performances connu avec votre application ou une optimisation qui permet à votre application de répondre à des critères d'acceptation bien définis.

Une fois identifié, il faut prendre un peu de temps pour établir le correctif et mesurer les avantages en termes de performances.

(c’est-à-dire que ce n’est pas - "Je pense que cette partie du code a l’air qu’elle pourrait être lente, je changerai X pour utiliser Y à la place et ce sera plus rapide").

J'ai rencontré beaucoup d'optimisations prématurées qui ont finalement rendu le code plus lent. Dans ce cas, j'entends prématuré comme signifiant "pas réfléchi". Les performances doivent être analysées avant et après l'optimisation et ne conserver que le code qui améliore réellement les performances.


0

"L'optimisation prématurée est la racine de tout mal" est quelque chose que nous avons presque tous entendu / lu

Vrai. Malheureusement, c’est aussi l’une des citations de programmation les plus (malicieusement) mal utilisées de tous les temps. Depuis que Donald Knuth a inventé le meme, il convient d’ajouter un contexte original tiré de la citation:

Nous devrions oublier les petites efficacités, disons environ 97% du temps: l'optimisation prématurée est la racine de tout mal. Pourtant, nous ne devrions pas laisser passer nos opportunités dans ces 3% critiques. ... Un bon programmeur ... aura intérêt à examiner attentivement le code critique; mais seulement après que ce code a été identifié. ... l'expérience universelle des programmeurs qui utilisent des outils de mesure est que leurs suppositions intuitives échouent

Notez que Knuth a parlé spécifiquement de la vitesse d'exécution en exécution .

Les programmeurs perdent énormément de temps à réfléchir à la vitesse des parties non critiques de leurs programmes ou à s'inquiéter de leur rapidité .

En outre, il a écrit l'article en 1974 à un moment où toutes les ressources de la machine où la corrélation privilégiée entre la vitesse d'exécution et la maintenabilité du programme (vitesse supérieure - sans maintenance) étaient probablement plus fortes que maintenant.

OK, pour répondre à votre question, selon Donald Knuth, l'optimisation n'est PAS prématurée si elle corrige un goulot d'étranglement des performances qui a été identifié (idéalement mesuré et identifié lors du profilage).

Comme je l'ai déjà dit, "l'optimisation prématurée" est l'un des mèmes les plus mal utilisés, donc answer ne sera pas complet sans quelques exemples de choses qui ne sont pas des optimisations prématurées mais qui sont parfois ignorées comme telles:

  • goulots d'étranglement visibles à l'œil nu et pouvant être évités avant d'être introduits, tels que O (N ^ 2) nombre d'allers-retours à la base de données avec un grand N où il existe une alternative O (1)

En outre, ne sont même pas liés à la vitesse d'exécution:

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.