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


178

J'ai récemment posé une question sur Stack Overflow pour savoir pourquoi isset () était plus rapide que strlen () en PHP . Cela a soulevé des questions sur l’importance du code lisible et sur la question de savoir si les améliorations de la performance en micro-secondes dans le code méritaient d’être prises en compte.

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 prenait pas en compte les performances de son code, même au niveau micro, il n'était pas un bon programmeur.

Je n'en suis pas si sûr. L'augmentation de la puissance de traitement nous évite peut-être de prendre en compte ce type d'amélioration de la micro-performance. Peut-être que ce genre de réflexion appartient aux personnes qui écrivent le code de langue actuel? (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 microsecondes de code représentent une perte de temps lorsqu’elles sont répliquées des milliards de fois sur des millions de sites Web.

J'aimerais connaître des réponses basées de préférence sur des 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 préoccuper 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 de temps en temps la micro-optimisation ne fait pas mal. Une compréhension de base peut nous aider à ne pas faire de mauvais choix évidents lors du codage tel que

if (expensiveFunction() || counter < X)

Devrait être

if (counter < X || expensiveFunction())

( Exemple de @ zidarsk8 ) Il pourrait s'agir d'une fonction peu coûteuse et, par conséquent, modifier le code constituerait une micro-optimisation. Mais, avec une compréhension de base, vous n’auriez pas à le faire, car vous l’écririez correctement au départ.


123
Le conseil de ton père est obsolète . Je ne demanderais pas dans quelle mesure cela améliore les performances. Je voudrais demander où le goulot d'étranglement est. Peu importe si vous améliorez les performances d'une section de code si cela ne fait aucune différence, votre lien le plus lent va déterminer la vitesse. En PHP, cela consiste à écrire sur le réseau (à moins que vous ne puissiez prouver la mesure IE autrement); ce qui se traduit par l'écriture de code plus lisible est plus important.
Martin York

61
Si le mot clé est à considérer, il n'a pas tort. Vous devez avoir une idée à ce sujet.
JeffO

37
Je suis triste car la fameuse citation de Premature Optimization n’a pas encore été mentionnée: "Les programmeurs perdent énormément de temps à réfléchir à la vitesse des parties non critiques de leurs programmes et à s’inquiéter pour eux, et ces tentatives d’efficacité ont en réalité un fort effet négatif. Nous devons oublier les petites économies d’efficacité, disons environ 97% du temps: une optimisation prématurée est la racine de tout mal . Cependant, nous ne devrions pas laisser passer nos opportunités dans ces 3% critiques. "
Tamara Wijsman

13
Pouvez-vous fournir une source sur "10% de l'énergie mondiale"?
Michael Easter

17
coder does not consider performance in their code even at the micro level, they are not good programmersest très différent de la micro-optimisation. C'est juste un bon codage.
woliveirajr

Réponses:


90

Je suis tous les deux d'accord et pas d'accord avec ton père. Les performances doivent être envisagées tôt, mais la micro-optimisation ne doit l'être que si vous savez réellement qu'un pourcentage élevé de temps sera consacré à de petites sections de code liées au processeur.

Le problème avec la micro-optimisation est que cela se fait généralement sans 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 du réglage des performances, comme dans cet exemple , dans lequel un programme apparemment simple, sans aucune efficacité évidente, est suivi d'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.

Cela montre que vous ne pouvez vraiment pas deviner ou deviner où seront les problèmes. Si vous effectuez un diagnostic, qui dans mon cas est une pause aléatoire , les lignes de code responsables d'une fraction importante du temps sont de préférence exposées. Si vous les examinez, vous pouvez trouver un code de substitution et ainsi réduire le temps total d'environ cette fraction.

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

Après ce type d’expérience, lorsque vous abordez de nouveaux problèmes de programmation, vous reconnaissez les approches de conception qui ont initialement conduit à de telles inefficiences. D'après mon expérience, cela vient de la conception excessive de la structure de données, de la structure de données non normalisée, du recours massif aux notifications, etc.


120

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

Les exigences sur lesquelles vous vous développez doivent comporter certaines spécifications de données de performances, si celles-ci posent problème au 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 avez atteint les performances minimales requises, vous n'avez plus besoin de réduire les performances du système, surtout si vous voulez compromettre davantage la lisibilité et la maintenabilité du code (dans mon expérience, un code hautement optimisé est moins lisible et plus complexe. 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,

Il existe cependant des cas où la performance est de la plus haute importance. Je pense principalement aux systèmes temps réel et aux systèmes embarqués. Dans les systèmes temps réel, la modification de l'ordre des opérations peut avoir un impact considérable sur le respect des délais rigoureux nécessaires au bon fonctionnement, voire même sur les résultats des calculs. Dans les systèmes intégrés, la mémoire, le processeur et la puissance de la batterie sont généralement limités. Vous devez donc réduire la taille de vos fichiers binaires et le nombre de calculs pour optimiser la durée de vie du système.


D'un autre côté, s'il y a un problème entre l'utilisation d'une fonction plus lente et plus rapide, il n'y a aucune raison d'utiliser la fonction plus lente - comme ici en cas de isset.
Mavrik

7
@Mavrik C'est vrai. Si vous avez deux fonctions, X et Y, et que Y est plus rapide que X (du moins dans vos conditions particulières), il n'y a aucune raison de ne pas utiliser Y, si le code est toujours aussi lisible et maintenable. Mais si vous ne connaissez pas Y et que vous avez besoin de refactoriser le code pour utiliser Y au lieu de X et que les performances (de ce segment de code) ne posent aucun problème, il n’ya aucune raison de le modifier. Tout est une question de compromis: performances, temps, coûts, efforts, lisibilité / maintenabilité, etc.
Thomas Owens

2
Je suis tout à fait d’accord, je voulais simplement préciser ce point en ce qui concerne la micro-optimisation - si cela ne vous coûte rien en termes de lisibilité / temps, faites-le. Sinon ne le fais pas.
Mavrik

Le code +1 hautement optimisé est moins lisible et moins maintenable ... mais pas toujours.
Boz

Plus de cas où la performance est importante: (1) les jeux; (2) grandes quantités de données; (3) site Web à fort trafic; (4) réactivité d'une interface utilisateur très complexe; (5) un service censé fonctionner en arrière-plan, comme une vérification de virus; (6) finances; (7) smartphone; etc. Ce n'est guère limité aux cas ésotériques comme RTS et systèmes embarqués.
Rex Kerr

103

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 de l'optimisation de programme: ne le faites pas.

Deuxième règle de l'optimisation de programme (réservée aux experts!): Ne le faites pas encore .

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

La deuxième règle implique implicitement de profiler votre code et de ne consacrer que du temps à optimiser les éléments qui feront la différence.

Lors de la programmation en assemblage, l'affirmation de votre père était correcte. Mais c'est beaucoup plus proche du métal que la plupart des gens ne programment ces jours-ci. Aujourd'hui, même si vous essayez de vous optimiser (sans profilage), votre code risque de fonctionner plus lentement que si vous aviez fait quelque chose de la manière la plus courante, car cette manière de procéder est plus susceptible d'être optimisée par les compilateurs JIT modernes .

Même en C, il faut être très bon en optimisation pour en savoir plus sur l'optimisation d'une section de code par rapport au compilateur.

Si vous ne connaissez pas ce dont Ulrich Drepper parle dans son excellent document intitulé Ce que tous les programmeurs devraient savoir à propos de la mémoire , vous êtes probablement sur un perdant qui tente même de s’optimiser. Cependant, contrairement au titre du journal (ce qui est en réalité un hommage à la même chose fantastique de David Goldberg. ), Ne pas avoir ce niveau de compréhension ne vous empêche pas nécessairement d'être un bon programmeur, mais simplement une sorte de programmeur.

isset()vs strlen()en PHP

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

Non seulement cela, mais rien ne garantit que ce isset()sera toujours plus efficace, simplement parce que c'est plus efficace maintenant. Une optimisation maintenant ne sera peut-être pas une optimisation l'année prochaine ou dans 10 ans. Les processeurs, systèmes et compilateurs s’améliorent et évoluent avec le temps. Si les performances de PHP strlen()posent problème, il est possible que PHP soit modifié à l'avenir. Il peut alors être nécessaire de supprimer toutes les optimisations de isset () pour optimiser encore une fois le code.

Toute optimisation a le potentiel de devenir une future anti-optimisation , elle doit donc être considérée comme une odeur de code possible, à conserver au minimum.

Un exemple d'expérience personnelle

Comme exemple d’une telle anti-optimisation , j’ai déjà eu à nettoyer une énorme base de code remplie de code de formulaire, if x==0 z=0 else z=x*ycar quelqu'un avait supposé qu’une multiplication à virgule flottante coûterait toujours 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 et très pipeline, les performances étaient horriblement mauvaises. Chacune de ces déclarations provoque un vidage du pipeline. En simplifiant toutes ces lignes de code, z=x*yle programme a dû exécuter un ordre de grandeur plus rapide sur la nouvelle architecture, rétablissant ainsi les pertes de performances dues à l' anti-optimisation .

Les problèmes que nous devons généralement optimiser pour aujourd'hui sont très différents de ceux que nous devions optimiser il y a 20, voire 10 ans.

Ensuite, nous nous inquiétions de faire le plus de travail possible par cycle d'horloge. Nous sommes maintenant davantage préoccupés par les vidages de pipeline, les erreurs de prédiction de branche et les erreurs de cache au niveau du processeur, mais les verrous et la communication interprocessus deviennent de plus en plus importants au fur et à mesure que nous passons au multi- processus et architectures multiprocesseurs. Le papier de Drepper peut vraiment aider à comprendre beaucoup de ces problèmes.


3
Ce que vous voulez éviter, c’est ce que vous voulez éviter: le vidage du pipeline et l’absence de mémoire cache: D mais seulement sur des parties de code qui les excutent très souvent.
deadalnix

7
J'ajouterais que les compilateurs ont parcouru un long chemin et optimiseront beaucoup de choses pour vous. Autant que je sache, ils optimisent mieux le code propre et lisible que le truc épineux.
Becuzz

3
+1 pour avoir fourni un exemple réel de micro-optimisation qui a fait perdre du temps - et révélé que Michael Jackson était un programmeur.
Boz

1
+1 pour l'exemple. Cela illustre parfaitement pourquoi vous devez laisser des transformations triviales au compilateur.
back2dos

1
@Rex Kerr> dans l'exemple, le coût provient du branchement, qui provoque le vidage du pipeline de la CPU. La multiplication en virgule flottante est également coûteuse. Ce qui est plus onéreux dépend fortement de la FPU et de la longueur du pipeline de la CPU exécutant le code. Je ne serais pas surpris que ce code soit plus rapide sur les anciens processeurs dotés d'un pipeline plus court et d'un FPU moins efficace que le processeur actuel.
deadalnix

84
  1. Écrivez un code propre, concis, simple et explicite.
  2. Faites des tests de performance 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 est inutile d’optimiser avant de profiler / évaluer votre code et de voir quels sont les 5% exécutés 95% du temps.

Chaque imbécile peut faire de la micro-optimisation et tout compilateur / run-time décent le fera pour vous.
Optimiser un bon code est trivial. Écrire du code optimisé et essayer de le rendre bon après cela est fastidieux au mieux et insoutenable au pire.

Si vous vous souciez sérieusement des performances, n'utilisez pas PHP pour du code essentiel à la performance. Trouvez les goulots d'étranglement et réécrivez-les avec les extensions C. Même la micro-optimisation de votre code PHP au-delà de l'obscurcissement ne vous donnera pas 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 moyen idéal de procrastination. Il vous permet de fuir les aspects vraiment importants du développement logiciel: la conception de systèmes évolutifs, flexibles, extensibles et robustes.


2
La meilleure réponse à ma question a été trouvée, remarquablement, dans le Guide du développeur de Bugzilla: "Si vous essayez d'être intelligent au lieu d'essayer d'être lisible, vous essayez peut-être de rendre les choses" plus rapides? "Si oui, rappelez-vous : ne résolvez pas un problème avant de savoir qu'il existe. Si vous ne savez pas (par des tests réels et détaillés) que votre code est lent, ne vous inquiétez pas pour le rendre "plus rapide". l'optimisation - de nombreux programmeurs résolvent constamment des problèmes que personne n'a jamais rencontrés. Ne faites pas cela. " bugzilla.org/docs/developer.html#general
Marco

7
Je suis généralement d'accord - sauf pour une ligne, je soutiens que "tous les idiots pensent qu'ils peuvent micro-optimiser" ...;)
Nim

@Nim: Point pris;)
back2dos

26

Je suis d’accord avec votre père: "Si un codeur ne prend pas en compte les performances dans son code, même au niveau micro, il n’est pas un bon programmeur." La clé est de "considérer la performance". Cela n’équivaut pas à "faire des micro-optimisations à chaque étape".

Je suis d'accord avec la plupart des autres commentaires - ce qui était utilisé auparavant pour accélérer les programmes C ne le fait peut-être pas aujourd'hui - mais il y a d'autres choses sérieuses à prendre en compte: Devrais-je utiliser le C ou C ++? Les classes avec des opérateurs simples surchargés peuvent nuire aux performances si vous les utilisez beaucoup. Est-ce important? Cela dépend de votre application, mais si vous ne le considérez 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 ne le considèrent même pas littéralement.

En réalité, 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 du code, et le résultat peut être très différent de celui que vous aviez é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 jeux. Vous avez ignoré l'optimisation de votre système physique et de votre système graphique, car les deux cœurs à 2,5 GHz sont à la base le minimum requis de nos jours et que votre jeu fonctionne correctement. Ensuite, les téléphones intelligents arrivent et vous voulez le porter. Oh, sacrément, un noyau ARM 600 MHz ?

Pensez à un site Web - quelque chose qui a été créé pendant un week-end comme Hot or Not . Vous utilisez la base de données qui vous convient, écrivez tout avec un développement rapide à l’esprit, lancez en envoyant une URL à vos amis. Trois mois plus tard, votre serveur est en train de mourir de surcharge et vous ne pouvez rien faire pour passer à la vitesse supérieure. Cela arrive tout le temps. Les sites Web les plus importants 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 y penser . La plupart des gens ne savent même pas à quel point les performances sont sur la table et la dissimulent avec une petite astuce sur "l'optimisation prématurée" et "ne le fais pas". Ce ne sont pas de bons programmeurs.

Ce n'est pas une opinion populaire sur ces sites. Au revoir les points de réputation ....


3
Bien sûr, vous devriez l’envisager (à l’arrière de votre tête) et généralement le rejeter, sauf s’il est démontré que cela en vaut la peine. Vous devez tenir compte du fait que les optimisations réduisent généralement la lisibilité du code et peuvent multiplier par 10 le temps nécessaire au codage et à la maintenance. Si le programme ne nécessite pas beaucoup de ressources en processeur, il n’est souvent pas nécessaire. Reconnaissez que votre compilateur optimise généralement beaucoup mieux que vous et que nombre de vos optimisations vont en réalité nuire aux performances. Si cela ne vaut pas la peine de tester vos optimisations et votre profil, il ne vaut pas votre temps d'optimiser.
dr jimbob

3
Votre exemple Angry Birds montre exactement pourquoi vous ne devriez pas optimiser prématurément. Lorsque vous effectuez un transfert de poste de travail sur une console ou sur un ou plusieurs appareils mobiles, vous devez gérer au moins trois types de matériel très différents, et l’optimisation d’un matériel peut être préjudiciable au lieu d’aider un autre. Pire encore, l'optimisation va rendre le code plus difficile à comprendre, donc plus difficile à porter. Bien sûr, choisissez dès le départ des algorithmes efficaces, mais économisez la micro-optimisation pour la phase de réglage des performances lorsque les données réelles vous indiqueront où se situe le problème sur chaque plate-forme.
Caleb

@Caleb: l'exemple Angry Birds illustre pourquoi ne pas optimiser un matériel particulier. Il montre également comment créer une application entière sans se soucier de faire des optimisations plus générales "au niveau C", puis de se faire graver. En fait, pas brûlé, mais vous avez du mal à aller au-delà de votre intention initiale.
phkahler

25

Prenons d'abord votre cas: PHP

  • Je ne pense pas que PHP soit un type de langage (à la fois en raison de sa nature et de son domaine d'application principal) dont vous avez besoin pour vous soucier de ces "micro-optimisations". Le code PHP est principalement optimisé avec la mise en cache opcode.
  • Les programmes écrits en PHP ne sont pas liés au processeur, ils sont principalement liés aux E / S , donc ces optimisations ne valent pas votre temps de toute façon.
  • Tout ce que vous DEVEZ optimiser doit probablement être inséré dans une extension C puis chargé dynamiquement dans le runtime de PHP
  • Comme vous pouvez le constater, nous n'obtenons aucune incitation à la micro-optimisation de notre code PHP. Par contre, si vous passez ce temps à rendre le code PHP plus lisible et facile à gérer, cela vous rapportera plus de dividendes.

En général,

Je ne passerais pas beaucoup de temps à optimiser mon code dans un langage dynamique comme Python ou Ruby , car ils ne sont PAS conçus pour des tâches de traitement de données nécessitant beaucoup de temps . Ils résolvent différents types de problèmes pour lesquels la modélisation d'une situation réelle (facile à lire et à gérer) - ce qui s'appelle l' expressivité - est plus importante que la rapidité. Si la vitesse était la préoccupation principale, 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 examiner la nature / domaine / objectif du programme que vous écrivez. Vous devez également peser soigneusement le temps nécessaire à la micro-optimisation par rapport aux avantages de cette optimisation. Si vous avez encore besoin d'optimisation, vous pouvez également envisager une étape supplémentaire et coder ces éléments de code dans l'assembleur.

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

  • Quel genre de chose faites-vous: domaine d'application, complexité?
  • Les améliorations de la vitesse en microsecondes sont-elles VRAIMENT importantes pour votre programme?
  • Quelle optimisation sera la plus rentable? Ce n'est peut-être pas toujours une optimisation de code, mais quelque chose d'extérieur.
  • Combien de "bien" (en termes de rapidité) vous récoltez-vous du temps que vous investissez en micro-optimisation?
  • Peut-on atteindre de meilleures vitesses autrement - en modifiant le matériel, la RAM et le processeur, en exécutant le code en parallèle ou sur un système distribué?

Non seulement la micro-optimisation (l'optimisation de code, d'ailleurs) prend du temps, elle "déforme" la lisibilité naturelle de votre code, le rendant ainsi très lourd en maintenance. Considérez toujours cela comme un dernier recours. Essayez toujours d'optimiser l'ensemble de l'application en adoptant un meilleur matériel et une meilleure architecture que l'optimisation de fichiers de code individuels.


18

Il semble y avoir beaucoup de réponses qui disent que l'optimisation micro est

tout ce qui concerne les compromis - performances, temps, coûts, efforts, lisibilité / maintenabilité, etc.

Mais bon, je sais qu’il ya certaines optimisations pour lesquelles il n’existe aucun impact sur la lisibilité, et j’aime simplement les faire pour le plaisir. J'ai constaté sur certains de mes travaux scolaires (qui étaient tous basés sur la vitesse), qu'il était toujours agréable de considérer l'optimisation micro lors de la rédaction d'énoncés conditionnels tels que:

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

est toujours plus gentil que

if (shouldDoThis() && counter < X ) 

Il y a pas mal de façons d '"accélérer" votre code comme ça et la différence est généralement négligeable (pas toujours), mais je me sentirais mieux si je l'écrivais comme ça.

Je ne sais pas si quelqu'un considère cela comme une optimisation, mais je pense qu'un programmeur devrait savoir et tenir compte de ces choses lorsqu'il écrit son code.


2
Ce n'est peut-être pas important pour ce cas particulier . Cependant , je pense qu'il est très important d'être en mesure de reconnaître des optimisations comme celles - ci de sorte que quand il fait la matière, vous ne devez pas passer le profilage de temps inutile et optimiser après le fait.
tskuzzy

4
C'est un exemple très dangereux . Une optimisation ne devrait jamais changer de comportement . Même en suggérant que cela cheap() && expensive()soit une optimisation des expensive () && cheap()invite les gens à substituer aveuglément l’une à l’autre sans tenir compte du changement sémantique important qu’elle crée (dans les langues où &&est l’opérateur de court-circuit).
Mark Booth

5
Si les fonctions n'ont pas d'effets secondaires, elles sont équivalentes et l'une est plus rapide. S'ils ont des effets secondaires, on ne devrait pas écrire le code comme celui-ci en premier lieu. Je dirais même que cela devrait être fait par habitude - à moins que cela ne change réellement le comportement.
Phkahler

3
@ MarkBooth Je suis d'accord avec phkahler ici, aucune de ces fonctions ne devrait avoir d'effets secondaires! L'ordre des condionos dans une déclaration if ne doit pas avoir d'effet sur le résultat du programme. Mon exemple serait mieux écrit comme if (x<100 && isPrime(x)), juste pour le rendre plus clair.
zidarsk8

1
@ zidarsk8 - Si une optimisation modifie autre chose que la vitesse d'exécution, il ne s'agit pas d'une optimisation . En tant que programmeurs, nous devons souvent être pragmatiques . Parfois, cela signifie que nous ne pouvons pas garantir que toutes les fonctions utilisées avec un opérateur de court-circuit sont pures - en particulier lorsque notre code appelle des bibliothèques tierces sur lesquelles nous n’avons aucun contrôle. Dans cette situation, vous devez veiller à ce que les programmeurs inexpérimentés ne soient pas encouragés à introduire des bogues au nom de l' optimisation .
Mark Booth

11

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 du SQL en ligne. Chez moi, nous sommes sur SQL Server 2000 . 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 représente plusieurs milliers de dollars.
  • Vendre des développeurs sur l'idée d'apprendre de nouvelles technologies.

Je sais d'expérience que cela ne va pas arriver. Donc, je pouvais arrêter de fumer, ne pas trop stresser ou ne pas suivre les meilleures pratiques.

Des considérations politiques, techniques et monétaires sous-tendant les décisions ont une incidence sur le résultat global. Rappelez-vous ce fait lorsque vous prenez une décision et choisissez judicieusement vos batailles.

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


1
En passant, vous pouvez utiliser Dapper comme une alternative micro-ORM au SQL intégré.
Dan

2
LINQ and Entity Framework should be used in lieu of inline SQL- Jusqu'à ce que vous ayez réellement besoin de SQL intégré pour optimiser quelque chose; le SQL que EF produit n'est pas toujours optimal.
Robert Harvey

1
FWIW, si votre patron est inquiet au sujet des frais de licence de 2K8 SQL (ou tout autre chose peut être en cours), vous devez RELEVÉ qu'il est assez vieux pour être à venir, sur EOL très bientôt (si ce n'est pas déjà)
warren

@ Warren - Certaines entreprises ne tiennent pas compte de telles choses. Pour certains, si cela fonctionne toujours, ils ne seront pas mis à niveau. Par travail, je veux dire que le serveur fonctionne toujours. Nous constatons déjà un manque de soutien avec EF. Ce n'est tout simplement pas suffisant pour les convaincre de dépenser de l'argent.
P.Brian.Mackey

1
Pour votre information, vous pouvez utiliser EF avec SQL 2000. Le concepteur ne fonctionne pas, mais le framework d’entités actuel prend en charge SQL 2000. Pour contourner les limites du concepteur, vous pouvez créer une base de données locale dans SQL 2008 Express avec le même schéma. en tant que base de données SQL 2000, indiquez au concepteur de générer toutes les classes, puis accédez au fichier .edmx, modifiez la version de la base de données cible en 2000 et pointez la chaîne de connexion sur votre base de données SQL Server 2000. Ce n'est pas la meilleure solution, mais si vous ne pouvez pas mettre à niveau, cela fonctionne.
Neil

8

C'est toujours un compromis.

Premièrement, l’industrie informatique est une question d’argent à la fin. Ce que vous devez faire en tant que développeur, c'est générer de la valeur pour le client afin d’obtenir de l’argent (c’est une simplification à outrance, mais le point principal est ici).

Le temps de développement 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 les développeurs puissent passer le plus clair de leur temps à générer de la valeur.

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

Deuxièmement, la micro-optimisation dans un grand projet peut rendre de plus en plus difficile la maintenance / l'évolution. Le problème, c’est que lorsqu’elles évoluent, une autre optimisation peut maintenant être impossible à faire. Avec une application en évolution, vous obtiendrez généralement une solution plus lente que celle que vous auriez eue sans ces optimisations.

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

Parfois, la valeur réside dans cette optimisation (pensez aux programmes critiques en matière 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 majeure partie du temps dans une portion limitée de code. Quelle que soit la micro-optimisation que vous fassiez, vos programmes ne seront jamais aussi rapidement accélérés sans identifier le goulot d'étranglement et travailler sur cette partie.

Poser votre question comme vous l'avez montré montre que vous n'avez pas comparé le problème à un programme réel. Dans ce cas, vous pourriez avoir fait le tour et remarqué si c'était plus rapide ou pas. Donc, vous demandiez cela avant d'avoir un problème. C'est là que se trouve le problème. Vous avez mal géré le problème de l'optimisation.

Comme la maintenance et l'évolution ont généralement plus de valeur que la micro-optimisation, assurez-vous de disposer de la bonne interface avant de vous lancer. Ensuite, si certaines parties de votre programme sont suffisamment abstraites l’une pour l’autre, vous pouvez en optimiser un sans en déranger tout. Cela nécessite que votre interface fonctionne suffisamment longtemps pour être approuvée.


"Il y a toujours un compromis". Certes, réduire une variable augmentera l’autre, si le programme est sur la courbe des compromis . D'après mon expérience, la plupart des programmes sont loin de la courbe des compromis et laissent beaucoup de marge pour réduire les deux variables.
Mike Dunlavey

La maintenance +1 et l'évolution ont plus de valeur que la micro-optimisation. Bien que je sois sûr que l’industrie informatique ne se limite pas à l’argent? Par exemple, l'open source, l'éducation, l'innovation, la gouvernance, la communauté, etc. Je suis sûr que l'argent peut être trouvé à la base, mais c'est vrai pour la plupart des choses.
Boz

@ Boz kay> Ceci est partiellement vrai. D'abord parce que votre patron et votre client ignorent la plupart des choses et se soucient de l'argent. Si vous souhaitez promouvoir des outils open source, vous devez leur dire comment cela améliorera la marque de l'entreprise ou comment cela réduira les coûts de développement. De plus, rendre les développeurs heureux est un moyen d'obtenir un bon développement dans votre entreprise. Un bon développeur gagne de l’argent (principalement par qualité et innovation). À la fin, l'argent est la clé. Et je vous écris que de mon ordinateur linux un grand partisan du logiciel libre. La même chose vaut pour l'éducation.
deadalnix

8

La performance est une caractéristique

L'article de Jeff Atwood est excellent sur la création d'un site Web performant et sur 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 présentaient des problèmes de haut niveau (couche de service Web inutile, conception de base de données médiocre, architectures excessivement compliquées) qui non seulement nuisaient aux performances, mais étaient profondément enracinés et difficiles à corriger.

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 causer des problèmes de performances que votre code côté serveur. Comme quoi que ce soit, si vous avez des problèmes de performances, vous saurez mieux, profilez encore mieux votre code et vous pourrez le retrouver rapidement.


7

Le temps de développement coûte plus cher que le temps d’ordinateur. 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. Consacrez suffisamment de temps pour vous assurer que vous utilisez le bon algorithme .
  • Assurez-vous que vous posez la bonne question, ce select (select count(*) from foo) >= 1n'est pas la même chose que select exists(select 1 from foo).
  • certains idiomes de langue sont populaires simplement parce qu'ils sont plus rapides. Il est correct de les utiliser, car la plupart des utilisateurs de cette langue les maîtriseront. (votre exemple est un bon exemple).

7

Que voulez-vous optimiser?

  • Performance du logiciel?
  • Fiabilité?
  • Productivité du programmeur?
  • Satisfaction du client?
  • Efficacité énergétique?
  • Maintenabilité?
  • Temps de marché?
  • Coût?

"Optimiser" ne signifie pas toujours que le code soit exécuté aussi rapidement que possible. Il est parfois important de trouver le moyen le plus rapide et absolu de faire quelque chose, mais ce n'est pas vraiment 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 aucune différence entre les deux en code qui ne s'exécutera qu'occasionnellement. Voici un exemple:

Si vous devez continuellement mettre à jour un affichage de la longueur de la saisie 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 de touche consécutives, peu importe la routine. tu utilises. D'autre part, si vous devez déterminer la longueur d'un milliard de chaînes, vous devrez probablement porter une attention particulière aux différences de performances entre différentes routines. Dans le premier cas, vous préférerez peut-être écrire un code facile à comprendre et à vérifier; dans le second cas, vous pourriez être prêt à échanger votre lisibilité pour gagner du temps.

Dans tous les cas, si vous souhaitez optimiser votre code, vous devez le profiler avant et après les modifications que vous apportez. Les programmes actuels sont suffisamment compliqués pour qu'il soit souvent difficile de déterminer les goulots d'étranglement; Le profilage vous aide à optimiser le bon code , puis à montrer que les optimisations que vous avez effectuées ont réellement fonctionné.

Vous n'avez pas dit quand votre père a pris sa retraite ni quel genre de programmation il a faite, mais sa réaction n'est pas surprenante. Historiquement, la mémoire, le stockage secondaire et le temps de calcul étaient coûteux et parfois très coûteux. Ces jours-ci, toutes ces choses sont devenues très bon marché par rapport au temps des programmeurs. Dans le même temps, les processeurs et les compilateurs sont devenus capables d’optimiser le code de manière que les programmeurs ne puissent jamais égaler. Les jours où les programmeurs utilisent de petites astuces pour réduire quelques instructions de machine ici et là sont pour la plupart révolues.


1
+1 Sans oublier que ces dernières années, les appareils mobiles sont redevenus très dépendants de l'optimisation du code. Quelqu'un qui n'écrit pas du code optimisé ou du moins estime que cela pourrait avoir du mal à faire en sorte que son application gourmande en ressources processeur s'exécute sans heurts sur un appareil mobile.
Styler

+1 ressemble beaucoup à votre liste d’optimisations possibles. Il a utilisé assembly / fortran
Boz

@ Styler: il ne faudra pas longtemps avant que les appareils mobiles disposent d'un processeur quad core avec une Go de mémoire, nous avons déjà des smartphones dual core.
Lie Ryan

@Lie Ryan: oui c'est vrai, mais comme la plupart des pionniers, ils devaient voyager dans des bateaux en bois;)
Styler

7

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

CEPENDANT , un programmeur doit é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 dans une boucle. Stockez la valeur dans une variable en dehors de la boucle et utilisez-la. Ne faites pas des choses comme les comparaisons de chaînes ou les expressions rationnelles dans une fonction souvent appelée, lorsque vous pouvez monter d'un niveau, faire la comparaison et en faire un entier, 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.


Réalisé que je devais être plus clair dans ma question, je disais vraiment la même chose - je l'ai mise à jour.
Boz

7

Lorsque vous décidez quoi optimiser, souvenez-vous toujours de la loi d'Amdahl . Voir le lien pour des maths précises; la phrase à retenir est la suivante:

Si une partie de votre programme représente 10% de son temps d'exécution et que vous optimisez le temps d'exécution de cette partie deux fois plus vite, le programme dans son ensemble ne fera qu'accélérer de 5%.

C'est pourquoi les gens disent toujours qu'il ne vaut pas la peine d'optimiser les parties de votre programme qui n'occupent pas plus de quelques pour cent de la durée totale d'exécution. Mais ce n'est qu'un cas particulier d'un principe plus général. La loi d'Amdahl vous dit que si vous devez faire en sorte que le programme fonctionne deux fois plus vite, vous devez accélérer chaque élément de 50% en moyenne. Il vous indique que si vous devez traiter vingt gigaoctets de données, il n'y a que deux façons de le rendre plus rapide que le temps nécessaire pour lire vingt gigaoctets sur le disque: obtenez un disque plus rapide ou réduisez la taille des données.

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


1
+1 pour la citation d'Amdahl, mais je ne suis pas d'accord avec "pour que tout le programme se répète deux fois plus vite, il faut accélérer chaque étape". Je dirais que vous n'accélérez en fait aucun "morceau". Au contraire, vous trouvez du travail inutile et l'éliminez. Surtout les appels de fonction, si le programme est plus gros qu'un jouet. Une grande partie de la réflexion commune sur les performances semble complètement ignorer l'importance de trouver des branches entières superflues de l'arbre des appels (qui peuvent être des instructions uniques) et de les supprimer.
Mike Dunlavey

Le diable est dans le mot "moyenne" là-bas. Il est mathématiquement vrai que pour accélérer un programme de 50%, chaque élément doit être accéléré de 50% en moyenne . Maintenant, si vous pouvez diviser le programme en un travail prenant 75% du temps d’exécution et un autre 25%, et accélérer l’ancien jusqu’à 3 fois, cela vous donnera 50% au total bien que vous n’ayez rien fait. Mais le cas le plus courant est qu’il existe des dizaines d’emplois représentant chacun moins de 5% de la durée d’exécution. Il faut ensuite accélérer ou supprimer beaucoup d’entre eux.
dimanche

Je pense qu'il y a un cas encore plus commun. Un "travail" prend 50% du temps, mais vous n'en avez pas réellement besoin , vous le supprimez donc complètement, ce qui réduit le temps total de ce temps, puis vous répétez. Je sais que c'est difficile à accepter - que les programmes peuvent passer beaucoup de temps à faire des choses qui (avec le recul) sont totalement inutiles. Mais voici mon exemple canonique .
Mike Dunlavey

6

Cela dépend de votre stade de développement. Lorsque vous commencez à écrire, les micro-optimisations ne doivent pas être prises en compte, car vous obtiendrez plus de gains de performances en utilisant de bons algorithmes que de micro-optimisations. En outre, réfléchissez à ce que vous développez, car les applications sensibles au facteur temps bénéficieront davantage des considérations d'optimisation micro que les applications d'entreprise génériques.

Si vous testez et développez des logiciels, les micro-optimisations vous blesseront probablement, elles tendent à 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 l'être.

Si vous recevez en fait des plaintes d'utilisateurs au sujet du code lent, elles pourraient valoir la peine d'être examinées, mais uniquement si tout le reste a été résolu, à savoir:

  • Le code est-il bien écrit?
  • L'application est-elle capable d'accéder à ses données sans aucun problème?
  • Peut-on utiliser un meilleur algorithme?

Si toutes ces questions ont été résolues et que vous rencontrez toujours des problèmes de performances, alors il serait peut-être temps de commencer à utiliser des micro-optimisations dans le code, mais il est fort probable que d'autres modifications (par exemple, un meilleur code, un meilleur algorithme, etc.) plus d'un gain de performance qu'une volonté de micro-optimisation.


5

La rapidité 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 pour pouvoir être conservé. Le seul moment où la lisibilité peut être compromise, c'est lorsque la vitesse est une exigence essentielle. L’obligation de rendre le code plus rapide que ne le permettent totalement la lisibilité / la maintenabilité n’est pratiquement jamais applicable, mais dans certains cas, cela sera le cas. La principale chose à retenir est que le code micro-optimisé est souvent du code hacky. Par conséquent, à moins d’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 des durées d'exécution de 0,5 seconde et 1 seconde dans les opérations CRUD. Vous n'avez donc pas besoin de participer à une assemblée-interop-hackfest pour en arriver à cette seconde. Oui, je pourrais piloter un hélicoptère au travail 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 optimisez inutilement le code, c'est exactement ce que vous faites: ajouter une complexité et des coûts inutiles pour atteindre un objectif superflu.


5

La micro-optimisation est importante lorsque vous frappez une contrainte. Ce qui compte pour vous peut être la mémoire, le débit, la latence ou la consommation électrique. Notez qu'il s'agit de caractéristiques au niveau du système. vous n'avez pas besoin (et ne pouvez pas) optimiser chaque fonction de toutes les manières.

Les systèmes embarqués auront probablement plus besoin de la micro-optimisation, car les contraintes sont plus facilement impactées. Cependant, même là, la micro-optimisation ne vous mène que jusque-là; vous ne pouvez pas micro-optimiser votre sortie d'un mauvais design. Le point sur la bonne conception d’un système est qu’il est possible de raisonner sur le système dans son ensemble. Les composants nécessitant une micro-optimisation doivent être clairement exposés et optimisés de manière à ne pas compromettre la conception du système.

Notez qu’aujourd’hui, les petits systèmes «intégrés» peuvent être assez proches du Vaxen ou du PDP-11 d’aujourd’hui. Ces problèmes étaient donc plus courants. Sur un système moderne polyvalent faisant appel à l'informatique commerciale générale moderne, la micro-optimisation est rare. Cela fait probablement partie des raisons pour lesquelles votre père adopte la position qu'il adopte.

Cependant, peu importe si vous avez 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.

Voici un exemple d'une question récente à laquelle j'ai répondu sur Stack Overflow pour un cas dans lequel une micro-optimisation était nécessaire: des encodeurs vidéo open source pour un système intégré .


4

Le principal problème de la micro-optimisation est qu’elle vous oblige à écrire un code plus difficile à gérer.

Un autre problème est que, selon la configuration de votre ordinateur, votre micro-optimisation peut parfois présenter de plus mauvaises performances que sans «optimisation».

Faire beaucoup de micro-optimisation vous prendra beaucoup de temps à lutter contre quelque chose qui ne compte pas vraiment.

Une meilleure approche consiste à créer un code plus propre, plus facile à gérer, et si vous rencontrez des problèmes de performances, vous créez un profil pour déterminer ce qui ralentit vraiment 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

Si vous commencez à vous soucier des millisecondes, vous devriez envisager d'abandonner PHP et d'utiliser plutôt C ou Assembly. Non pas que je veuille faire cela, cela n’a aucun sens de discuter de tels nombres et d’utiliser un langage de script. Votre code itère-t-il souvent avec cette commande?

Les facteurs environnementaux sont hors de question ici, ces serveurs fonctionnent quand même 24 heures sur 24, 7 jours sur 7, et s’ils traitent réellement quelque chose, cela n’aura d’importance que s’il s’agit d’une tâche très longue.

Très probablement, la lumière dans votre bureau et l'énergie utilisée par nos ordinateurs pendant que nous tapions tous les questions et réponses utilisaient beaucoup plus d'énergie que toute optimisation que vous pouvez raisonnablement appliquer à vos applications.


+1 éteindre la lumière ou ne pas répondre aux questions.
Boz

4

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

ALORS, si les chiffres de profilage montrent que votre choix du meilleur algorithme simple n’était pas suffisant, vous pouvez lancer l’optimisation (qui correspond généralement au coût de la lisibilité).


BubbleSort peut en réalité être meilleur que quicksort ou mergesort lorsque vos données sont presque triées avec seulement quelques éléments parasites qui ne sont pas trop éloignés de leur destination finale. Pour toutes les autres tâches, vous devez utiliser la fonction de tri intégrée fournie par votre langage de programmation. c'est le moyen le plus simple de commencer (et la fonction de tri intégrée dans la plupart des langues offre de bonnes performances). MAUVAIS CONSEIL:, start out with bad runtime characteristicne commencez pas délibérément avec une mauvaise caractéristique d'exécution.
Lie Ryan

@Lie, si vous SAVEZ que vos données sont presque triées et que, par conséquent, vous pouvez utiliser Bubblesort, vous ne choisissez pas exactement votre algorithme à l' aveuglette ... Merci également d'avoir signalé cette faute de frappe.

4

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'emballiez à la main avec une puce en tête, l'optimisation vous apportera toujours quelque chose à gagner. Cependant, à moins que vous VOULEZ réaliser un assemblage à la main pour tout ce que vous faites, vous devez définir un objectif quantitatif. Lorsque vous vous rencontrez, vous dites "c'est assez" et arrêtez l'optimisation, même s'il reste encore une performance éblouissante à regarder. vous en face.

Un code beau, élégant et extrêmement performant est inutile s'il ne fonctionne pas (et par "travail", je veux dire le résultat attendu compte tenu de tous les apports attendus). 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, le cas échéant, recherchez les moyens de l'améliorer, jusqu'au point où elles sont suffisamment performantes.

Il y a certaines choses que vous devez décider dès le départ qui auront une incidence sur les performances; décisions très basiques telles que la langue / le runtime que vous utiliserez pour implémenter cette solution. Nombre de ces problèmes auront davantage d’impacts sur les performances que d’appeler une méthode plutôt qu’une autre. Honnêtement, PHP, en tant que langage scripté, est déjà un succès en termes de performances, mais comme très peu de sites scriptés sont construits à partir de la base en C / C ++, ils sont comparables à 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 killer de performances. Optimiser ce que vous lisez et écrivez sur le disque dur, les ports série, les canaux réseau, etc. améliorera généralement l'exécution du programme de plusieurs ordres de grandeur, même si les algorithmes à l'origine des opérations d'E / S étaient efficaces. Après cela, réduisez la complexité de Big-O de l’algorithme lui-même, puis si vous le devez absolument, vous pouvez «optimiser» en choisissant des appels de méthode moins coûteux et en prenant d’autres décisions ésotériques à bas niveau.


2
+1 Produire du code qui fonctionne devrait TOUJOURS être la première priorité.
Boz

2
@ Keith, en fait, Knuth l'a dit en premier, et il en a dit un peu plus que cela.

"Faites-le fonctionner, puis faites-le fonctionner aussi vite que nécessaire", Anon.
John Saunders

1
En fait, la religion est la racine de tout le mal, mais je m'éloigne du sujet.
Thomas Eding

4

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 la performance. Je me souviens d’avoir étudié une activité de la US Navy dans laquelle leur ordinateur central était limité à 64 Ko de mémoire par utilisateur. Dans ce monde de programmation, vous devez chercher chaque fois que vous le pouvez.

Les choses sont très différentes maintenant et la plupart des programmeurs n'ont pas à se préoccuper autant de la micro-optimisation. Cependant, les programmeurs de systèmes intégrés et les utilisateurs de bases de données doivent encore beaucoup utiliser du code optimisé.


3

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 code peut toujours être changé pour être plus rapide plus tard, s'il peut être compris - mais bonne chance, changez-le pour qu'il soit clair s'il est rapide.


3

C'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 est probablement une mauvaise idée.

Personnellement, j’adopte une double approche: vous pouvez faire des micro-optimisations qui n’affecteront pas la lisibilité et vous voudrez bien sûr les utiliser. Mais si cela affecte la lisibilité, attendez, vous n’obtiendrez pas beaucoup d’avantages et le processus de débogage à long terme risque de prendre plus de temps.


2
Quelques points mineurs sur votre exemple: une fonction dans un moniteur de fréquence cardiaque qui prend 25 ms ne poserait pas de problème aussi longtemps que d’autres tâches nécessaires pourraient être exécutées avec le temps de réponse requis. Les interruptions sont bonnes pour cela. Et une latence de 25 ms pour un élément qui ne fait que surveiller des événements réels pour mettre à jour un affichage destiné à la consommation humaine ne pose probablement pas de problème.
Janm

3

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 que, par conséquent, l'optimisation de l'exécution peut ne pas fonctionner aussi bien que 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. Un élément à prendre en compte est la diversité du matériel. À quel point est-il réaliste d'optimiser le code pour des puces spécifiques telles qu'un processeur ou un processeur graphique lorsqu'un nouveau modèle sortira probablement dans moins d'un an?

Une autre question à prendre en compte ici concerne les performances mesurées par la métrique: vitesse d’exécution, mémoire utilisée, vitesse de développement de nouvelles fonctionnalités, taille de la base de code sur un serveur sous forme compilée ou décompilée, évolutivité, maintenabilité, etc. . Si elle est prise au sens large, la question devient triviale, mais je ne suis pas sûre de savoir dans quelle mesure vous entendiez par performance le fait que cela puisse être presque n'importe quoi pourvu que cela puisse être mesuré d'une manière ou d'une autre.


Certaines micro-optimisations peuvent fonctionner et d'autres ne fonctionnent pas. C'est pourquoi on peut se demander à quel point il est intéressant de réaliser un tel travail par rapport à d'autres travaux pouvant être considérés comme prioritaires, telles que les nouvelles fonctionnalités ou la correction de bugs. L'autre question serait de savoir si une mise à niveau de matériel ou de logiciel pourrait également casser certaines de ces optimisations.


1
Notez que vous pouvez absolument faire des micro-optimisations sur des plateformes telles que JVM et .NET, elles prennent simplement des formes légèrement différentes. Mais la même chose est vraie si vous comparez un vieux compilateur C simple avec un compilateur plus moderne et hautement optimisateur: les optimisations que l'utilisateur peut faire seront différentes.
Joachim Sauer

1

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

S'il existe deux façons de faire la même tâche, l'une étant plus rapide que l'autre et offrant la même lisibilité, vous devriez 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 la documenter est simple: 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 leur utilisation n’a toujours pas cette performance, vous pouvez envisager de la 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 et d’argent en optimisant vos achats en achetant du matériel.


1

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 sans sens :

Comme la plupart d'entre nous, je suis fatiguée de lire des articles de blog sur les micro-optimisations non sensées, telles que le remplacement de print par echo, ++ $ i par $ i ++ ou les guillemets doubles par des guillemets simples. Pourquoi? Comme 99,999999% du temps, cela n'a aucune importance. Pourquoi? Parce que 99,99% du temps, vous feriez mieux d'installer un accélérateur PHP comme APC, d'ajouter ces index manquants dans les colonnes de votre base de données ou d'éviter les 1 000 demandes de base de données que vous avez sur la page d'accueil.

print utilise un autre opcode car il renvoie en réalité quelque chose. Nous pouvons en conclure que l'écho est plus rapide que l'impression. Mais un code d'opération ne coûte rien, vraiment rien.

J'ai essayé une nouvelle installation de WordPress. Le script s'arrête avant qu'il ne se termine avec 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 enregistre une opération parmi des millions, mais rend la lisibilité plus difficile.


1

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

Je vais expliquer. Une mauvaise optimisation (optimisation prématurée / micro de lecture) n’est pas le cas lorsque vous optimisez des sections de code sans profilage pour savoir s’il s’agit vraiment de goulots d’étranglement. C'est lorsque vous optimisez en fonction de vos hypothèses, de vos auditions et de vos comportements non documentés. Si elle est documentée et fait quelque chose d'une manière plus efficace / logique , aussi petite soit-elle, je l'appelle une bonne optimisation . Comme d’autres l’ont dit, ces deux services n’ont contre et presque aucun avantage en ce qui concerne les bonnes affaires, mais je fais tout de même le dernier, pas le premier, si cela ne nuit pas totalement à la lisibilité. Oui, la lisibilité / la maintenabilité est de la plus haute importance et concerne le point de départ de la ligne.

Je réitère les points soulevés par d’autres ici comme la futilité des bonnes et des mauvaises optimisations:

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

  2. Généralement, le goulet d'étranglement réel de votre application (considéré comme une différence mesurable) pourrait représenter 5% de votre code (principalement les codes SQL) et l'optimisation des 95% restants n'apporte aucun avantage à vos clients.

  3. Habituellement, un code "techniquement" plus performant signifie plus de verbosité, ce qui signifie plus de code sujet aux erreurs, ce qui signifie une maintenabilité plus difficile et plus de temps, ce qui signifie que vous gagnez moins.

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

Les inconvénients de la mauvaise optimisation sont notamment:

  1. Cela ne vous donne pas souvent la performance que vous attendez. Voir cette question sur SO, où les optimisations ont mal tourné . En fait, cela peut avoir des effets indésirables. C'est le problème du comportement non documenté.

  2. Les compilateurs principalement modernes le feront pour vous de toute façon.

Je vais donner quelques exemples d'optimisation mauvaise et bonne:

Le mauvais -

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

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

  3. forau 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. utiliser à la charplace de chaîne lors de la concaténation de chaîne, comme:

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

The good (from .NET world. 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 l'ordre 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 cela présente des avantages notables en termes de performances, je dirais non. Mais je suggérerais qu'on devrait les utiliser parce que cela découle d'une compréhension du comportement de ces constructions. Pourquoi faire deux appels alors que vous ne pouvez en faire qu'un? D'un point de vue philosophique, c'est une bonne pratique de codage. Et 1 & 3 sont également un peu moins lisibles au sens strict, mais ont-ils une valeur supérieure à la lisibilité? Non, pas beaucoup, alors je l'utilise. C’est la clé: maintenir un rapport performance / lisibilité décent. Et quand c'est ça, c'est à propos de l'endroit où vous tracez la ligne.


1

"Worth it" a besoin d'un contexte, comme la simplicité d'écriture, de lecture et de maintenance par rapport à la rapidité avec laquelle il rend quelque chose nettement plus réactif à l' utilisateur, plus interactif et nécessitant moins de temps d'attente.

Économiser quelques sous pour acheter une canette de soda ne me fera pas grand bien si je dois parcourir une certaine distance pour les économiser, d'autant plus que je bois rarement de soda de nos jours. Économiser quelques centimes par canette à l’achat d’un million de canettes de sodas pourrait être une grosse affaire.

En attendant, économiser quelques centimes quand deux personnes sont à côté de moi et que l'une offre exactement la même chose pour quelques centimes moins cher et l'autre pas, et j'ai choisi la plus chère parce que j'aime mieux que leur chapeau ressemble à un cas insensé de pessimisation.

Ce que je trouve souvent chez les gens qui appellent "micro-optimisations" semble être curieusement dépourvu de mesures, de contexte et de discussions entre utilisateurs, alors qu'il devrait être impératif que tous les trois envisagent de telles optimisations si elles ne sont pas faciles à appliquer. Pour moi, une micro-optimisation appropriée de nos jours concerne des choses telles que la disposition de la mémoire et les modèles d'accès, et bien qu'elles puissent sembler "micro" focalisées, elles ne le sont pas.

Il n’ya pas si longtemps, j’ai réussi à réduire une opération de 24 secondes à 25 millisecondes (environ 960 fois plus rapide), avec des sorties identiques (sécurisées par des tests automatisés), sans modification de la complexité algorithmique, pour le skinning par diffusion de chaleur volumétrique, à travers des "micro-optimisations" (dont la plus importante a été causée par une modification de la structure de la mémoire qui a réduit le délai à environ 2 secondes, puis les autres tâches ont consisté à SIMD, à une analyse plus poussée des erreurs de cache dans VTune et à un réaménagement de la disposition de la mémoire).

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

Mon implémentation a réussi à être capable de le faire en millisecondes alors qu'il luttait pour le réduire à moins d'une minute: entrez la description de l'image ici

Après avoir «optimisé micro» le temps passé de 24 secondes à 25 ms, cela a changé la donne en termes de flux de travail. Désormais, les artistes peuvent changer de plate-forme en temps réel à plus de 30 images par seconde sans attendre 24 secondes à chaque fois qu’ils modifient légèrement leur plate-forme. Et cela a en fait changé la conception de mon logiciel puisque je n'avais plus besoin de barre de progression et que des choses de ce genre étaient devenues interactives. Donc, cela pourrait être une "micro-optimisation" dans le sens où toutes les améliorations ont été apportées sans aucune amélioration de la complexité algorithmique, mais c'était plutôt une "méga-optimisation" qui a rendu ce qui était auparavant un processus douloureux et non interactif en temps réel et interactif, ce qui a complètement changé le mode de travail des utilisateurs.

Mesure, besoins de l'utilisateur, contexte

J'ai vraiment aimé le commentaire de Robert ici et peut-être que j'ai échoué à faire le point que je voulais:

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

C’est, même si je travaille dans un domaine très critique en termes de performances avec des exigences souvent en temps réel, le seul moment où je considère toute micro-optimisation qui nécessite de sortir de mon chemin.

Et j'insisterais non seulement sur les mesures, mais sur le côté utilisateur. Je suis curieux de savoir que je suis arrivé dans mon domaine actuel (et anciennement gamedev) en tant qu'utilisateur / fan, puis développeur. Je n’ai donc jamais été aussi enthousiasmé par les choses habituelles qui excitent les programmeurs comme résoudre des énigmes techniques; Je les ai trouvés un fardeau, mais je les supporterais à travers le rêve utilisateur que je partageais avec d'autres utilisateurs. Mais cela m'a aidé à m'assurer que si j'optimisais quelque chose, cela aurait un impact réel sur les utilisateurs avec des avantages réels. C'est ma protection contre la micro-optimisation sans but.

C’est aussi important que le profileur à mon avis, car j’avais des collègues qui micro-optimisent la subdivision d’un cube en un milliard de facettes uniquement pour s’étouffer avec des modèles de production réels tels que des personnages et des véhicules. Leur résultat était impressionnant au sens de "démo technologique", mais presque inutile pour les utilisateurs réels, car ils profilaient, mesuraient et comparaient les cas qui ne correspondaient pas aux cas d'utilisation réels. Il est donc primordial de comprendre en premier lieu ce qui est important pour les utilisateurs, soit en apprenant à penser et à utiliser le logiciel comme un logiciel, soit en collaborant avec eux (idéalement, les deux, au moins, en leur collaborant).


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

1
@RobertHarvey C'était un peu le point que j'espérais faire, puisque ce que certains appellent « micro-optimisation » est pas nécessairement microscopique en effet, mais il est aussi dépendant du contexte, des mesures, etc. par issetrapport strlensemble plus miniscule mise au point sans le contexte et les mesures. :-D
Dragon Energy

1
@ RobertHarvey J'espérais pouvoir dire, peut-être même indirectement, que s'il existe un contexte négatif pour les "micro-optimisations", c'est le type qui a tendance à être dépourvu de ces mesures, contextes et besoins des utilisateurs finaux. Je pourrais aussi parler du dernier cas, car un de mes collègues a optimisé quelque chose de cool, sauf que personne ne l’a utilisé. Je pense même que l'optimisation correcte nécessite une certaine compréhension de la part de l'utilisateur, sinon nous pourrions profiler et ajuster des choses qui ne les intéressent pas.
Dragon Energy

1
Certaines optimisations sont motivées par des besoins impérieux, d'autres par curiosité (poursuite intellectuelle et aventurisme). Nous avons besoin des deux. Dans le récit de Dragon Energy, il ne s'agissait probablement pas d'un "besoin urgent", les artistes ne s'étant apparemment pas plaints de ne voir aucun résultat de rendu avant 24 secondes après chaque montage. En fait, les utilisateurs pourraient ne pas savoir à quelle vitesse cela aurait pu être, jusqu'à ce qu'un programmeur investisse dans tous ses efforts pour battre le record de vitesse. Se limiter à une demande motivée a du sens sur le plan commercial, mais cela va rater des opportunités d’optimisation étonnantes ou des facteurs décisifs.
Rwong

1
Parlant de bon sens des affaires, il y a aussi la question de la monétisation. Chaque déménagement (par exemple, un programmeur travaillant sur l'optimisation des performances) coûte de l'argent, et le coût doit être recouvré afin de rendre les affaires plus rationnelles. Ainsi, il faut se demander si l’amélioration de la vitesse qui change le jeu peut être «vendue» ou le montant «économisé» si le programmeur doit obtenir l’approbation d’un chef d’entreprise.
Rwong

0

Je vais le dire ainsi: 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 que A prend 100 millisecondes à compléter et que B prend 2 microsecondes, et que vous continuez d’optimiser la fonction B. C’est non seulement non important, mais il est tout à fait faux. Mais l'optimisation de la fonction B s'appelle optimisation et non micro-optimisation. L'importance de l'optimisation dépend. Supposons que vous n’ayez plus rien à faire et que votre programme soit exempt de bogues, alors oui, c’est important. Mais généralement, vous avez des priorités. Supposons que vous deviez ajouter / écrire la fonction C. Si vous pensez que l'écriture de la fonction C vous rapportera plus d'argent que de rendre votre programme plus rapide sans cette fonctionnalité, optez pour l'optimisation. Sinon poursuivre la fonctionnalité. Aussi, les programmeurs expérimentés qui se concentrent sur les performances ne passent pas beaucoup de temps à optimiser, ils écrivent simplement des programmes rapides. Au moins, ils savent quels outils utiliser et quoi faire pour ne pas passer des années à optimiser (lire des micro) optimisations.


Cet article est plutôt difficile à lire (mur de texte). Pourriez - vous l' esprit modifier ing dans une meilleure forme?
Gnat
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.