Qu'est-ce que les programmeurs «micro-optimisent» aujourd'hui? [fermé]

14

À l'époque des «bons vieux jours», lorsque nous copions des logiciels partagés sur des disquettes pour des amis, nous avons également utilisé un peu d'assemblage. Il y avait une pratique courante de «micro-optimisation», où vous regardiez et regardiez les lignes d'assemblage jusqu'à ce que vous trouviez un moyen de l'exprimer dans une instruction de moins. Il y avait même un dicton, qui était mathématiquement impossible, que " Vous pouvez toujours supprimer une instruction de plus. " Étant donné que la modification des performances d'exécution par de petits facteurs constants n'est pas un problème majeur pour (la plupart) de la programmation aujourd'hui, les programmeurs transfèrent ces micro- efforts d'optimisation ailleurs?

En d'autres termes, une meilleure pratique peut-elle être portée à un état extrême où elle n'ajoute plus rien de valeur? Et au lieu de cela, c'est perdre du temps?

Par exemple: les programmeurs perdent-ils du temps à généraliser des méthodes privées qui ne sont appelées qu'à partir d'un seul endroit? La perte de temps réduit-elle les données des cas de test? Les programmeurs sont-ils (encore) trop préoccupés par la réduction des lignes de code?

Il existe deux excellents exemples de ce que je recherche ci-dessous: (1) Passer du temps à trouver les bons noms de variables, voire à tout renommer; et (2) l'élimination de la duplication de code, même mineure et ténue.


Notez que ceci est différent de la question "Pour quoi optimisez-vous? ", Parce que je demande ce que les autres programmeurs semblent maximiser, avec la stigmatisation de ces optimisations "micro", et donc pas une utilisation productive du temps.

Macneil
la source
@Macneil, je ne sais pas pour quoi les autres programmeurs micro-optimisent, mais je n'ai pas beaucoup de temps pour ça. Mes collègues sont également occupés (juste mes 2 cents).
Job
@Job: Vous n'avez jamais vu quelqu'un perdre son temps à changer le code sans raison? Considérez-vous chanceux. Il existe deux excellents exemples ci-dessous: Noms de variables et duplication de code mineure.
Macneil
1
La question, telle qu'elle est libellée actuellement, est une amélioration. Je ne peux pas supprimer le vote serré, mais il vieillira dans quelques jours. En fait, la question attire de très bonnes réponses.
Robert Harvey
1
BTW, toute meilleure pratique peut être poussée à un tel point qu'elle ne produit plus de valeur.
Robert Harvey

Réponses:

22

Formatage du code

Don't     get    me   wrong             ,
code      should be   consistent        & 
readable                                , 
but       some   take it         too far.
JeffO
la source
Ah oui, les bons vieux types de variables et les noms de variables ont besoin de leurs propres colonnes dans une série de déclarations de variables. Oh! Vous avez oublié la ligne supplémentaire pour le =et le quatrième pour les initialiseurs!
Macneil
[Bon sang, je voterais positivement, mais ma limite quotidienne est atteinte ...]
Macneil
3
Nos professeurs nous ont forcés à formater le code pour les devoirs de cette façon. Ça m'a pris des années pour me débarrasser de cette habitude.
Oliver Weiler
Oh cher. Sur d'autres réponses, je riais, mais celle-ci fait vraiment mal :-(
Steve314
2
+1 J'ai déjà travaillé avec une bibliothèque où le développeur a refusé de rendre son code correct car il a bousillé son code formaté en colonne ...
Dean Harding
20

J'écrivais beaucoup d'assembleur à l'époque. Ce n'est pas seulement que les compilateurs se sont améliorés, c'est que la plupart du matériel a maintenant beaucoup de logique consacrée à l'exécution de code dans le désordre. Le vrai micro-problème est la planification, la plupart des instructions informatiques prennent plusieurs horloges pour produire un résultat - et une charge mémoire qui manque de cache peut prendre plusieurs centaines! L'idée était donc de planifier d'autres instructions pour faire quelque chose d'utile, au lieu d'attendre un résultat. Et les machines modernes peuvent émettre plusieurs instructions par période d'horloge. Une fois que nous avons commencé à obtenir un matériel d'exécution hors service, j'ai constaté qu'essayer d'obtenir de grandes performances avec le codage manuel était devenu un jeu de tasses. Tout d'abord, le matériel hors service n'exécutera pas les instructions de votre commande soigneusement conçue, la nouvelle architecture HW sophistiquée a réduit la pénalité de la programmation logicielle non optimale suffisamment pour que le compilateur soit généralement à quelques pour cent de vos performances. J'ai également découvert que les compilateurs implémentaient maintenant des trucs bien connus mais générateurs de complexité, tels que le déroulement, le chargement par le bas, le pipelining du logiciel, etc. Utilisez-les tous et le nombre d'instructions d'assemblage dont vous avez besoin augmente plusieurs fois!

Encore plus important, la plupart des problèmes de performances ne concernent probablement pas les taux d'émission des instructions, mais la saisie des données dans le processeur. Comme je l'ai mentionné ci-dessus, la latence de la mémoire est maintenant de centaines de cycles, et le CPU peut exécuter plusieurs instructions par période d'horloge, donc à moins que le programme - et surtout les structures de données ne soient conçus de manière à ce que le taux d'accès au cache soit excessivement élevé, microtuning à l'instruction le niveau n'aura aucun gain. Tout comme les militaires disent que les amateurs parlent de tactique, les pros parlent de logistique. La programmation des performances représente désormais plus de 90% de la logistique (déplacement des données). Et cela est difficile à quantifier, car la gestion de la mémoire moderne a généralement plusieurs niveaux de cache et les pages de mémoire virtuelle sont gérées par une unité matérielle appelée TLB. L'alignement des adresses de bas niveau devient également important, car les transferts de données réels ne sont pas en unités d'octets, ou même 64 bits long-longs, mais ils viennent en unités de lignes de cache. Ensuite, la plupart des machines modernes ont un matériel qui essaie de prédire quelle ligne de cache manque, dont vous pourriez avoir besoin dans un proche avenir et émettre des préfixes automatiques pour les mettre dans le cache. La réalité est donc qu'avec les processeurs modernes, les modèles de performances sont si complexes qu'ils sont presque incompréhensibles. Même les simulateurs matériels détaillés ne peuvent jamais correspondre à la logique exacte des puces, donc un réglage précis est tout simplement impossible.

Il y a encore une place pour un codage manuel. Les bibliothèques mathématiques (comme par exemple la fonction exp), tout comme les opérations d'algèbre linéaire les plus importantes (comme la multiplication matricielle) sont toujours généralement codées à la main par des experts qui travaillent pour le fournisseur de matériel (c.-à-d. Intel ou AMD ou IBM), mais elles n'ont probablement besoin d'un couple de programmeurs assembleur de premier ordre par corp méga-ordinateur.

Omega Centauri
la source
1
Le codage manuel devient de plus en plus difficile pour les personnes travaillant en dehors des fournisseurs de CPU, car la tâche dépend de plus en plus des connaissances internes et des outils spécifiques du fournisseur (compilateurs et profileurs). spiral.net essaie de modéliser l'optimisation du processeur et d'automatiser la recherche de solutions optimales.
rwong
De nombreux langages informatiques poussent les programmeurs à une micro-optimisation insensée en rendant difficile l'utilisation de la double précision pour les calculs dont les résultats seront rendus float. Pour une raison que je n'arrive pas à comprendre, beaucoup de gens pensent que c'est une bonne chose.
supercat
10

Je passe parfois du temps (perdu?) À choisir un bon nom pour une variable ou une méthode afin qu'elle soit non seulement précisément descriptive, mais ait également un bon style linguistique.

Cela va un peu plus loin lorsque j'essaie de mettre l'ensemble des œuvres (un programme) dans le même style linguistique. Parfois mon avis change et je révise le livre. :)

Non, cela prend autant de temps. C'est plutôt rare. Mais j'aime garder la bonne grammaire dans mes programmes.


la source
3
La dénomination est difficile. Par conséquent, vous devriez refaçonner un nom lorsque vous pensez à un bien meilleur. Notez que cela capture l'effort mental et, espérons-le, cristallise aussi le «pourquoi».
1
C'est une chose à l'esprit gauche (le côté gauche de votre cerveau est responsable du traitement du langage). En tant que programmeur intelligent, j'ai tendance à passer beaucoup moins de temps à m'inquiéter de la sémantique et plus de temps à m'inquiéter de la façon dont toutes les pièces s'assemblent.
Jason Baker
7
La dénomination des variables et des méthodes est un élément important de la maintenabilité. Il faut passer du temps à penser aux noms, afin que dans 5 ans, la personne qui gère le code ait plus de facilité avec lui.
GrandmasterB
@grandmaster: Je ne pourrais pas être plus d'accord.
Robert Harvey
4
@ right-brainers: Veuillez coder pour les lef-tbrainers, afin que je puisse également lire votre code
Juan Mendes
10

Complexité temporelle. Je passe beaucoup trop de temps à optimiser les choses pour les pires performances sur une échelle qui est beaucoup plus grande que tout ce que je sais que le programme rencontrera de manière réaliste.

Je suis tout simplement trop obsessionnel pour lâcher le «mais ça pourrait grossir», même lorsque d'autres décisions de conception l'empêchent de se produire de manière réaliste.

Cependant, pour ma défense, si l'irréaliste devenait réalité .. l'optimisation n'est vraiment plus «micro». Remarque, je n'ai pas dit impossible , mais irréaliste .

Bien sûr, les exigences ont priorité.

Tim Post
la source
1
J'ai travaillé pour une entreprise qui a coulé à cause de cela.
Henry
2
@Henry - Je te le promets, ce n'était pas moi :)
Tim Post
1
@Henry: Vous voulez dire qu'ils temps gaspillés optimisation pour des choses qui ne seraient jamais susceptible de se produire, ou ils ne pensent à des choses qui seraient probablement « jamais » se produire ... jusqu'à ce qu'ils ne se produise et il était trop tard?
Dean Harding
2
@Henry: Si une entreprise a un produit hautement évolutif et continue de couler, c'est la faute aux ventes et au marketing (pour ne pas cibler les clients à volume élevé et ne pas fixer les prix de manière appropriée), pas pour le développement.
rwong
1
L'entreprise a passé trop de temps à concevoir un système pour des millions d'utilisateurs alors qu'ils n'en avaient pas. Ce devait être une faute de commercialisation. Ouais, blâmons le marketing, ces gars sont des idiots.
Henry
8

Je pense que j'ai perdu des semaines en tripotant des gestionnaires d'exceptions Java.

C'est beaucoup de travail pour le code qui échoue deux ou trois fois par an. Cela devrait-il être un avertissement ou une info? Erreur ou fatal? Est-ce vraiment fatal que le processus recommence dans cinq minutes? Est-ce vraiment un avertissement si tout est encore à l'état par défaut?

Beaucoup de nombril et de discussion sur la nature d'une erreur d'E / S. Si vous ne pouvez pas lire un fichier sur le réseau, s'agit-il d'une erreur de fichier ou d'une erreur réseau? Etc.

À un moment donné, j'ai remplacé toutes les chaînes de concaténation String.formatafin que l'erreur de fichier annuelle n'entraîne pas la création d' objets supplémentaires dans le tas. C'était un gaspillage.

sal
la source
3
C'est un travail important. Le prix de l'échec = votre message d'erreur apparaît sur le WTF quotidien.
Steve314
7

Je suppose que je suis trop préoccupé par les LOC. Pas tant les LOC eux-mêmes, mais plutôt le nombre de déclarations et encore plus de déclarations en double. Je suis allergique au code en double. En général, j'adore le refactoring, mais je suppose qu'environ 50% de ce que je fais ne rend pas le code nettement plus agréable.

back2dos
la source
4
+1 pour "Je suis allergique au code en double". Voir aussi ma réponse ici: programmers.stackexchange.com/questions/14610/…
Macneil
En y réfléchissant - j'ai ce problème avec les boucles qui concerne un point que Knuth a fait à propos de goto, et parfois d'avoir à échanger un cycle ou deux ou un code en double afin d'écrire du code structuré. Je vais utiliser un goto dans des cas très rares ( le plus courant = code généré), mais ma variation de ce trouble est de perdre du temps et de se soucier de jongler avec une boucle sans fin en essayant d'éliminer une inefficacité triviale encore garder le code lisible.
Steve314
5

Lire un fichier ligne par ligne au lieu de simplement lire la ligne entière dans une chaîne et traiter la chaîne en une seule prise.

Bien sûr, cela fait une différence dans la vitesse d'exécution mais vaut rarement les lignes de code supplémentaires. Cela rend le code beaucoup moins facile à gérer et augmente la taille du code.

Oui, cela n'a probablement pas de sens si le fichier fait 3 Go mais la plupart des fichiers ne sont pas si gros (du moins pas ceux avec lesquels je travaille ;-)).

Oliver Weiler
la source
3
Même s'il fait 3 Go ou plus, une machine 64 bits peut le gérer avec de la mémoire virtuelle. Utilisez un fichier mappé en mémoire et il ne lira même aucune partie de votre fichier tant qu'il n'est pas nécessaire. Remarquez que même la micro-optimisation dans le cas normal.
Steve314
3

Lorsque j'écrivais un langage d'assemblage, il était logique de taper sur les octets et les cycles, mais c'était il y a longtemps et les compilateurs ont parcouru un long chemin depuis. Je n'essaierais pas d'en optimiser manuellement un maintenant.

De même, lorsque je suis passé à l'écriture en C, il était assez facile de faire un meilleur travail que les compilateurs C, mais chaque année, Borland ou Microsoft ou quelqu'un en publiait un nouveau qui améliorait le précédent dans la salle. J'ai commencé à prêter attention au code d'assemblage réel que le compilateur émettait et, si cela n'écrivait pas du code agréable et serré, dérouler des boucles, déplacer des variables en dehors des boucles, etc.

De nos jours, j'écris dans des langages beaucoup plus élevés comme Perl, Python et Ruby. J'utilise certains des trucs du compilateur à l'avant, comme le déroulage de boucle si cela a du sens, le déplacement de variables statiques en dehors des boucles, etc., mais je ne m'en inquiète pas autant car les processeurs sont un peu plus rapides maintenant. Si une application semble se déplacer de façon inattendue, j'utiliserai un profileur et verrai ce que je peux trouver, puis si quelque chose peut être amélioré, je commencerai à comparer les différentes façons dont je peux penser pour faire quelque chose plus rapidement, puis voir comment cela peut évolue.

En général, j'essaie d'être intelligent sur la façon dont j'écris du code, basé sur des années d'expérience.

l'homme d'étain
la source
Bonjour Greg, merci pour la réponse, mais je cherche ce que les programmeurs font pour perdre du temps, pas pour optimiser les performances d'exécution. Il existe deux excellents exemples ci-dessus: noms de variables et suppression de la duplication de code, même mineure.
Macneil
3

Une micro-optimisation: améliorer les performances mono-thread des choses qui sont parallélisables ou qui peuvent simplement être améliorées avec un nouveau matériel.

Si quelque chose est lent sur un ordinateur il y a 10 ans, une solution moins coûteuse est probablement d'acheter un ordinateur plus récent et plus rapide, plutôt que de perdre du temps à optimiser le programmeur. Un gros objectif des optimisations envisagées devrait cependant être de trouver un moyen d'utiliser les 8 cœurs que vous pouvez obtenir aujourd'hui, ou les 64 que vous pourrez obtenir dans quelques années, au lieu de vous tourmenter à propos des minuties comme le coût supplémentaire des ordures collection.

Kevin Cantu
la source
2

La micro-optimisation en termes de performances d'exécution n'est guère un problème fermé, même aujourd'hui (bien qu'elle puisse être moins courante). Je dois parfois expliquer aux gens que le surcoût de l'allocation d'un objet supplémentaire à chaque demande ou de l'ajout d'un appel de fonction supplémentaire est négligeable.

En dehors de cela, je vois également des programmeurs micro-optimiser pour plus de simplicité (y compris moi-même). Je n'ai pas encore travaillé quelque part où je n'ai pas eu à expliquer la différence entre simplicité et simplisme.

Jason Baker
la source
Pourquoi les programmeurs. être différent? Quelle est la différence, s'il vous plaît.
Dan Rosenstark
@Yar - Pourquoi les programmeurs seraient-ils différents de quoi?
Jason Baker
pourquoi serait programmers.= programmers.stackexchange.comdifférent de chaque endroit où vous avez travaillé où vous avez dû expliquer la différence entre ces deux concepts? Veuillez expliquer la différence.
Dan Rosenstark
@Yar - Je ne sais pas si ce serait le cas. En fait, comme le but de programmers.se est d'aider les programmeurs à mettre en commun leurs connaissances, j'espère que ce n'est pas pour que les gens soient au moins un peu éclairés par ma réponse.
Jason Baker
2
Alors, quelle est la différence b / t simplicité et simplisme?
Dan Rosenstark
2

Je suis tout à fait pour le principe de ne pas optimiser, sauf si c'est vraiment nécessaire. Et je suis pour le principe du profil d'abord. Et en principe, je n'optimiserai que quelque chose qui fera la différence.

C'est en principe. Mais le principe est un menteur.

J'ai l'habitude de faire attention aux fonctions des bibliothèques fréquemment utilisées qui, je pense, seront beaucoup utilisées dans les boucles internes. Et puis, lorsque vous repérez quelque chose dans une autre fonction, ce n'est pas si souvent utilisé ...

Oh - et puis il y a la logique "je l'écris - bien sûr, c'est une bibliothèque importante".

Oh - et BTW. Je n'ai encore jamais utilisé de profileur pour guider une optimisation. Je n'ai pas accès à un service commercial et je n'ai jamais vraiment développé la motivation pour comprendre gprof.

En gros, je suis un hypocrite. Ces principes s'appliquent à d'autres personnes, mais j'ai trop peur que quelqu'un dise "mais pourquoi l'avez-vous écrit de cette manière lente et merdique?" donc je ne peux jamais vraiment les appliquer correctement à moi-même.

Cependant, je ne suis pas aussi mauvais que je le dis ici. Et je suis complètement immunisé contre l'auto-tromperie, alors vous savez que j'ai raison à ce sujet!

ÉDITER

Je devrais ajouter - l'un de mes principaux problèmes stupides est les frais généraux d'appel. Pas partout, bien sûr, mais dans ces cas où je pense que ça va être utilisé beaucoup dans les boucles internes (où je n'ai aucune preuve objective d'un problème). J'ai écrit du code désagréable basé sur offsetof pour éviter de faire des appels de méthode virtuelle plus d'une fois. Le résultat peut même être plus lent, car ce n'est probablement pas un style de codage que les optimiseurs sont conçus pour bien gérer - mais c'est plus intelligent ;-)

Steve314
la source
+1 Ah, oui! Cette classe analyse les arguments de ligne de commande très spécifiques et excentriques de mon application, mais permettez-moi de formater et de documenter complètement quand Javadoc, car d'autres l'utiliseront sûrement pendant des années! [J'aurai besoin de voter plus tard, mon plafond quotidien est atteint.]
Macneil
@Macneil - c'est Doxygen, je vous le ferai savoir. Avec chaque option que je peux trouver activée, chaque petite fonction est "documentée" dans des détails atroces, avec une douzaine de jolis graphiques GraphViz. Aide vraiment tout le monde à apprécier à quel point mon code est important - et l'impression peut tapisser un assez grand immeuble de bureaux.
Steve314
1

Autrefois, lorsque les ordinateurs avaient des temps d'horloge mesurés en microsecondes, de la mémoire mesurée en kilo-octets et des compilateurs primitifs, la micro-optimisation avait un certain sens.

La vitesse et la taille des ordinateurs de génération actuelle et la qualité des compilateurs de génération actuelle signifient que la micro-optimisation est généralement une perte de temps totale. Les exceptions ont tendance à se produire lorsque vous devez absolument obtenir des performances maximales d'un code à forte intensité de calcul ... ou lorsque vous écrivez pour un système embarqué avec des ressources extrêmement limitées.

mais je cherche ce que les programmeurs font pour perdre du temps, pas pour optimiser les performances d'exécution.

Twitter et Facebook me viennent à l'esprit :-)

Stephen C
la source
Bonjour Stephen, c'est un excellent commentaire sur la micro-optimisation, mais voyez-vous des équivalents modernes? [Facebook et Twitter ne sont pas des "meilleures pratiques" qui peuvent être poussées trop loin.]
Macneil
Cela a toujours du sens. Les heures d'horloge peuvent être des ordres de grandeur plus petits, mais le code est des ordres de grandeur plus grands ...
hplbsh
@Stuart - cela signifie qu'il y a des ordres de grandeur plus de code à micro-optimiser ... ce qui n'est tout simplement pas à l'échelle.
Stephen C