web-dev-qa-db-fra.com

La micro-optimisation est-elle importante lors du codage?

J'ai récemment posé une question sur Stack Overflow pour savoir pourquoi isset () était plus rapide que strlen () in PHP . Cela a soulevé des questions quant à l'importance du code lisible et si les améliorations de performances des micro-secondes dans le code valaient même la peine d'être considérées.

Mon père est un programmeur à la retraite et je lui ai montré les réponses. Il était absolument certain que si un codeur ne considère pas les performances de son code même au niveau micro, il n'est pas un bon programmeur.

Je n'en suis pas si sûr - peut-être que l'augmentation de la puissance de calcul signifie que nous n'avons plus à envisager ce type d'améliorations des micro-performances? Peut-être que ce genre de réflexion appartient aux personnes qui écrivent le code de langue réel? (de PHP dans le cas ci-dessus).

Les facteurs environnementaux pourraient être importants - Internet consomme 10% de l'énergie mondiale. Je me demande à quel point quelques micro-secondes de code sont inutiles lorsqu'elles sont répliquées des milliards de fois sur des millions de sites Web?

J'aimerais connaître les réponses de préférence en fonction de faits concernant la programmation.

La micro-optimisation est-elle importante lors du codage?

Mon résumé personnel de 25 réponses, merci à tous.

Parfois, nous devons vraiment nous inquiéter des micro-optimisations, mais seulement dans de très rares circonstances. La fiabilité et la lisibilité sont beaucoup plus importantes dans la majorité des cas. Cependant, considérer la micro-optimisation de temps en temps ne fait pas de mal. Une compréhension de base peut nous aider à ne pas faire de mauvais choix évidents lors du codage, comme

if (expensiveFunction() || counter < X)

Devrait être

if (counter < X || expensiveFunction())

( Exemple de @ zidarsk8 ) Cela pourrait être une fonction peu coûteuse et donc changer le code serait une micro-optimisation. Mais, avec une compréhension de base, vous n'auriez pas à le faire, car vous l'écririez correctement en premier lieu.

181
Boz

Je suis à la fois d'accord et en désaccord avec votre père. Les performances doivent être envisagées tôt, mais la micro-optimisation ne doit être envisagée tôt que si vous savez qu'un pourcentage élevé de temps sera consacré aux petites Sections de code liées au processeur.

Le problème de la micro-optimisation est qu'elle se fait généralement sans avoir la moindre idée de la façon dont les programmes passent réellement plus de temps que nécessaire.

Cette connaissance provient de l'expérience de l'optimisation des performances, comme dans cet exemple , dans lequel un programme apparemment simple, sans inefficacités évidentes, passe par une série d'étapes de diagnostic et d'accélération, jusqu'à ce qu'il soit 43 fois plus rapide qu'au début.

Ce que cela montre, c'est que vous ne pouvez pas vraiment deviner ou comprendre où seront les problèmes. Si vous effectuez un diagnostic, qui dans mon cas est pause aléatoire , les lignes de code responsables d'une fraction significative du temps sont préférentiellement exposées. Si vous les regardez, vous pouvez trouver du code de remplacement, et ainsi réduire le temps global d'environ cette fraction.

D'autres choses que vous n'avez pas corrigées prennent toujours autant de temps qu'auparavant, mais comme le temps global a été réduit, ces choses prennent maintenant une fraction plus importante, donc si vous recommencez, cette fraction peut également être éliminée. Si vous continuez à le faire sur plusieurs itérations, c'est ainsi que vous pouvez obtenir des accélérations massives , sans jamais nécessairement avoir fait de micro-optimisation .

Après ce type d'expérience, lorsque vous abordez de nouveaux problèmes de programmation, vous en venez à reconnaître les approches de conception qui conduisent initialement à de telles inefficacités. D'après mon expérience, cela vient d'une conception excessive de la structure des données, d'une structure de données non normalisée, d'une dépendance massive aux notifications, ce genre de choses.

90
Mike Dunlavey

La micro-optimisation n'est importante que si les chiffres le disent.

Les exigences que vous développez doivent avoir certaines spécifications de données de performances, si les performances sont un problème pour le client ou l'utilisateur. Lorsque vous développez un logiciel, vous devez tester les performances de votre système par rapport à ces exigences. Si vous ne répondez pas aux exigences de performances, vous devez profiler votre base de code et optimiser au besoin pour atteindre les exigences de performances. Une fois que vous êtes dans les performances minimales requises, il n'est plus nécessaire de comprimer les performances du système, surtout si vous allez compromettre la lisibilité et la maintenabilité du code (selon mon expérience, le code hautement optimisé est moins lisible et maintenable, mais pas toujours). Si vous pouvez obtenir des gains de performances supplémentaires sans dégrader les autres attributs de qualité du système, vous pouvez le considérer.

Il existe cependant des cas où les performances sont de la plus haute importance. Je pense principalement aux systèmes temps réel et aux systèmes embarqués. Dans les systèmes en temps réel, le changement de l'ordre des opérations peut avoir un effet énorme sur le respect des délais fermes qui sont nécessaires pour un bon fonctionnement, peut-être même influencer les résultats des calculs. Dans les systèmes intégrés, la mémoire, la puissance du processeur et la puissance (comme dans la batterie) sont généralement limitées, vous devez donc réduire la taille de vos fichiers binaires et le nombre de calculs pour maximiser la durée de vie du système.

120
Thomas Owens

Chaque fois que quelqu'un pose des questions sur l'optimisation , je me souviens de la citation de Michael A. Jackson

La première règle d'optimisation de programme: Ne le faites pas.

La deuxième règle de l'optimisation des programmes (pour les experts seulement!): Ne le faites pas encore.

Citation de Wikipedia corrigée pour l'anglais britannique. * 8 ')

Implicite dans la deuxième règle est de profil votre code et de ne passer que du temps optimiser les choses qui feront la différence.

Lors de la programmation dans Assembly, l'affirmation de votre père était correcte. Mais c'est beaucoup plus proche du métal que la plupart des gens ne le programme de nos jours. Aujourd'hui, même essayer pour vous optimiser (sans profilage) peut entraîner l'exécution de votre code plus lentement que si vous aviez fait quelque chose de la manière la plus courante, car le le moyen commun est plus susceptible d'être optimisé par les compilateurs modernes JIT .

Même en C, vous devez être assez bon en optimisation pour en savoir plus sur l'optimisation d'une section de code que le compilateur.

Si vous ne connaissez pas beaucoup de ce dont Ulrich Drepper parle dans son excellent article Ce que chaque programmeur devrait savoir sur la mémoire, alors vous êtes probablement sur un perdant même essayer de vous optimiser. Contrairement au titre des articles (qui est en fait un hommage à David Goldberg Ce que tout informaticien devrait savoir sur l'arithmétique à virgule flottante) n'ayant pas ce niveau de la compréhension ne vous empêche pas nécessairement d'être un bon programmeur, juste un type de programmeur différent.

isset() vs strlen() dans PHP

Je ne connais pas PHP, donc ce n'est vraiment pas évident ce que isset() est censé faire. Je peux le déduire du contexte, mais cela signifie qu'il sera tout aussi obscur pour les programmeurs novices PHP et pourrait même amener les programmeurs plus expérimentés à prendre deux fois. C'est le genre de idiomatique utilisation d'une langue qui peut faire de l'entretien un cauchemar.

Non seulement cela, mais il n'y a aucune garantie que isset() sera toujours plus efficace, juste parce qu'il est plus efficace maintenant. Une optimisation n'est peut-être plus une optimisation l'année prochaine ou dans 10 ans. Les processeurs, les systèmes et les compilateurs s'améliorent et changent avec le temps. Si les performances de la strlen() de PHP sont un problème, PHP pourrait être modifié à l'avenir, alors toutes les optimisations isset () devront peut-être être supprimées pour optimiser le code une fois de plus.

Chaque optimisation a le potentiel de devenir un futur anti-optimisation, devrait donc être considéré comme une odeur de code possible, à garder au minimum.

Un exemple d'expérience personnelle

Comme exemple d'un tel anti-optimisation, j'ai dû une fois désinfecter une énorme base de code remplie de code de la forme if x==0 z=0 else z=x*y parce que quelqu'un avait fait l'hypothèse qu'une multiplication en virgule flottante était toujours allait être plus cher qu'une branche. Sur l'architecture cible d'origine, cette optimisation a accéléré l'exécution du code, mais les temps changent.

Lorsque nous avons essayé d'utiliser ce code sur un processeur plus moderne qui était hautement pipeline, les performances étaient horriblement mauvaises - chacune de ces déclarations provoque un vidage du pipeline. Simplifier toutes ces lignes de code pour simplement z=x*y a accéléré l'exécution du programme sur la nouvelle architecture, rétablissant les performances perdues par l'anti-optimisation .

Les problèmes que nous devons généralement optimiser aujourd'hui sont très différents de ceux que nous avons dû optimiser il y a 20 ou même 10 ans.

Ensuite, nous nous inquiétions de faire le plus de travail par cycle d'horloge, maintenant nous sommes plus susceptibles de nous inquiéter des vidages de pipeline, des erreurs de prédiction de branche et des échecs de cache au niveau du processeur, mais les verrous et la communication interprocessus deviennent beaucoup = plus important à mesure que nous évoluons vers des architectures multi-processus et multi-processeurs. article de Drepper peut vraiment aider à comprendre bon nombre de ces problèmes.

103
Mark Booth
  1. Écrivez du code, propre, concis, simple et explicite.
  2. Effectuez des tests de performances pour identifier les goulots d'étranglement.
  3. Optimiser les sections critiques.

En règle générale: 95% de votre code est exécuté 5% du temps. Il ne sert à rien d'optimiser avant de profiler/comparer votre code et de voir quels sont les 5% qui sont exécutés 95% du temps.

Chaque idiot peut faire de la micro-optimisation et tout compilateur/runtime décent le fera pour vous.
L'optimisation d'un bon code est triviale. Écrire du code optimisé et essayer de le rendre bon après cela est au mieux fastidieux et au pire insoutenable.

Si vous sérieusement vous souciez des performances, n'utilisez pas PHP pour le code critique pour les performances. Trouvez les goulots d'étranglement et réécrivez-les avec des extensions C. Même la micro-optimisation de votre code PHP au-delà du point d'obscurcissement ne vous permettra pas d'obtenir autant de vitesse.

Personnellement, j'ai beaucoup aimé faire de la micro-optimisation lorsque j'ai commencé à programmer. Parce que c'est évident. Parce que cela vous récompense rapidement. Parce que vous n'avez pas à prendre de décisions importantes. C'est le parfait moyen de procrastination. Il vous permet de fuir les parties vraiment importantes du développement logiciel: la conception de systèmes évolutifs, flexibles, extensibles et robustes.

84
back2dos

Je serais d'accord avec votre père: "Si un codeur ne considère pas les performances dans son code même au niveau micro, ce ne sont pas de bons programmeurs." La clé est de "considérer les performances". Ce n'est pas équivalent à "faire des micro-optimisations à chaque étape".

Je suis d'accord avec la plupart des autres commentaires - ce qui rendait les programmes C plus rapides peut ne pas le faire aujourd'hui - mais il y a d'autres choses sérieuses à considérer: devrais-je utiliser C ou C++? Les classes avec de simples opérateurs surchargés peuvent réduire les performances si vous les utilisez beaucoup. Est-ce important? Cela dépend de votre application, mais si vous n'y réfléchissez même pas, vous n'êtes pas un très bon programmeur. Certaines personnes pourraient le considérer pendant environ 2 millisecondes et le rejeter, mais je pense que beaucoup trop de gens ne le considèrent même pas.

La réalité est qu'avec l'optimisation, le code peut devenir plus difficile à lire. Le code prendra plus de temps à écrire. Le code sera quelque part entre un peu plus rapide et un ordre de grandeur plus rapide (c'est rare). Vos clients ne connaîtront probablement pas la différence.

Une autre réalité est que les gens aiment réutiliser le code, et où il finit peut être très différent de celui où vous l'avez écrit. Tout à coup, les gens peuvent s'en soucier.

Par exemple, disons que vous avez écrit quelque chose comme Angry Birds sur un PC ou pour une console de jeu. Vous avez ignoré l'optimisation de votre système physique et de votre système graphique - car les doubles cœurs à 2,5 GHz sont fondamentalement les minimums de nos jours, et votre jeu fonctionne assez bien. Ensuite, les téléphones intelligents arrivent et vous voulez le porter. Oh zut, un bras de 600 MHz core?

Pensez à un site Web - quelque chose jeté ensemble pendant un week-end comme chaud ou pas. Vous utilisez la base de données à portée de main, écrivez tout avec un développement rapide à l'esprit, lancez en envoyant une URL à vos amis. Trois mois plus tard, votre serveur meurt de surcharge et vous ne pouvez rien faire pour évoluer. Cela arrive tout le temps. Les plus grands sites Web ont des factures d'électricité mesurées en centaines de kilowatts ou même en mégawatts. Pensez-y, il y a des mégawatts à économiser grâce à l'optimisation du code.

Comme votre père l'a dit, vous devez au moins le considérer . La plupart des gens ne savent même pas combien de performances sont sur la table et les ignorer avec une brève explication sur "l'optimisation prématurée" et "ne le faites pas". Ce ne sont pas de bons programmeurs.

Ce n'est pas une opinion populaire sur ces sites. Bye bye points de réputation ....

27
phkahler

Prenons d'abord votre cas: PHP

  • Je ne pense pas que PHP est une sorte de langage (à la fois en raison de sa nature et de son domaine d'application principal) que vous devez vous soucier de ces "micro-optimisations". PHP est principalement optimisé avec la mise en cache d'opcode.
  • Les programmes écrits en PHP ne sont pas liés au CPU, ils sont principalement I/O liés, donc ces optimisations ne valent pas votre temps de toute façon.
  • Tout ce que vous DEVEZ optimiser devrait probablement être glissé dans une extension C puis chargé dynamiquement dans le runtime PHP
  • Comme vous pouvez le voir, nous n'obtenons aucune incitation en micro-optimisant notre code en PHP - d'autre part, si vous passez ce temps à faire PHP = code plus lisible et maintenable - qui vous rapportera plus de dividendes.

En général,

Je ne passerais pas beaucoup de temps à "TOOOOO" pour optimiser mon code dans un langage dynamique comme Python ou Ruby - car ils ne sont PAS conçus pour les tâches de calcul intensif en CPU . Ils résolvent différentes classes de problèmes où la modélisation d'une situation du monde réel d'une manière élaborée (qui est facile à lire et à maintenir) - qui s'appelle expressivité - est plus important que la vitesse. Si la vitesse était la principale préoccupation, ils ne seraient pas dynamiques en premier lieu.

Pour les programmes compilés (C++, Java), l'optimisation est plus cruciale. Mais là aussi, vous devez d'abord regarder la nature/le domaine/le but du programme que vous écrivez. Vous devez également peser soigneusement le temps de micro-optimisation par rapport aux gains de cette optimisation. Si vous avez besoin d'encore plus d'optimisation, vous pouvez également envisager de descendre un peu - et de coder ces morceaux de votre code dans l'assembleur.

Donc, pour répondre à votre question initiale - "La micro-optimisation est-elle importante lors du codage?" - la réponse est - cela DÉPEND -

  • Quel genre de chose que vous faites: domaine d'application, complexité?
  • Les améliorations de la vitesse en microsecondes sont-elles vraiment importantes pour votre programme?
  • Quel type d'optimisation sera le plus avantageux? Ce n'est pas toujours une optimisation de code, mais quelque chose d'extérieur.
  • Combien de "bonté" (en termes de vitesse) vous récoltez du temps que vous investissez dans la micro-optimisation?
  • De meilleures vitesses peuvent-elles être atteintes par d'autres moyens - en changeant le matériel, RAM & processeur, en exécutant le code en parallèle ou sur un système distribué?

Non seulement la micro-optimisation (optimisation du code d'ailleurs) prend du temps, mais elle "fausse" la lisibilité naturelle de votre code, le rendant ainsi lourd à entretenir. Considérez-le toujours comme un dernier recours - essayez toujours d'optimiser l'ensemble de l'application en adoptant un meilleur matériel et une meilleure architecture que d'optimiser des fichiers de code individuels.

25
treecoder

Il semble y avoir beaucoup de réponses qui disent que la micro-optimisation est

tout sur les compromis - performances, temps, coût, effort, lisibilité/maintenabilité, etc.

Mais bon je sais qu'il y a des optimisations où il n'y a pas d'impact sur la lisibilité, et j'aime juste les faire pour le plaisir. J'ai vu sur certains de mes travaux scolaires (qui étaient tous basés sur la vitesse), qu'il est toujours agréable d'envisager la micro-optimisation lors de l'écriture d'instructions conditionnelles comme:

if (counter < X && shouldDoThis()) // shouldDoThis() is an expensive function

est toujours plus agréable que

if (shouldDoThis() && counter < X ) 

Il y a plusieurs façons d'accélérer votre code comme ça et la différence est généralement négligeable (pas toujours cependant), mais je me sens mieux si je l'écris comme ça.

Je ne sais pas si quelqu'un considère même cela comme une optimisation, mais je pense qu'un programmeur devrait savoir et considérer ces choses lors de l'écriture de son code.

18
zidarsk8

Au début de ma carrière, des déclarations générales telles que "ne pas micro-optimiser" ont créé beaucoup de confusion. Tout est circonstanciel; ainsi, la raison pour laquelle les gens disent "meilleure pratique" plutôt que "faire ceci".

La "meilleure pratique" est le premier choix compte tenu de toutes les circonstances. Par exemple, LINQ et Entity Framework doivent être utilisés à la place de SQL en ligne. Dans mon entreprise, nous sommes sur SQL Server 20 . SQL Server 2000 ne prend pas en charge Entity Framework. Les meilleures pratiques nécessitent:

  • Vendre mon patron à l'idée d'acheter une nouvelle version de SQL Server, ce qui signifie plusieurs milliers de dollars.
  • Vendre des développeurs sur l'idée d'apprendre de nouvelles technologies.

Je sais par expérience que cela ne se produira pas. Donc, je pouvais arrêter, stresser sans fin ou ne pas suivre les meilleures pratiques.

Il y a des considérations politiques, techniques et monétaires derrière les décisions qui affectent le résultat global. N'oubliez pas ce fait lorsque vous prenez une décision et choisissez judicieusement vos combats.

" Pour tout, il y a une saison, un temps pour chaque activité sous le ciel. "

11
P.Brian.Mackey

C'est toujours un compromis.

Tout d'abord, l'industrie informatique est à la fin de l'argent. Ce que vous devez faire en tant que développeur, c'est générer de la valeur pour le client afin que vous obteniez de l'argent (c'est une simplification excessive mais le point principal est ici).

Le temps du développeur coûte de l'argent. La puissance de la machine coûte aussi de l'argent. Habituellement, ce deuxième coût est bien inférieur au premier. Il est donc capital d'avoir un code lisible et un code maintenable, afin que le développeur puisse passer la plupart de son temps à fournir de la valeur.

La micro-optimisation peut, dans certains cas, être importante. Mais ils impliquent généralement du code moins lisible ou moins extensible (ce n'est pas le cas de votre exemple lié, mais en général, c'est le cas). Cela coûtera à un moment donné au développeur. Cette fois étant plus chère que la puissance de la machine, c'est du gaspillage.

Deuxièmement, la micro-optimisation dans un grand projet peut rendre sa maintenance/évolution de plus en plus difficile. Le problème avec cela est que lors de l'évolution, une autre optimisation peut maintenant être impossible à faire. Avec une application évolutive, vous vous retrouverez généralement avec une solution plus lente que ce que vous auriez eu sans faire ces optimisations.

Troisièmement, l'optimisation est souvent peu pertinente car la complexité de l'algorithme surmontera généralement toute micro-optimisation que vous auriez pu faire si l'ensemble de données augmentait. Malheureusement, comme la micro-optimisation rend votre code plus difficile à maintenir/évoluer, cette optimisation peut être plus difficile à faire.

Parfois, la valeur est dans cette optimisation (pensez aux programmes critiques de latence, comme dans les jeux vidéo ou le pilote automatique d'un avion). Mais cela doit être démontré. Habituellement, votre programme passe la plupart du temps dans une portion limitée de code. Quelle que soit la micro-optimisation que vous faites, vous n'obtiendrez jamais vos programmes plus rapidement sans identifier le goulot d'étranglement et travailler sur cette partie.

En posant votre question comme vous l'avez montré, vous n'avez pas évalué le problème sur un programme réel. Dans ce cas, vous auriez pu faire l'affaire et avoir remarqué si c'était plus rapide ou non. Vous le demandiez donc avant d'avoir un problème. C'est là que se trouve le problème. Vous gérez le problème de l'optimisation dans le mauvais sens.

La maintenance et l'évolution étant généralement plus utiles que la micro-optimisation, assurez-vous d'avoir la bonne interface avant de faire quoi que ce soit. Ensuite, si certaines parties de votre programme sont suffisamment abstraites les unes pour les autres, vous pouvez en micro-optimiser une sans gâcher le tout. Cela nécessite que votre interface fonctionne suffisamment longtemps pour être approuvée.

8
deadalnix

La performance est une caractéristique

L'article de Jeff Atwood est un excellent article sur la construction d'un site Web haute performance et l'importance de le faire ...

Cela dit, ne vous concentrez pas sur la micro-optimisation avant d'en avoir besoin. Vous pouvez effectuer une optimisation plus rentable. Concentrez-vous sur l'architecture, pas sur le code. La plupart des sites Web que j'ai vus qui fonctionnaient lentement avaient des problèmes de haut niveau (couche de service Web inutile, mauvaise conception de base de données, architectures trop compliquées) qui non seulement affectaient les performances mais étaient profondément enracinés et difficiles à résoudre.

Lorsque vous créez un site Web, votre code côté client et votre logique de base de données sont beaucoup plus susceptibles de provoquer des problèmes de performances que votre code côté serveur. Comme tout, cependant, si vous avez des problèmes de performances, vous le saurez, encore mieux profiler votre code et vous pouvez les trouver dès le début.

8
Mike Cellini

Que voulez-vous optimiser?

  • Performances logicielles?
  • Fiabilité?
  • Productivité du programmeur?
  • Satisfaction du client?
  • Efficacité énergétique?
  • Maintenabilité?
  • Temps de mise sur le marché?
  • Coût?

"Optimiser" ne signifie pas toujours que le code doit être exécuté aussi rapidement que possible. Il est parfois important de trouver le moyen le plus rapide de faire quelque chose, mais ce n'est vraiment pas si courant dans la plupart des codes. Si les utilisateurs ne peuvent pas remarquer la différence entre 50 et 100 microsecondes, il n'y a effectivement aucune différence entre les deux dans le code qui ne s'exécutera qu'occasionnellement. Voici un exemple:

Si vous devez mettre à jour en permanence un affichage de la longueur de l'entrée de l'utilisateur et du temps qu'il faut à l'une des deux routines pour déterminer que la longueur est beaucoup plus petite que le temps entre deux frappes consécutives, peu importe la routine tu utilises. D'un autre côté, si vous devez déterminer la longueur d'un milliard de chaînes, vous voudrez probablement prêter une attention particulière aux différences de performances entre les différentes routines. Dans le premier cas, vous préférerez peut-être écrire du code facile à comprendre et à vérifier; dans le second cas, vous pourriez être disposé à échanger la lisibilité contre la vitesse.

Dans tous les cas, si vous souhaitez optimiser votre code, vous devez profiler votre code avant et après toute modification que vous apportez. De nos jours, les programmes sont suffisamment compliqués pour qu'il soit souvent difficile de dire où se trouvent les goulots d'étranglement; le profilage vous aide à optimiser le bon code puis à montrer que les optimisations que vous avez faites ont vraiment fonctionné.

Vous n'avez pas dit quand votre père a pris sa retraite ou quel genre de programmation il a fait, mais sa réaction n'est pas surprenante. Historiquement, la mémoire, le stockage secondaire et le temps de calcul étaient tous chers, et parfois très coûteux. De nos jours, toutes ces choses sont devenues très bon marché par rapport au temps du programmeur. En même temps, les processeurs et les compilateurs sont devenus capables d'optimiser le code d'une manière que les programmeurs ne pourraient jamais égaler. L'époque où les programmeurs utilisent de petites astuces pour faire quelques instructions machine ici et là est pour la plupart révolue.

7
Caleb

Il n'est pas important de micro-optimiser lors de l'écriture du code. L'optimisation doit être effectuée à l'aide d'un profileur, optimisant le code là où cela est important.

CEPENDANT , un programmeur devrait essayer d'éviter de faire des choses évidemment stupides en écrivant le code.

Par exemple, ne faites pas d'opérations coûteuses répétées à l'intérieur d'une boucle. Stockez la valeur dans une variable en dehors de la boucle et utilisez-la. Ne faites pas des choses comme des comparaisons de chaînes ou des expressions régulières encore et encore dans une fonction souvent appelée, lorsque vous pouvez monter d'un niveau, faire la comparaison et en faire un entier ou une référence de fonction ou une classe dérivée.

Ces choses sont faciles à retenir pour un programmeur expérimenté et améliorent presque toujours la qualité du code.

7
Zan Lynx

Le temps du développeur coûte plus cher que le temps informatique. C'est généralement ce que vous souhaitez optimiser. Mais:

  • Il y a une différence entre la micro-optimisation et la complexité algorithmique. Passez suffisamment de temps pour être sûr que vous utilisez le bon algorithme.
  • Assurez-vous de poser la bonne question, select (select count(*) from foo) >= 1 n'est pas la même chose que select exists(select 1 from foo).
  • certains idiomes linguistiques sont populaires simplement parce qu'ils sont plus rapides, c'est correct de les utiliser, car la plupart des utilisateurs couramment de la langue les connaissent. (votre exemple est un bon exemple).

Lorsque vous décidez quoi optimiser, souvenez-vous toujours loi d'Amdahl . Voir le lien pour des mathématiques précises; la déclaration lapidaire à retenir est:

Si une partie de votre programme représente 10% de son exécution et que vous optimisez cette partie pour qu'elle s'exécute deux fois plus rapidement, le programme dans son ensemble ne accélérer de 5%.

C'est pourquoi les gens disent toujours que cela ne vaut pas la peine d'optimiser les parties de votre programme qui n'occupent pas plus de quelques pour cent du temps d'exécution total. Mais ce n'est là qu'un cas particulier d'un principe plus général. La loi d'Amdahl vous dit que si vous devez exécuter le programme entier deux fois plus vite, vous devez accélérer chaque morceau en moyenne de 50%. Il vous indique que si vous avez besoin de traiter vingt gigaoctets de données, il n'y a que deux façons de faire plus vite que le temps qu'il faut pour lire vingt gigaoctets sur le disque: obtenir un disque plus rapide ou réduire la taille des données.

Alors, que dit la loi d'Amdahl sur les micro-optimisations? Il dit qu'ils valent peut-être la peine s'ils s'appliquent à tous les niveaux. Si vous pouvez réduire de 1% la durée d'exécution de chaque fonction de votre programme, félicitations! Vous avez accéléré le programme d'un pour cent. Cela valait-il la peine? Eh bien, en tant que compilateur, je serais ravi de trouver une optimisation qui a fait cela, mais si vous le faites à la main, je dirais que vous cherchez quelque chose de plus grand.

7
zwol

Cela dépend du stade de développement auquel vous vous trouvez, lorsque vous commencez à écrire quelque chose, les micro-optimisations ne doivent pas être prises en compte, car vous obtiendrez plus de gains de performances en utilisant de bons algorithmes que vous en utilisant des micro-optimisations. Tenez également compte de ce que vous développez, car les applications sensibles au facteur temps bénéficieront davantage de considérations de micro-optimisation que les applications métier génériques.

Si vous testez et étendez des logiciels, les micro-optimisations vous nuiront probablement.Ils ont tendance à rendre le code plus difficile à lire et même à introduire leur propre ensemble unique de bogues qui doivent être corrigés avec tout ce qui doit être corrigé.

Si vous recevez des plaintes d'utilisateurs concernant le code lent, cela peut valoir la peine d'être pris en compte, mais uniquement si tout le reste a été résolu, à savoir:

  • Le code est-il bien écrit?
  • L'application est-elle en mesure d'accéder à ses données sans aucun problème?
  • Un meilleur algorithme peut-il être utilisé?

Si toutes ces questions ont reçu une réponse et que vous rencontrez toujours des problèmes de performances, il est peut-être temps de commencer à utiliser des micro-optimisations dans le code, mais il y a de fortes chances que d'autres changements (c'est-à-dire un meilleur code, un meilleur algorithme, etc.) vont vous aider. plus de gain de performance qu’une micro-optimisation.

6
rjzii

La vitesse d'exécution est l'un des nombreux facteurs qui contribuent à la qualité d'un programme. Souvent, la vitesse a une corrélation inverse avec la lisibilité/maintenabilité. Dans presque tous les cas, le code doit être lisible par l'homme afin qu'il puisse être conservé. Le seul moment où la lisibilité peut être compromise est lorsque la vitesse est une exigence essentielle. L'exigence de rendre le code plus rapide que ne le permet la lisibilité/maintenabilité complète n'est pratiquement jamais applicable, mais il y a certains cas où cela le sera. La principale chose à retenir est que le code micro-optimisé est souvent du code hacky, donc à moins qu'il n'y ait une exigence définie quelque part, c'est presque toujours la mauvaise façon de résoudre le problème. Par exemple, l'utilisateur ne remarquera presque jamais la différence entre les temps d'exécution de 0,5 seconde et de 1 seconde dans les opérations CRUD, vous n'avez donc pas besoin de participer à un Assembly-interop-hackfest pour atteindre ces 0,5 secondes. Oui, je pourrais piloter un hélicoptère pour travailler et ce serait 10 fois plus rapide, mais je ne le fais pas à cause du prix et du fait que l'hélicoptère est beaucoup plus difficile à piloter. Lorsque vous micro-optimisez du code inutilement, c'est exactement ce que vous faites: ajouter une complexité et des coûts inutiles pour atteindre un objectif superflu.

5
Morgan Herlocker

La micro-optimisation est importante lorsque vous frappez une contrainte. La chose qui vous intéresse peut être la mémoire, le débit, la latence ou la consommation d'énergie. Notez que ce sont des caractéristiques au niveau du système; vous n'avez pas besoin (et ne pouvez pas) optimiser chaque fonction dans tous les sens.

Les systèmes embarqués sont plus susceptibles d'avoir besoin de micro-optimisation car les contraintes sont plus facilement atteintes. Cependant, même là, la micro-optimisation ne vous amène à ce jour; vous ne pouvez pas micro-optimiser votre sortie d'une mauvaise conception. Le point sur une bonne conception dans un système est que vous pouvez raisonner sur le système dans son ensemble. Les composants qui nécessitent une micro-optimisation doivent être soigneusement exposés et optimisés de manière à ne pas compromettre la conception du système.

Notez que les petits systèmes "embarqués" aujourd'hui peuvent être assez proches des Vaxen ou PDP-11s d'antan, donc ces problèmes étaient plus courants. Sur un système polyvalent moderne faisant de l'informatique commerciale générale moderne, la micro-optimisation est rare. Cela explique probablement pourquoi votre père prend la position qu'il occupe.

Cependant, peu importe que vous ayez affaire à des nanosecondes, des millisecondes, des secondes ou des heures; les problèmes sont les mêmes. Ils doivent être évalués dans le contexte du système et de ce que vous essayez de réaliser.

Ceci est un exemple d'une question récente à laquelle j'ai répondu Stack Overflow pour un cas où une micro-optimisation était nécessaire: encodeurs vidéo open source pour un système embarqué système.

5
janm

Le plus gros problème de la micro-optimisation est qu'elle vous conduit à écrire un code plus difficile à maintenir.

Un autre problème dépend de la configuration de l'ordinateur, parfois votre micro-optimisation peut avoir les pires performances que sans "optimisation".

Faire de nombreuses micro-optimisations vous prendra beaucoup de temps à lutter contre quelque chose qui n'a pas vraiment d'importance.

Une meilleure approche consiste à rendre un code plus propre, plus facile à maintenir et si vous rencontrez des problèmes de performances, vous exécutez un profil pour comprendre ce qui ralentit réellement votre code. Et sachant exactement ce qui est vraiment mauvais, vous pouvez y remédier.

Je ne dis pas que ne pas faire de micro-optimisations est une excuse pour écrire du code stupide.

4
Daniel Moura

Je l'ai déjà dit, et je le dirai ici: "L'optimisation prématurée est la racine de tout mal". Cela devrait être l'une des règles au centre de l'esprit de tout programmeur.

Le code peut, jusqu'à un certain point, toujours être plus rapide qu'il ne l'est actuellement. À moins que vous n'assembliez l'assemblage à la main avec une puce particulière à l'esprit, l'optimisation a toujours quelque chose à gagner. Cependant, à moins que vous VOULEZ être un assemblage à la main pour tout ce que vous faites, il doit y avoir un objectif quantitatif, qui une fois que vous vous réunissez, vous dites "c'est assez" et arrêtez d'optimiser, même s'il y a toujours un aspirant de performance vous au visage.

Un code beau, élégant et extrêmement performant est inutile s'il ne fonctionne pas (et par "travail", je veux dire produire la sortie attendue compte tenu de toutes les entrées attendues). Par conséquent, produire du code qui fonctionne devrait TOUJOURS être la première priorité. Une fois que cela fonctionne, vous évaluez les performances, et si elles manquent, vous cherchez des moyens de les améliorer, au point où elles sont suffisamment bonnes.

Il y a certaines choses que vous devez décider à l'avance qui auront un impact sur les performances; décisions très basiques comme la langue/le runtime que vous utiliserez pour implémenter cette solution. Beaucoup de ces facteurs auront un impact sur les performances de plusieurs ordres de grandeur plus que d'appeler une méthode contre une autre. Honnêtement, PHP, en tant que langage scripté, est déjà un gage de performances, mais comme très peu de sites scriptés sont construits de bas en haut en C/C++, il est comparable à d'autres technologies parmi lesquelles vous choisiriez probablement (Java Servlets, ASP.NET , etc).

Après cela, la taille des messages d'E/S est votre prochain plus grand tueur de performances. L'optimisation de ce que vous lisez et écrivez sur le disque dur, les ports série, les canaux réseau, etc. améliorera généralement le temps d'exécution du programme de plusieurs ordres de grandeur, même si les algorithmes derrière les opérations d'E/S étaient efficaces. Après cela, réduisez la complexité Big-O de l'algorithme lui-même, puis si vous le devez absolument, vous pouvez "micro-optimiser" en choisissant des appels de méthode moins coûteux et en prenant d'autres décisions ésotériques à bas niveau.

4
KeithS

Si vous commencez à vous soucier des millisecondes, vous devriez envisager d'abandonner PHP et utiliser C ou Assembly à la place. Non pas que je veuille le faire, cela n'a aucun sens de discuter de tels nombres utilisez un langage de script. Est-ce que votre code itère souvent avec cette commande?

Les facteurs environnementaux sont hors de question ici, ces serveurs fonctionnent de toute façon 24h/24 et 7j/7 et s'ils traitent réellement quelque chose n'aurait d'importance que si c'est vraiment une tâche qui s'exécute pendant très longtemps.

Très probablement, la lumière dans votre bureau et l'énergie que nos ordinateurs utilisaient pendant que nous tapions tous des questions et des réponses, consommaient beaucoup plus d'énergie que n'importe quel type de micro-optimisation que vous pouvez raisonnablement appliquer à vos applications.

4
thorsten müller

Vous mentionnez que votre père est un programmeur à la retraite. Les programmeurs qui travaillaient dans le monde du mainframe devaient être très préoccupés par les performances. Je me souviens avoir étudié une activité de l'US Navy où leur ordinateur central était contraint par le matériel à 64 Ko de mémoire par utilisateur. Dans ce monde de programmation, vous devez effleurer chaque petit tout petit peu que vous pourriez.

Les choses sont très différentes maintenant et la plupart des programmeurs n'ont pas à se soucier autant des micro-optimisations. Cependant, les programmeurs de systèmes embarqués le font toujours et les personnes travaillant dans les bases de données ont encore beaucoup besoin d'utiliser du code optimisé.

4
HLGEM

Vous devez choisir le meilleur algorithme simple pour la tâche. La raison pour laquelle il doit être simple est de garder le code lisible. La raison pour laquelle il doit être le meilleur est d'éviter de démarrer avec de mauvaises caractéristiques d'exécution. Ne choisissez pas aveuglément BubbleSort lorsque vous savez que vous aurez de grands ensembles de données. C'est bien, cependant, pour la sorte occasionnelle de 10 éléments.

ALORS, si les chiffres de profilage montrent que votre choix du meilleur algorithme simple n'était pas assez bon, vous pouvez commencer l'optimisation (qui est généralement le coût de la lisibilité).

4
user1249

La micro-optimisation est-elle importante lors du codage?

Non, étant donné qu'il existe des plates-formes telles que JVM et . NET où le code est écrit pour une machine virtuelle et tente ainsi d'optimiser l'exécution peut ne pas fonctionner aussi bien car ce qui est optimal sur le bureau d'un développeur n'est pas nécessairement le même sur un serveur. Regardez à quel point certains de ces logiciels de haut niveau sont éloignés du matériel pour un autre point ici. La diversité du matériel est quelque chose à considérer, dans quelle mesure est-il réaliste d'optimiser le code pour des puces spécifiques comme un CPU ou un GPU lorsqu'un nouveau modèle sortira probablement dans moins d'un an?

Une autre question à considérer ici est la performance mesurée par quelle métrique: vitesse d'exécution, mémoire utilisée pour l'exécution, vitesse de développement de nouvelles fonctionnalités, taille de la base de code sur un serveur sous des formes compilées ou décompilées, évolutivité, maintenabilité, etc. .? Si elle est prise assez largement, la question devient triviale, mais je ne sais pas dans quelle mesure vous vouliez vraiment considérer la performance comme telle, cela peut être presque n'importe quoi tant qu'elle peut être mesurée d'une manière ou d'une autre.


Certaines micro-optimisations peuvent fonctionner et d'autres peuvent ne pas fonctionner, c'est pourquoi on peut se demander combien cela vaut la peine d'effectuer un tel travail par rapport à d'autres travaux qui peuvent être considérés comme une priorité beaucoup plus élevée, comme les nouvelles fonctionnalités ou la correction de bogues. L'autre question serait de savoir si une mise à niveau du matériel ou des logiciels peut également briser certaines de ces optimisations.

3
JB King

Le code doit être écrit pour être absolument clair sur ce qu'il fait. Ensuite, si et seulement si c'est trop lent, revenez en arrière et accélérez-le. Le code peut toujours être modifié pour être plus rapide plus tard, si cela peut être compris, mais bonne chance pour le changer pour qu'il soit clair s'il est rapide.

3
DeadMG

Il est important si:

1) La vie de quelqu'un dépend de votre code. Une fonction prenant 25 ms à exécuter dans le moniteur de fréquence cardiaque de quelqu'un est probablement une mauvaise idée.

Personnellement, j'adopte une double approche - il y a des micro-optimisations que vous pouvez faire qui n'affecteront pas la lisibilité - évidemment, vous voulez les utiliser. Mais si cela affecte la lisibilité, attendez - vous n'obtiendrez pas beaucoup d'avantages et cela pourrait vous prendre plus de temps pour déboguer à long terme.

3
ansiart

La lisibilité du code à mon humble avis est plus importante que la micro-optimisation car dans la plupart des cas, la micro-optimisation n'en vaut pas la peine.

Article sur les micro-optimisations non sensées :

Comme la plupart d'entre nous, je suis fatigué de lire des articles de blog sur les micro-optimisations non sensées comme le remplacement de l'impression par l'écho, ++ $ i par $ i ++, ou les guillemets doubles par des guillemets simples. Pourquoi? Parce que 99,999999% du temps, ce n'est pas pertinent. Pourquoi? Parce que 99,99% du temps, vous feriez mieux d'installer un accélérateur PHP comme APC, ou ajoutez ces index manquants sur les colonnes de votre base de données, ou essayez d'éviter les 1000 requêtes de base de données que vous avez sur la page d'accueil .

print utilise un opcode de plus car il retourne réellement quelque chose. Nous pouvons conclure que l'écho est plus rapide que l'impression. Mais un opcode ne coûte rien, vraiment rien.

J'ai essayé une nouvelle installation WordPress. Le script s'arrête avant qu'il ne se termine par une "erreur de bus" sur mon ordinateur portable, mais le nombre d'opcodes était déjà supérieur à 2,3 millions. Assez dit.

Ainsi, dans la plupart des cas, la micro-optimisation permet d'économiser 1 opération sur des millions, mais aggrave la lisibilité.

1
webvitaly

Je pense qu'il y a une grande différence entre une bonne programmation et une micro-optimisation.

S'il y a deux façons de faire la même tâche, l'une étant plus rapide que l'autre et les deux ayant la même lisibilité, vous devez utiliser la plus rapide. Toujours. Et c'est une bonne programmation. Il n'y a aucune raison de ne pas utiliser un meilleur algorithme pour résoudre un problème. Et même le documenter est facile: donnez le nom de l'algorithme, tout le monde pourra le rechercher sur Google et trouver plus d'informations sur son fonctionnement.

Et les bons algorithmes sont déjà optimisés. Ils seront rapides. Ils seront petits. Ils utiliseront la mémoire minimale requise.

Même si vous les utilisez, votre programme n'a toujours pas cette performance, vous pouvez envisager de les micro-optimiser. Et vous devrez vraiment connaître la langue pour pouvoir micro-optimiser.

Et il est toujours possible de dépenser plus d'argent en matériel. Le matériel est bon marché, les programmeurs sont chers . Ne dépensez pas trop de temps/argent en optimisant quand vous pouvez simplement acheter du matériel.

1
woliveirajr

"Worth it" a besoin de contexte, comme combien il est plus simple d'écrire, de lire et de maintenir par rapport à combien plus rapide il fait quelque chose pour utilisateur nettement plus réactif, interactif, nécessitant moins de temps pour eux d'attendre.

Économiser quelques centimes pour acheter une canette de soda ne me fera pas beaucoup de bien si je dois parcourir une distance pour sauver ces centimes, d'autant plus que je bois rarement du soda de nos jours. Économiser quelques centimes par boîte sur l'achat d'un million de canettes de sodas pourrait être une énorme affaire.

Pendant ce temps, économiser quelques centimes lorsque deux personnes sont juste à côté de moi et que l'un offre exactement la même chose pour quelques centimes moins cher et l'autre pas, et je choisis le plus cher parce que j'aime mieux leur chapeau semble être un cas insensé de pessimisation.

Ce que je trouve souvent que les gens appellent des "micro-optimisations" semblent curieusement dépourvus de mesures, de contexte et de discussion avec les utilisateurs, alors qu'il devrait y avoir absolument les trois à envisager de telles optimisations si elles ne sont pas triviales à appliquer. Pour moi, une micro-optimisation appropriée de nos jours concerne des choses comme les dispositions de mémoire et les modèles d'accès, et même si elles peuvent sembler "micro" au point, elles ne sont pas micro en effet.

J'ai réussi, il n'y a pas si longtemps, à réduire une opération de 24 secondes à 25 millisecondes (environ 960 fois plus vite), avec des sorties identiques (sécurisées par des tests automatisés), sans modification de la complexité algorithmique, pour le skinning de diffusion de chaleur volumétrique, à travers "micro-optimisations" (dont la plus importante provenait d'un changement de disposition de la mémoire qui l'a réduit à environ 2 secondes, puis le reste était des choses comme SIMD et une analyse plus approfondie des échecs de cache dans VTune et un autre réarrangement de la disposition de la mémoire).

Wolfire explique la technique ici, et il a eu du mal avec le temps requis: http://blog.wolfire.com/2009/11/volumetric-heat-diffusion-skinning/

Mon implémentation a réussi à le faire en quelques millisecondes alors qu'il avait du mal à le réduire à moins d'une minute: enter image description here

Après l'avoir "micro-optimisé" de 24 secondes à 25 ms, cela a changé la donne dans le flux de travail. Désormais, les artistes peuvent changer leurs plates-formes en temps réel à plus de 30 FPS sans attendre 24 secondes à chaque fois qu'ils apportent de petites modifications à leur plate-forme. Et cela a en fait changé toute la conception de mon logiciel puisque je n'avais plus besoin de barre de progression et de choses de ce genre, tout est devenu interactif. Cela pourrait donc être une "micro-optimisation" dans le sens où toutes les améliorations sont venues sans aucune amélioration de la complexité algorithmique, mais c'était plutôt une "méga-optimisation" qui a rendu ce qui était autrefois un processus douloureux et non interactif en un système interactif en temps réel qui a complètement changé la façon de travailler des utilisateurs.

Mesure, exigences de l'utilisateur final, contexte

J'ai vraiment aimé le commentaire de Robert ici et peut-être que je n'ai pas fait le point que je voulais:

Eh bien, allez. Personne ne dira que ce type de changement n'en vaut pas la peine. Vous avez pu démontrer un avantage tangible; de nombreuses micro-optimisations ne le peuvent pas.

C'est, malgré le fait de travailler dans un domaine très critique pour les performances avec des exigences souvent en temps réel, la seule fois où je considère une micro-optimisation qui nécessite de sortir de mon chemin.

Et je soulignerais non seulement les mesures, mais le côté utilisateur de celui-ci. Je suis bizarre en ce sens que je suis venu dans mon domaine actuel (et anciennement gamedev) en tant qu'utilisateur/fan d'abord, développeur ensuite. Je n'ai donc jamais été aussi excité par les choses habituelles qui excitent les programmeurs comme la résolution d'énigmes techniques; Je leur ai trouvé un fardeau, mais je les supporterais à travers le rêve de l'utilisateur que j'ai partagé avec d'autres utilisateurs. Mais cela m'a aidé à m'assurer que si j'optimisais quoi que ce soit, cela aurait un réel impact sur les utilisateurs avec de réels avantages. C'est ma protection contre la micro-optimisation sans but.

C'est en fait aussi important que le profileur à mon avis, car j'avais des collègues qui ont fait des choses comme la micro-optimisation de la subdivision d'un cube en un milliard de facettes uniquement pour s'étouffer avec des modèles de production du monde réel comme des personnages et des véhicules. Leur résultat était impressionnant dans un certain sens "démo technologique", mais presque inutile pour les utilisateurs réels, car ils profilaient et mesuraient et comparaient des cas qui ne s'alignaient pas avec des cas d'utilisation réels. Il est donc très important de comprendre ce qui est important pour les utilisateurs en premier, soit en apprenant à penser et à utiliser le logiciel comme tel, soit en collaborant avec eux (idéalement les deux, mais au moins collaborer avec eux). La chose la plus importante pour moi si nous voulons obtenir des micro et commencer des cycles de rasage et des ratés de cache et ainsi de suite est de commencer à devenir vraiment bon pour prioriser où nous allons faire le chemin pour le faire (ce qui correspond naturellement à connaître tous les endroits où nous ne devrions pas ne faites pas cela, pour lequel la compréhension du profileur et de l'utilisateur est très importante).

1
Dragon Energy

D'autres réponses sont exactes sur l'argent. Mais j'ajouterai un autre point où l'on doit différencier ce qui est l'optimisation/micro-optimisation prématurée et l'écriture de code performant qui reflète une compréhension du comportement des constructions du langage/framework (désolé, impossible de trouver un seul mot pour le dernier). Le dernier est un bonne pratique de codage et on devrait généralement le faire!

Je vais expliquer. Une mauvaise optimisation (lecture prématurée/micro-optimisation) n'est pas lorsque vous optimisez des sections de code sans profilage pour savoir si elles sont vraiment les goulots d'étranglement. C'est lorsque vous optimisez en fonction de vos hypothèses, des rumeurs et des comportements non documentés. S'il est documenté et fait quelque chose de manière plus efficace/ logique aussi petite soit-elle, je l'appelle bonne optimisation . Comme d'autres l'ont déclaré, ces deux éléments ont des inconvénients et presque aucun avantage en ce qui concerne les bonnes affaires, mais je fais toujours le dernier, pas le premier, si ce n'est pas le cas défait totalement la lisibilité. Oui, la lisibilité/maintenabilité est de la plus haute importance et il s'agit de l'endroit où vous tracez la ligne.

Je vais réitérer les points avancés par d'autres ici comme la futilité des optimisations bonnes et mauvaises:

  1. Vos dépendances à un problème spécifique peuvent changer et tout le temps passé à optimiser avant de terminer la section logique de votre application est une perte de temps. Je veux dire l'optimisation à un stade relativement précoce. Aujourd'hui, vous avez un List<T> et au moment où votre application est livrée, vous deviez la changer en LinkedList<T> et maintenant tout le benchmarking était une perte de temps et d'efforts.

  2. La plupart du temps, le véritable goulot d'étranglement de votre application (lu comme une différence mesurable) pourrait être 5% de votre code (principalement les sql) et l'optimisation des 95% restants ne procure aucun avantage à vos clients.

  3. Habituellement, un code plus performant "techniquement" signifie plus de verbosité, ce qui signifie à son tour plus de code sujet aux erreurs, ce qui signifie à son tour une maintenance plus difficile et plus de temps passé, ce qui signifie que vous gagnez moins d'argent.

  4. L'empreinte carbone que vous économisez pour le monde entier grâce à un gain de performances de 1% est facilement éclipsée par les gaz à effet de serre que votre équipe devra émettre lors du débogage et du maintien de ce code.

Les points négatifs de mauvaise optimisation en particulier sont:

  1. Il ne vous donne pas souvent les performances que vous attendez. Voir cette question sur SO, où les optimisations ont mal tourné . En fait, cela peut avoir des effets négatifs. C'est le problème avec un comportement non documenté.

  2. La plupart des compilateurs modernes le feront de toute façon.

Je vais donner quelques exemples de mauvaise et bonne optimisation:

Le mauvais -

  1. utilisation de types entiers plus petits au lieu de Int32.

  2. ++i utilisé au lieu de i++

  3. for au lieu de foreach (le pire que j'ai vu, défait totalement la logique)

  4. éviter les variables fermées

    string p;
    foreach (var item in collection)
        p = ...;
    
  5. en utilisant char au lieu de chaîne lors de la concaténation de chaîne, comme:

    string me = 'i' + "me myself"; // something along that line - causes boxing
    

Le bon (du monde .NET. Devrait être explicite) -

  1. Double recherche

    if (Dictionary<K, V>.TryGetValue(K, out V))
        do something with V
    

    au lieu de

    if (Dictionary<K, V>.ContainsKey(K))
        do something with Dictionary<K, V>[K]
    
  2. Chargez-les tous

    DirectoryInfo.EnumerateFiles();
    

    au lieu de

    DirectoryInfo.GetFiles();
    
  3. Coulée en deux étapes:

    s = o as string;
    if (s != null)
        proceed
    

    au lieu de

    if (o is string)
        s = (string)o;
    
  4. Si la commande n'a pas d'importance

    if (counter < X || expensiveFunction())
    

    au lieu de

    if (expensiveFunction() || counter < X)
    
  5. Boxe

    void M<T>(T o) //avoids boxing
    {
    
    }
    

    au lieu de

    void M(object o)
    {
    
    }
    

Si vous me demandez si ces avantages de performance sont notables, je dirais que non. Mais je suggérerais de les utiliser car cela découle d'une compréhension du comportement de ces constructions. Pourquoi passer deux appels alors que vous ne pouvez en faire qu'un? D'un point de vue philosophique, sa bonne pratique de codage. Et 1 et 3 sont également légèrement moins lisibles en termes stricts, mais prévalent-ils sur la lisibilité? Non, pas grand chose, donc j'utilise. Maintenant, c'est la clé - maintenir un rapport performances/lisibilité décent. Et quand c'est ça, c'est à peu près où vous tracez la ligne.

1
nawfal

J'ai commencé à programmer il y a près de 31 ans, où la mémoire et le CPU sont rares. C'est peut-être pour ça que je suis d'accord avec ton père.

Je crois qu'un bon codeur doit se soucier de l'optimisation dans chaque ligne de code. Mais j'ajouterais à cette phrase: autant que cela vaut et essayant toujours de privilégier la lisibilité à l'optimisation dans les endroits où les calculs ne sont pas critiques.

Par exemple, dans un autre fil, un gars a posé des questions sur le code ci-dessous, quelle solution il choisirait: CPU ou mémoire.

public class Main {

    public static int totalRevenue;
    public static int totalProfit;

    public static int option1(int numSold, int price, int cost) {
        // Option 1 (memory)
        totalRevenue += numSold * price;
        totalProfit += numSold * price - numSold * cost;
        return numSold * price;
    }

    public static int option2(int numSold, int price, int cost) {
        // Option 2 (time)
        int saleRevenue = numSold * price;
        totalRevenue += saleRevenue;
        totalProfit += saleRevenue - numSold * cost;
        return saleRevenue;
    }
}

Ce code génère le bytecode suivant:

public class Main {
  public static int totalRevenue;

  public static int totalProfit;

  public Main();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method Java/lang/Object."<init>":()V
       4: return

  public static int option1(int, int, int);
    Code:
       0: getstatic     #2                  // Field totalRevenue:I
       3: iload_0
       4: iload_1
       5: imul
       6: iadd
       7: putstatic     #2                  // Field totalRevenue:I
      10: getstatic     #3                  // Field totalProfit:I
      13: iload_0
      14: iload_1
      15: imul
      16: iload_0
      17: iload_2
      18: imul
      19: isub
      20: iadd
      21: putstatic     #3                  // Field totalProfit:I
      24: iload_0
      25: iload_1
      26: imul
      27: ireturn

  public static int option2(int, int, int);
    Code:
       0: iload_0
       1: iload_1
       2: imul
       3: istore_3
       4: getstatic     #2                  // Field totalRevenue:I
       7: iload_3
       8: iadd
       9: putstatic     #2                  // Field totalRevenue:I
      12: getstatic     #3                  // Field totalProfit:I
      15: iload_3
      16: iload_0
      17: iload_2
      18: imul
      19: isub
      20: iadd
      21: putstatic     #3                  // Field totalProfit:I
      24: iload_3
      25: ireturn
}

Par souci de compréhension, 'iload_' charge les données de la pile et 'istore_' sauvegarde les données dans la pile.

Il est facile de remarquer que vous avez vraiment enregistré une allocation de mémoire dans une solution en dépensant plus de cycles CPU. Ce genre de question peut se poser même pour des programmeurs expérimentés.

Mais il y a un hic dans cet exemple: la mémoire de pile est pré-allouée en blocs, pas au niveau des octets. Chaque fois qu'un thread s'exécute, il alloue une certaine quantité de mémoire à utiliser dans les opérations de pile. Donc, à moins que vous n'ayez la chance de voir ces 4 octets déborder votre pile (et vous obliger à configurer une taille de pile plus grande), vous finirez par dépenser la même quantité de mémoire pour exécuter les deux exemples. Mais dans le second, vous passez plus de cycles à faire des calculs mathématiques et votre code est beaucoup moins lisible.

Je l'ai apporté ici pour donner un exemple que discuter des optimisations dans de petites portions de code n'est pas mauvais. Un gars a fermé cette question en pointant ce fil. Mais ce fil ne répond pas à cette question spécifique. Il ne parle que de "ne vous inquiétez pas de l'optimisation". Et à cause de ce stupide mantra, les gens pensent que c'est juste de ne pas aller à une compréhension profonde.

Il y a une réponse raisonnable à cette question, et peut-être qu'on peut même donner une meilleure réponse sur les internes. Une fois appris, un bon programmeur sera capable de répéter instinctivement ce modèle et deviendra un meilleur programmeur. Les programmeurs doivent avoir une réflexion critique sur leur code et doivent essayer de comprendre, autant que possible, comment la machine le traitera.

Je ne préconise pas ici que nous devons tous optimiser les petites choses. N'oubliez pas que j'ai recommandé de privilégier la lisibilité aux micro-optimisations.

Je crois juste que répéter le mantra "ne vous inquiétez pas de l'optimisation" n'améliore pas les choses. Cela rend les programmeurs paresseux. Les programmeurs doivent être incités à savoir comment les choses fonctionnent dans les coulisses. De cette façon, les gens peuvent continuer à écrire un meilleur code, et choisir judicieusement quand ne pas optimiser.

0
David Rissato Cruz

Je vais le dire de cette façon - la micro-optimisation est un processus d'optimisation de quelque chose qui n'est pas du tout un goulot d'étranglement. Par exemple, si votre programme appelle deux fonctions A et B, et A prend 100 millisecondes pour terminer et B prend 2 microsecondes, et vous continuez à optimiser la fonction B. Ce n'est pas seulement important, c'est absolument faux. Mais la fonction d'optimisation B est appelée optimisation et non micro-optimisation. L'importance de l'optimisation dépend. Disons que vous n'avez rien d'autre à faire et que votre programme est exempt de bogues, alors oui, c'est important. Mais généralement, vous avez des priorités. Disons que vous devez ajouter/écrire la fonction C. Si vous pensez que l'écriture de la fonction C vous fera plus d'argent que de rendre votre programme plus rapide sans cette fonctionnalité, optez pour l'optimisation. Sinon, poursuivez la fonctionnalité. De plus, les programmeurs expérimentés axés sur les performances ne passent pas beaucoup de temps à optimiser, ils écrivent simplement des programmes rapides. Ils savent au moins quels outils utiliser et quoi faire pour ne pas passer des années à faire des optimisations (lire des micro) inutiles.

0
user11408

Il y a des micro-optimisations et des micro-optimisations. Dans VB (VB6 et VB.NET, mais en ignorant l'offre IsNullOrEmpty du framework), j'utilise toujours Len(str) <> 0 plutôt que str <> "". Cependant, je ne "corrige" normalement pas les autres codes là où ils ont utilisé ce dernier.

Oui, ce dernier est plus lisible, mais, dans ce cas, le premier n'est pas illisible.

La performance doit être un considération lors de la conception du code, mais pas au détriment de la lisibilité et de la maintenabilité.

0
Mark Hurd