Normalerweise hasse ich das Wort "vorzeitige Optimierung", aber das stinkt danach. Es ist erwähnenswert, dass Knuth dieses berühmte Zitat im Zusammenhang mit der Verwendung von goto
Anweisungen verwendet hat, um den Code in kritischen Bereichen zu beschleunigen . Das ist der Schlüssel: kritische Pfade.
Er goto
schlug vor, den Code zu beschleunigen, warnte aber vor den Programmierern, die diese Art von Dingen auf der Grundlage von Aberglauben und Aberglauben für Code ausführen möchten, der nicht einmal kritisch ist.
Zu bevorzugen switch
Aussagen so weit wie möglich gleichmäßig über einen Code - Basis (ob eine schwere Last gehandhabt wird) ist das klassische Beispiel dafür , was Knuth nennt die „Penny-weise und Pfund-dumm“ Programmierer, der den ganzen Tag kämpfen verbringt behalten ihre „optimiert "Code, der sich als Ergebnis des Versuchs, Pennies über Pfund zu sparen, in einen Debug - Albtraum verwandelte. Ein solcher Code ist selten zu warten, geschweige denn überhaupt effizient.
Hat er recht
Er hat von der Grundperspektive der Effizienz her Recht. Meines Wissens kann kein Compiler polymorphen Code mit Objekten und dynamischem Versand besser optimieren als eine switch-Anweisung. Sie werden nie mit einer LUT oder einer Sprungtabelle zu Inline-Code aus polymorphem Code enden, da dieser Code in der Regel als Optimierungsbarriere für den Compiler dient (er weiß erst zum Zeitpunkt des dynamischen Versands, welche Funktion aufzurufen ist) tritt ein).
Es ist sinnvoller, nicht an diese Kosten in Form von Sprungtabellen zu denken, sondern eher in Form der Optimierungsbarriere. Aus Gründen des Polymorphismus kann Base.method()
der Compiler beim Aufrufen nicht erkennen, welche Funktion tatsächlich aufgerufen wird, wenn sie method
virtuell ist, nicht versiegelt und überschrieben werden kann. Da es nicht weiß, welche Funktion tatsächlich im Voraus aufgerufen wird, kann es den Funktionsaufruf nicht optimieren und mehr Informationen für Optimierungsentscheidungen verwenden, da es nicht wirklich weiß, auf welche Funktion zugegriffen wird die Zeit, zu der der Code kompiliert wird.
Optimierer sind am besten geeignet, wenn sie einen Blick auf einen Funktionsaufruf werfen und Optimierungen vornehmen können, die entweder den Anrufer und den Angerufenen vollständig reduzieren oder zumindest den Anrufer optimieren, um mit dem Angerufenen am effizientesten zu arbeiten. Sie können das nicht tun, wenn sie nicht wissen, welche Funktion tatsächlich im Voraus aufgerufen wird.
Spricht er nur seinen Arsch aus?
Die Verwendung dieser Kosten, die sich oft auf ein paar Cent belaufen, um die Umwandlung in einen einheitlich angewendeten Kodierungsstandard zu rechtfertigen, ist im Allgemeinen sehr töricht, insbesondere für Orte, die Erweiterungsbedarf haben. Das ist die Hauptsache, auf die Sie bei echten vorzeitigen Optimierern achten sollten: Sie möchten geringfügige Leistungsprobleme in Codierungsstandards umwandeln, die auf einer Codebasis einheitlich angewendet werden, ohne auf die Wartbarkeit zu achten.
Ich ärgere mich ein wenig über das Zitat "alter C-Hacker", das in der akzeptierten Antwort verwendet wird, da ich einer von denen bin. Nicht jeder, der seit Jahrzehnten mit sehr begrenzter Hardware programmiert, hat sich in einen vorzeitigen Optimierer verwandelt. Dennoch habe ich auch mit denen zusammengearbeitet. Aber diese Typen messen niemals Dinge wie Verzweigungsfehlvorhersagen oder Cache-Fehler, sie denken, sie wissen es besser und stützen ihre Vorstellung von Ineffizienz auf eine komplexe Produktionscodebasis, die auf Aberglauben basiert, die heute nicht zutreffen und manchmal nie zutreffen. Menschen, die wirklich in leistungskritischen Bereichen gearbeitet haben, verstehen oft, dass eine effektive Optimierung eine effektive Priorisierung ist, und der Versuch, einen die Wartbarkeit verschlechternden Kodierungsstandard zu verallgemeinern, um ein paar Cent zu sparen, ist eine sehr ineffektive Priorisierung.
Pennies sind wichtig, wenn Sie eine billige Funktion haben, die nicht so viel Arbeit leistet, was in einer sehr engen, leistungskritischen Schleife milliardenfach genannt wird. In diesem Fall sparen wir am Ende 10 Millionen Dollar. Es lohnt sich nicht, ein paar Cent zu rasieren, wenn Sie eine Funktion haben, die zweimal aufgerufen wird und für die allein der Körper Tausende von Dollar kostet. Es ist nicht ratsam, beim Autokauf um ein paar Cent zu feilschen. Es lohnt sich, um ein paar Cent zu feilschen, wenn Sie eine Million Dosen Soda von einem Hersteller kaufen. Der Schlüssel zu einer effektiven Optimierung liegt darin, diese Kosten im richtigen Kontext zu verstehen. Jemand, der versucht, bei jedem Einkauf ein paar Cent zu sparen und den anderen vorschlägt, um ein paar Cent zu feilschen, egal was er kauft, ist kein erfahrener Optimierer.