Normalement, je déteste le mot "optimisation prématurée", mais ça en a une odeur. Il est intéressant de noter que Knuth a utilisé cette citation célèbre dans le cadre d'une incitation à utiliser des goto
instructions afin d'accélérer le code dans des domaines critiques . C'est la clé: les chemins critiques .
Il proposait d'utiliser goto
pour accélérer le code, mais en mettant en garde les programmeurs qui voudraient faire ce genre de choses basées sur des intuitions et des superstitions pour un code qui n'est même pas critique.
Favoriser les switch
déclarations autant que possible uniformément dans une base de code (qu’une charge lourde soit gérée ou non) est l’exemple classique de ce que Knuth appelle le programmeur "optimiste" qui passe toute la journée à lutter pour maintenir leur "optimisation". "Code qui s’est transformé en cauchemar de débogage en essayant de sauver des sous au lieu de trois livres. Un tel code est rarement maintenable et encore moins efficace en premier lieu.
A-t-il raison?
Il a raison du point de vue fondamental de l'efficacité. À ma connaissance, aucun compilateur ne peut optimiser un code polymorphe impliquant des objets et une répartition dynamique mieux qu'une instruction switch. Vous ne vous retrouverez jamais avec une table de conversion ou une table de saut dans le code incorporé du code polymorphe, car ce code a tendance à servir de barrière d'optimisation au compilateur (il ne saura pas quelle fonction appeler jusqu'à l'heure à laquelle la répartition dynamique se produit).
Il est plus utile de ne pas penser à ce coût en termes de tables de saut, mais plutôt en termes d'obstacle d'optimisation. Pour le polymorphisme, l'appel Base.method()
n'autorise pas le compilateur à savoir quelle fonction sera appelée si elle method
est virtuelle, non scellée et peut être remplacée. Comme il ne sait pas quelle fonction va être appelée à l'avance, il ne peut pas optimiser l'appel de fonction et utiliser plus d'informations pour prendre des décisions d'optimisation, car il ne sait pas en fait à quelle fonction il sera appelé. l'heure à laquelle le code est compilé.
Les optimiseurs sont à leur meilleur lorsqu'ils peuvent scruter un appel de fonction et effectuer des optimisations qui aplatissent complètement l'appelant et l'appelé, ou au moins optimisent l'appelant pour travailler plus efficacement avec l'appelé. Ils ne peuvent pas faire cela s'ils ne savent pas quelle fonction sera appelée à l'avance.
Est-ce qu'il parle juste son cul?
Utiliser ce coût, qui équivaut souvent à des sous, pour justifier de le transformer en une norme de codage appliquée uniformément est généralement très ridicule, en particulier pour les lieux qui ont besoin d’extensibilité. C’est la principale chose à surveiller avec les véritables optimiseurs prématurés: ils veulent transformer les problèmes de performances mineurs en normes de codage appliquées uniformément dans une base de code sans se soucier de la maintenabilité.
Je m'offusque cependant un peu de la citation "old C hacker" utilisée dans la réponse acceptée, puisque je suis l'un de ceux-là. Toutes les personnes qui codent depuis des décennies à partir de matériel très limité ne sont pas devenues un optimiseur prématuré. Pourtant, j'ai rencontré et travaillé avec eux aussi. Mais ces types ne mesurent jamais des erreurs telles que des erreurs de prédiction de branche ou des erreurs de cache, ils pensent en savoir plus et fondent leurs notions d'inefficacité sur une base de code de production complexe basée sur des superstitions qui ne sont pas vraies aujourd'hui et qui parfois ne le sont jamais. Les personnes qui ont véritablement travaillé dans des domaines critiques en matière de performance comprennent souvent que l'optimisation efficace est une priorisation efficace. Tenter de généraliser une norme de codage dégradant la maintenabilité afin d'économiser des sous est une hiérarchisation très inefficace.
Les sous sont importants lorsque vous avez une fonction peu coûteuse qui ne fait pas autant de travail, appelée un milliard de fois dans une boucle très étroite et critique en termes de performances. Dans ce cas, nous finissons par économiser 10 millions de dollars. Il ne vaut pas la peine de se couper des sous lorsque vous avez une fonction appelée deux fois pour laquelle le corps coûte à lui seul des milliers de dollars. Il n’est pas sage de passer son temps à marchander des sous lors de l’achat d’une voiture. Il vaut la peine de marchander des sous si vous achetez un million de canettes de soda à un fabricant. La clé d'une optimisation efficace consiste à comprendre ces coûts dans leur contexte approprié. Quelqu'un qui essaie d'économiser des sous sur chaque achat et suggère que tous les autres essayent de négocier des sous, peu importe ce qu'ils achètent, n'est pas un optimiseur qualifié.