it-swarm-eu.dev

Ist die Mikrooptimierung beim Codieren wichtig?

Ich habe kürzlich eine Frage zu Stack Overflow gestellt, um herauszufinden, warum isset () schneller als strlen () in PHP war. Dies warf Fragen hinsichtlich der Bedeutung von lesbarem Code auf und ob Leistungsverbesserungen von Mikrosekunden im Code überhaupt in Betracht gezogen werden sollten.

Mein Vater ist ein pensionierter Programmierer, und ich habe ihm die Antworten gezeigt. Er war sich absolut sicher, dass ein Codierer, der die Leistung seines Codes auch auf Mikroebene nicht berücksichtigt, keine guten Programmierer sind.

Ich bin mir nicht so sicher - vielleicht bedeutet die Erhöhung der Rechenleistung, dass wir diese Art von Verbesserungen der Mikroleistung nicht mehr berücksichtigen müssen? Vielleicht liegt diese Art der Überlegung bei den Leuten, die den eigentlichen Sprachcode schreiben? (von PHP im obigen Fall).

Die Umweltfaktoren könnten wichtig sein - das Internet verbraucht 10% der weltweiten Energie. Ich frage mich, wie verschwenderisch ein paar Mikrosekunden Code sind, wenn er millionenfach auf Millionen von Websites repliziert wird.

Ich würde gerne Antworten wissen, die vorzugsweise auf Fakten zur Programmierung basieren.

Ist die Mikrooptimierung beim Codieren wichtig?

Meine persönliche Zusammenfassung von 25 Antworten, danke an alle.

Manchmal müssen wir uns wirklich um Mikrooptimierungen kümmern, aber nur in sehr seltenen Fällen. Zuverlässigkeit und Lesbarkeit sind in den meisten Fällen weitaus wichtiger. Es tut jedoch nicht weh, von Zeit zu Zeit eine Mikrooptimierung in Betracht zu ziehen. Ein grundlegendes Verständnis kann uns helfen, beim Codieren wie z

if (expensiveFunction() || counter < X)

Sollte sein

if (counter < X || expensiveFunction())

( Beispiel aus @ zidarsk8 ) Dies könnte eine kostengünstige Funktion sein, und daher wäre das Ändern des Codes eine Mikrooptimierung. Aber mit einem Grundverständnis müssten Sie nicht, weil Sie es an erster Stelle richtig schreiben würden.

181
Boz

Ich stimme deinem Vater zu und stimme ihm nicht zu. Über die Leistung sollte früh nachgedacht werden, aber über die Mikrooptimierung sollte nur früh nachgedacht werden, wenn Sie tatsächlich wissen , dass ein hoher Prozentsatz der Zeit in kleinen Mengen verbracht wird CPU-gebundene Codeabschnitte.

Das Problem bei der Mikrooptimierung besteht darin, dass dies normalerweise ohne Vorstellung davon geschieht, wie Programme tatsächlich mehr Zeit als nötig verbringen.

Dieses Wissen stammt aus der Erfahrung mit der Leistungsoptimierung wie in diesem Beispiel , bei der ein scheinbar einfaches Programm ohne offensichtliche Ineffizienzen durch eine Reihe von Diagnose- und Beschleunigungsschritten geführt wird, bis es 43-mal schneller ist als am Anfang.

Was es zeigt, ist, dass Sie nicht wirklich erraten oder verstehen können, wo die Probleme liegen werden. Wenn Sie eine Diagnose durchführen, in meinem Fall zufällige Pause , werden Codezeilen, die für einen erheblichen Teil der Zeit verantwortlich sind, bevorzugt angezeigt. Wenn Sie sich diese ansehen, finden Sie möglicherweise Ersatzcode und reduzieren dadurch die Gesamtzeit um ungefähr diesen Bruchteil.

Andere Dinge, die Sie nicht repariert haben, brauchen immer noch so viel Zeit wie zuvor, aber da die Gesamtzeit reduziert wurde, benötigen diese Dinge jetzt einen größeren Bruchteil. Wenn Sie also alles noch einmal machen, kann dieser Bruchteil auch eliminiert werden. Wenn Sie dies über mehrere Iterationen hinweg tun, können Sie auf diese Weise massive Beschleunigungen erzielen, ohne jemals eine durchgeführt zu haben Mikrooptimierung .

Wenn Sie sich nach dieser Erfahrung neuen Programmierproblemen nähern, erkennen Sie die Entwurfsansätze, die anfänglich zu solchen Ineffizienzen führen. Nach meiner Erfahrung kommt es von einem Überdesign der Datenstruktur, einer nicht normalisierten Datenstruktur, einer massiven Abhängigkeit von Benachrichtigungen und dergleichen.

90
Mike Dunlavey

Mikrooptimierung ist nur wichtig, wenn die Zahlen dies aussagen.

Die Anforderungen, gegen die Sie entwickeln, sollten eine Spezifikation von Leistungsdaten enthalten, wenn die Leistung für den Client oder Benutzer überhaupt ein Problem darstellt. Während Sie Software entwickeln, sollten Sie die Leistung Ihres Systems anhand dieser Anforderungen testen. Wenn Sie die Leistungsanforderungen nicht erfüllen, müssen Sie Ihre Codebasis profilieren und nach Bedarf optimieren, um die Leistungsanforderungen zu erfüllen. Sobald Sie die erforderliche Mindestleistung erreicht haben, müssen Sie keine Leistung mehr aus dem System herausholen, insbesondere wenn Sie die Lesbarkeit und Wartbarkeit des Codes nicht mehr beeinträchtigen möchten (meiner Erfahrung nach ist hochoptimierter Code weniger lesbar und wartbar, aber nicht immer). Wenn Sie zusätzliche Leistungssteigerungen erzielen können, ohne die anderen Qualitätsmerkmale des Systems zu beeinträchtigen, können Sie dies in Betracht ziehen.

Es gibt jedoch Fälle, in denen die Leistung von größter Bedeutung ist. Ich denke hauptsächlich an Echtzeitsysteme und eingebettete Systeme. In Echtzeitsystemen kann eine Änderung der Reihenfolge der Operationen einen enormen Einfluss auf die Einhaltung der für einen ordnungsgemäßen Betrieb erforderlichen harten Fristen haben und möglicherweise sogar die Ergebnisse von Berechnungen beeinflussen. In eingebetteten Systemen verfügen Sie normalerweise über begrenzten Speicher, CPU-Leistung und Leistung (wie bei der Batterieleistung). Daher müssen Sie die Größe Ihrer Binärdateien und die Anzahl der Berechnungen reduzieren, um die Systemlebensdauer zu maximieren.

120
Thomas Owens

Immer wenn jemand nach Optimierung fragt, werde ich an das Zitat von Michael A. Jackson erinnert

Die erste Regel der Programmoptimierung: Tu es nicht.

Die zweite Regel der Programmoptimierung (nur für Experten!): Mach es nicht noch.

Zitat aus Wikipedia korrigiert für britisches Englisch. * 8 ')

Die zweite Regel impliziert, dass Profil Ihr Code und nur Zeit verbringen Dinge optimieren, die einen Unterschied machen.

Bei der Programmierung in Assembly war die Behauptung Ihres Vaters richtig. Aber das ist dem Metal viel näher als die meisten Leute heutzutage programmieren. Heute kann sogar versuchen, sich selbst zu optimieren (ohne Profilerstellung), dazu führen, dass Ihr Code ausgeführt wird langsamer als wenn Sie etwas auf die üblichere Weise getan hätten, da die Common Way wird eher von modernen JIT Compilern optimiert.

Selbst in C muss man ziemlich gut in der Optimierung sein, um mehr darüber zu wissen, wie man einen Codeabschnitt optimiert, als der Compiler.

Wenn Sie nicht viel von dem wissen, worüber Ulrich Drepper in seinem ausgezeichneten Artikel spricht Was jeder Programmierer über das Gedächtnis wissen sollte, dann sind Sie wahrscheinlich sogar auf einem Verlierer versuchen, sich selbst zu optimieren. Im Gegensatz zum Titel des Papiers (was eigentlich eine Hommage an David Goldbergs ebenso fantastisches Was jeder Informatiker über Gleitkomma-Arithmetik wissen sollte) ist, das dieses Niveau nicht hat Verständnis hält Sie nicht unbedingt davon ab, ein guter Programmierer zu sein, sondern nur eine andere Art von Programmierer.

isset() vs. strlen() in PHP

Ich kenne PHP nicht, daher ist es nicht klar, was isset() tun soll. Ich kann es aus dem Kontext ableiten, aber dies bedeutet, dass es für Anfänger ähnlich dunkel ist PHP Programmierer) und möglicherweise sogar dazu führen kann, dass erfahrene Programmierer es doppelt nehmen. Dies ist die Art von idiomatisch Verwendung einer Sprache, die Wartung zu einem Albtraum machen kann.

Darüber hinaus gibt es keine Garantie dafür, dass isset() immer effizienter ist, nur weil es jetzt effizienter ist. Eine Optimierung ist jetzt möglicherweise keine Optimierung im nächsten Jahr oder in 10 Jahren. CPUs, Systeme und Compiler verbessern und ändern sich im Laufe der Zeit. Wenn die Leistung von PHPs strlen() ein Problem ist, PHP wird möglicherweise in Zukunft geändert, müssen möglicherweise alle isset () - Optimierungen entfernt werden, um den Code zu optimieren einmal mehr.

Jede Optimierung hat das Potenzial, eine Zukunft zu werden Anti-Optimierung, sollte also als möglicher Codegeruch betrachtet werden, um auf ein Minimum beschränkt zu werden.

Ein Beispiel aus persönlicher Erfahrung

Als Beispiel für eine solche Anti-Optimierung musste ich einmal eine riesige Codebasis bereinigen, die mit Code der Form if x==0 z=0 else z=x*y Gefüllt war, weil jemand davon ausgegangen war, dass sich ein Gleitkomma multipliziert war immer wird teurer als eine Filiale. Bei der ursprünglichen Zielarchitektur führte diese Optimierung dazu, dass der Code um eine Größenordnung schneller ausgeführt wurde, die Zeiten sich jedoch ändern.

Als wir versuchten, diesen Code auf einer moderneren CPU mit hoher Pipeline zu verwenden, war die Leistung schrecklich schlecht - jede dieser Anweisungen führt zu einem Pipeline-Flush. Durch die Vereinfachung all dieser Codezeilen auf nur z=x*y Wurde das Programm auf der neuen Architektur um eine Größenordnung schneller ausgeführt, wodurch der Leistungsverlust durch Anti-Optimierung wiederhergestellt wurde.

Die Probleme, die wir heute normalerweise optimieren müssen, sind sehr anders als die, die wir vor 20 oder sogar 10 Jahren optimieren mussten.

Dann machten wir uns Sorgen, dass wir die meiste Arbeit pro Taktzyklus erledigen könnten, jetzt machen wir uns eher Sorgen über Pipeline-Flushes, Verzweigungsfehler und Cache-Fehler auf CPU-Ebene, aber Sperren und Interprozesskommunikation werden zu viel = Bedeutender, wenn wir zu Mehrprozess- und Multiprozessor-Architekturen übergehen. Dreppers Artikel kann wirklich helfen, viele dieser Probleme zu verstehen.

103
Mark Booth
  1. Schreiben Sie Code, der sauber, präzise, ​​einfach und selbsterklärend ist.
  2. Führen Sie Leistungstests durch, um Engpässe zu identifizieren.
  3. Kritische Abschnitte optimieren.

Als Faustregel gilt: 95% Ihres Codes werden 5% der Zeit ausgeführt. Es macht keinen Sinn, zu optimieren, bevor Sie Ihren Code profilieren/bewerten und feststellen, welche 5% in 95% der Fälle ausgeführt werden.

Jeder Idiot kann Mikrooptimierung durchführen und jeder anständige Compiler/jede anständige Laufzeit erledigt dies für Sie.
Die Optimierung von gutem Code ist trivial. Optimierten Code zu schreiben und danach zu versuchen, ihn wieder gut zu machen, ist bestenfalls mühsam und im schlimmsten Fall nicht nachhaltig.

Wenn Sie ernsthaft auf Leistung achten, verwenden Sie PHP nicht für leistungskritischen Code. Finden Sie die Engpässe und schreiben Sie sie mit C-Erweiterungen neu. Selbst eine Mikrooptimierung Ihres PHP Codes über den Punkt der Verschleierung hinaus bringt Sie nicht annähernd so schnell.

Persönlich mochte ich die Mikrooptimierung sehr, als ich anfing zu programmieren. Weil es offensichtlich ist. Weil es dich schnell belohnt. Weil Sie keine wichtigen Entscheidungen treffen müssen. Es ist das perfekte Mittel des Aufschubs. Damit können Sie den wirklich wichtigen Teilen der Softwareentwicklung entfliehen: dem Entwurf skalierbarer, flexibler, erweiterbarer und robuster Systeme.

84
back2dos

Ich würde Ihrem Vater zustimmen: "Wenn ein Codierer die Leistung seines Codes auch auf Mikroebene nicht berücksichtigt, sind sie keine guten Programmierer." Der Schlüssel ist, "Leistung zu berücksichtigen". Das ist nicht gleichbedeutend mit "Mikrooptimierungen bei jedem Schritt durchführen".

Ich stimme den meisten anderen Kommentaren zu - was früher dazu beigetragen hat, C-Programme schneller zu machen, funktioniert heute möglicherweise nicht mehr -, aber es gibt noch andere wichtige Dinge zu beachten: Soll ich C oder C++ verwenden? Klassen mit einfachen überladenen Operatoren können die Leistung beeinträchtigen, wenn Sie sie häufig verwenden. Spielt das eine Rolle? Es hängt von Ihrer Anwendung ab, aber wenn Sie es nicht einmal in Betracht ziehen, sind Sie kein sehr guter Programmierer. Einige Leute mögen es für ungefähr 2 Millisekunden in Betracht ziehen und es ablehnen, aber ich denke, viel zu viele denken buchstäblich nicht einmal darüber nach.

Die Realität ist, dass Code mit der Optimierung schwieriger zu lesen sein kann. Das Schreiben des Codes dauert länger. Code wird irgendwo zwischen etwas schneller und einer Größenordnung schneller sein (das ist selten). Ihre Kunden werden den Unterschied wahrscheinlich nicht kennen.

Eine andere Realität ist, dass die Leute Code gerne wiederverwenden, und wo er landet, kann es ganz anders sein, als wenn Sie ihn geschrieben haben. Plötzlich können sich die Leute darum kümmern.

Angenommen, Sie haben so etwas wie Angry Birds auf einem PC oder für eine Spielekonsole geschrieben. Sie haben die Optimierung in Ihrem Physiksystem und Ihrem Grafiksystem außer Acht gelassen - denn 2,5-GHz-Doppelkerne sind heutzutage im Grunde das Minimum und Ihr Spiel funktioniert gut genug. Dann kommen Smartphones und Sie möchten es portieren. Oh verdammt, ein 600 MHz ARM Kern?

Stellen Sie sich eine Website vor - etwas, das an einem Wochenende zusammengewürfelt wurde, wie heiß oder nicht. Sie verwenden eine beliebige Datenbank, schreiben alles mit Blick auf die schnelle Entwicklung und starten, indem Sie Ihren Freunden eine URL per E-Mail senden. Drei Monate später stirbt Ihr Server an Überlastung und Sie können nichts tun, um die Größe zu erhöhen. Es passiert ständig. Auf den größten Websites werden Stromrechnungen in Hunderten von Kilowatt oder sogar Megawatt gemessen. Denken Sie darüber nach, es gibt Megawatt, die durch Codeoptimierung eingespart werden müssen.

Wie dein Vater sagte, musst du es zumindest berücksichtigen . Die meisten Leute wissen nicht einmal, wie viel Leistung auf dem Tisch liegt, und beschönigen sie mit einem kurzen Spruch über "vorzeitige Optimierung" und "Mach es nicht". Das sind keine guten Programmierer.

Dies ist keine populäre Meinung auf diesen Seiten. Tschüss Reputationspunkte ....

27
phkahler

Nehmen wir zunächst Ihren Fall: PHP

  • Ich denke nicht, dass PHP ist eine Art Sprache (sowohl aufgrund ihrer Natur als auch aufgrund ihrer Hauptanwendungsdomäne)), dass Sie sich über diese "Mikrooptimierungen" Gedanken machen müssen. PHP Code wird hauptsächlich mit Opcode-Caching optimiert.
  • Die in PHP] geschriebenen Programme sind nicht CPU-gebunden, sie sind meistens I/O gebunden, daher sind diese Optimierungen Ihre Zeit sowieso nicht wert.
  • Alles, was Sie optimieren MÜSSEN, sollte wahrscheinlich in eine C-Erweiterung geschlichen und dann dynamisch in die Laufzeit PHP) geladen werden
  • Wie Sie sehen, erhalten wir keinen Anreiz, indem wir unseren Code in PHP - mikrooptimieren - andererseits, wenn Sie diese Zeit damit verbringen, PHP = Code besser lesbar und wartbar - das zahlt Ihnen mehr Dividenden.

Allgemein,

Ich würde "TOOOOO" nicht viel Zeit damit verbringen, meinen Code in einer dynamischen Sprache wie Python oder Ruby zu optimieren, da sie NICHT für CPU-intensive Aufgaben zur Zahlenverarbeitung ausgelegt sind . Sie lösen verschiedene Klassen von Problemen, bei denen eine reale Situation auf aufwändige Weise modelliert wird (die leicht zu lesen und zu pflegen ist) - was als bezeichnet wird. Ausdruckskraft - ist wichtiger als Geschwindigkeit. Wenn Geschwindigkeit das Hauptanliegen wäre, wären sie überhaupt nicht dynamisch.

Für kompilierte Programme (C++, Java) ist die Optimierung wichtiger. Aber auch dort müssen Sie zuerst die Art/Domäne/den Zweck des Programms betrachten, das Sie schreiben. Sie sollten auch die Zeit für die Mikrooptimierung sorgfältig gegen die Vorteile dieser Optimierung abwägen. Wenn Sie noch mehr Optimierung benötigen, können Sie auch einen Schritt nach unten gehen - und diese Teile Ihres Codes in Assembler codieren.

Um Ihre ursprüngliche Frage zu beantworten: "Ist die Mikrooptimierung beim Codieren wichtig?" - die Antwort ist - es hängt davon ab -

  • Was tun Sie: Anwendungsdomäne, Komplexität?
  • Sind Verbesserungen der Mikrosekundengeschwindigkeit für Ihr Programm WIRKLICH wichtig?
  • Welche Art der Optimierung ist am vorteilhaftesten? Es ist möglicherweise nicht immer eine Codeoptimierung, sondern etwas Externes.
  • Wie viel "Güte" (in Bezug auf Geschwindigkeit) ernten Sie aus der Zeit, die Sie in die Mikrooptimierung investieren?
  • Können auf andere Weise bessere Geschwindigkeiten erreicht werden - durch Ändern der Hardware, RAM & Prozessor, paralleles Ausführen von Code oder auf einem verteilten System?

Die Mikrooptimierung (Codeoptimierung) ist nicht nur zeitaufwändig, sondern "verzerrt" auch die natürliche Lesbarkeit Ihres Codes und macht ihn wartungsintensiv. Betrachten Sie es immer als letzten Ausweg - versuchen Sie immer, die gesamte Anwendung zu optimieren, indem Sie eine bessere Hardware und Architektur verwenden als die Optimierung einzelner Codedateien.

25
treecoder

Es scheint viele Antworten zu geben, die besagen, dass Mikrooptimierung ist

alles über Kompromisse - Leistung, Zeit, Kosten, Aufwand, Lesbarkeit/Wartbarkeit und so weiter.

Aber ich weiß, dass es einige Optimierungen gibt, bei denen es keine Auswirkungen auf die Lesbarkeit gibt, und ich mache diese nur zum Spaß. Bei einigen meiner Schulaufgaben (die alle auf Geschwindigkeit basierten) sah ich, dass es immer schön ist, die Mikrooptimierung in Betracht zu ziehen, wenn ich bedingte Aussagen schreibe wie:

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

ist immer schöner als

if (shouldDoThis() && counter < X ) 

Es gibt einige Möglichkeiten, Ihren Code so zu "beschleunigen", und der Unterschied ist normalerweise vernachlässigbar (allerdings nicht immer), aber ich fühle mich besser, wenn ich ihn so schreibe.

Ich weiß nicht, ob jemand dies überhaupt als eine tatsächliche Optimierung betrachtet, aber ich denke, ein Programmierer sollte diese Dinge wissen und berücksichtigen, wenn er seinen Code schreibt.

18
zidarsk8

Zu Beginn meiner Karriere führten pauschale Aussagen wie "Nicht mikrooptimieren" zu großer Verwirrung. Alles ist umständlich; Daher sagen die Leute eher "Best Practice" als "dies tun".

"Best Practice" ist unter allen Umständen die erste Wahl. Beispielsweise sollten LINQ und Entity Framework anstelle von Inline-SQL verwendet werden. In meiner Firma sind wir auf SQL Server 20 . SQL Server 2000 unterstützt Entity Framework nicht. Best Practices erfordern:

  • Ich verkaufe meinen Chef auf die Idee, eine neue Version von SQL Server zu kaufen, was mehrere tausend Dollar bedeutet.
  • Verkauf von Entwicklern auf die Idee, neue Technologien zu erlernen.

Ich weiß aus Erfahrung, dass dies nicht passieren wird. So konnte ich aufhören, ohne Ende Stress machen oder nicht den besten Praktiken folgen.

Hinter Entscheidungen stehen politische, technische und monetäre Überlegungen, die sich auf das Gesamtergebnis auswirken. Denken Sie an diese Tatsache, wenn Sie eine Entscheidung treffen, und wählen Sie Ihre Schlachten mit Bedacht aus.

" Für alles gibt es eine Jahreszeit, eine Zeit für jede Aktivität unter dem Himmel. "

11
P.Brian.Mackey

Dies ist immer ein Kompromiss.

Erstens geht es in der Computerindustrie am Ende um Geld. Was Sie als Entwickler tun müssen, ist, einen Mehrwert für den Kunden zu generieren, damit Sie Geld erhalten (das ist eine übermäßige Vereinfachung, aber der Hauptpunkt ist hier).

Entwicklerzeit kostet Geld. Maschinenleistung kostet auch Geld. Normalerweise sind diese zweiten Kosten viel niedriger als die ersten. Dies ist also das Kapital, um einen lesbaren Code und einen wartbaren Code zu haben, damit Entwickler die meiste Zeit damit verbringen können, Wert zu liefern.

In einigen Fällen kann die Mikrooptimierung wichtig sein. In der Regel handelt es sich jedoch um weniger lesbaren oder weniger erweiterbaren Code (dies ist bei Ihrem verknüpften Beispiel nicht der Fall, im Allgemeinen jedoch der Fall). Dies wird irgendwann Entwicklerzeit kosten. Diesmal teurer als Maschinenleistung, ist dies eine Verschwendung.

Zweitens kann die Mikrooptimierung in einem großen Projekt die Wartung/Weiterentwicklung immer schwieriger machen. Das Problem dabei ist, dass bei der Entwicklung möglicherweise keine andere Optimierung mehr möglich ist. Bei einer sich entwickelnden Anwendung erhalten Sie normalerweise eine Lösung, die langsamer ist als die, die Sie ohne diese Optimierungen gehabt hätten.

Drittens ist die Optimierung oft irrelevant, da die Komplexität des Algorithmus im Allgemeinen jede Mikrooptimierung überwindet, die Sie hätten durchführen können, wenn der Datensatz wächst. Da die Mikrooptimierung die Wartung/Weiterentwicklung Ihres Codes erschwert, ist diese Optimierung möglicherweise schwieriger durchzuführen.

Manchmal liegt der Wert in dieser Optimierung (denken Sie an latenzkritische Programme wie in Videospielen oder im Autopiloten eines Flugzeugs). Dies muss aber demonstriert werden. Normalerweise verbringt Ihr Programm die meiste Zeit in einem begrenzten Teil des Codes. Unabhängig davon, welche Mikrooptimierung Sie durchführen, werden Sie Ihre Programme niemals wertvoller erhalten, ohne den Engpass zu identifizieren und an diesem Teil zu arbeiten.

Das Stellen Ihrer Frage, wie Sie es getan haben, hat gezeigt, dass Sie das Problem nicht mit einem tatsächlichen Programm verglichen haben. In diesem Fall hätten Sie den Trick machen und feststellen können, ob er schneller war oder nicht. Sie haben das also gefragt, bevor Sie ein Problem hatten. Hier liegt das Problem. Sie haben das Problem der Optimierung falsch gehandhabt.

Da Wartung und Weiterentwicklung in der Regel wertvoller sind als Mikrooptimierung, stellen Sie sicher, dass Sie die richtige Schnittstelle haben, bevor Sie eine durchführen. Wenn dann Teile Ihres Programms abstrakt genug für einander sind, können Sie eines mikrooptimieren, ohne das Ganze durcheinander zu bringen. Dies setzt voraus, dass Ihre Schnittstelle lange genug ausgeführt wird, um vertrauenswürdig zu sein.

8
deadalnix

Leistung ist ein Feature

Jeff Atwoods Artikel befasst sich hervorragend mit dem Aufbau einer Hochleistungswebsite und der Wichtigkeit, dies zu tun ...

Konzentrieren Sie sich jedoch erst dann auf die Mikrooptimierung, wenn Sie dies benötigen. Es gibt kostengünstigere Optimierungen, die Sie durchführen können. Konzentrieren Sie sich auf die Architektur, nicht auf den Code. Die meisten Websites, die sich langsam entwickelt haben, hatten Probleme auf hoher Ebene (unnötige Webdienstschicht, schlechtes Datenbankdesign, übermäßig komplizierte Architekturen), die nicht nur die Leistung beeinträchtigten, sondern auch tief verwurzelt und schwer zu beheben waren.

Wenn Sie eine Website erstellen, ist es weitaus wahrscheinlicher, dass Ihr clientseitiger Code und Ihre Datenbanklogik Leistungsprobleme verursachen als Ihr serverseitiger Code. Wenn Sie jedoch Leistungsprobleme haben, können Sie Ihren Code noch besser profilieren und Sie können sie frühzeitig finden.

8
Mike Cellini

Was möchten Sie optimieren?

  • Softwareleistung?
  • Verlässlichkeit?
  • Programmiererproduktivität?
  • Kundenzufriedenheit?
  • Energie-Effizienz?
  • Wartbarkeit?
  • Zeit zum Markt?
  • Kosten?

"Optimieren" bedeutet nicht immer, dass der Code so schnell wie möglich ausgeführt wird. Es gibt Zeiten, in denen es wichtig ist, den absolut schnellsten Weg zu finden, um etwas zu tun, aber das ist in den meisten Codes nicht allzu häufig. Wenn Benutzer den Unterschied zwischen 50 und 100 Mikrosekunden nicht bemerken können, gibt es praktisch keinen Unterschied zwischen den beiden im Code, der nur gelegentlich ausgeführt wird. Hier ist ein Beispiel:

Wenn Sie eine Anzeige der Länge der Benutzereingaben und der Zeit, die eine der beiden Routinen benötigt, um festzustellen, dass diese Länge viel kleiner ist als die Zeit zwischen zwei aufeinanderfolgenden Tastenanschlägen, ständig aktualisieren müssen, spielt es keine Rolle, welche Routine Sie nutzen. Wenn Sie andererseits die Länge einer Milliarde Zeichenfolgen bestimmen müssen, sollten Sie wahrscheinlich die Leistungsunterschiede zwischen verschiedenen Routinen genau berücksichtigen. Im ersten Fall möchten Sie möglicherweise lieber Code schreiben, der leicht zu verstehen und zu überprüfen ist. Im zweiten Fall sind Sie möglicherweise bereit, Lesbarkeit gegen Geschwindigkeit zu tauschen.

Wenn Sie Ihren Code optimieren möchten, sollten Sie Ihren Code in jedem Fall vor und nach den von Ihnen vorgenommenen Änderungen profilieren. Programme sind heutzutage so kompliziert, dass es oft schwierig ist zu sagen, wo die Engpässe liegen. Mit der Profilerstellung können Sie den richtigen Code optimieren und dann zeigen, dass die von Ihnen vorgenommenen Optimierungen wirklich funktioniert haben.

Sie haben nicht gesagt, wann Ihr Vater in den Ruhestand ging oder welche Art von Programmierung er gemacht hat, aber seine Reaktion ist nicht überraschend. In der Vergangenheit waren Speicher, Sekundärspeicher und Rechenzeit teuer und manchmal sehr teuer. Heutzutage sind all diese Dinge im Vergleich zur Programmiererzeit sehr billig geworden. Gleichzeitig sind Prozessoren und Compiler in der Lage, Code auf eine Weise zu optimieren, die Programmierer niemals erreichen könnten. Die Zeiten, in denen Programmierer mit kleinen Tricks ein paar Maschinenanweisungen hier und da verbrennen, sind größtenteils vorbei.

7
Caleb

Es ist nicht wichtig, beim Schreiben des Codes eine Mikrooptimierung vorzunehmen. Die Optimierung sollte mit Hilfe eines Profilers erfolgen und den Code dort optimieren, wo es darauf ankommt.

JEDOCH , ein Programmierer sollte versuchen, offensichtlich dumme Dinge zu vermeiden, während er das schreibt Code.

Führen Sie beispielsweise keine wiederholten teuren Operationen innerhalb einer Schleife durch. Speichern Sie den Wert in einer Variablen außerhalb der Schleife und verwenden Sie diese. Führen Sie in einer häufig aufgerufenen Funktion nicht immer wieder Zeichenvergleiche oder Regex durch, wenn Sie eine Ebene höher gehen, den Vergleich durchführen und daraus eine Ganzzahl, eine Funktionsreferenz oder eine abgeleitete Klasse machen können.

Diese Dinge sind für einen erfahrenen Programmierer leicht zu merken und verbessern fast immer die Codequalität.

7
Zan Lynx

Entwicklerzeit kostet mehr als Computerzeit. Das möchten Sie normalerweise optimieren. Aber :

  • Es gibt einen Unterschied zwischen Mikrooptimierung und algorithmischer Komplexität. Nehmen Sie sich genügend Zeit, um sicher zu sein, dass Sie den richtigen Algorithmus verwenden.
  • Stellen Sie sicher, dass Sie die richtige Frage stellen: select (select count(*) from foo) >= 1 ist nicht dasselbe wie select exists(select 1 from foo).
  • einige Sprachsprachen sind einfach deshalb beliebt, weil sie schneller sind. Es ist in Ordnung, diese zu verwenden, da die meisten fließenden Benutzer der Sprache mit ihnen vertraut sind. (Ihr Beispiel ist ein gutes Beispiel).

Denken Sie bei der Entscheidung, was optimiert werden soll, immer an Amdahls Gesetz . Siehe den Link für genaue Mathematik; Die markige Aussage, an die man sich erinnern sollte, lautet:

Wenn ein Teil Ihres Programms 10% seiner Laufzeit ausmacht und Sie diesen Teil so optimieren, dass er doppelt so schnell ausgeführt wird, wird das Programm als Ganzes Nur um 5% beschleunigt.

Aus diesem Grund sagen die Leute immer, dass es sich nicht lohnt, Teile Ihres Programms zu optimieren, die nicht mehr als ein paar Prozent der gesamten Laufzeit belegen. Dies ist jedoch nur ein Sonderfall eines allgemeineren Prinzips. Amdahls Gesetz besagt, dass Sie, wenn Sie das gesamte Programm doppelt so schnell ausführen möchten, jedes Stück um durchschnittlich 50% beschleunigen müssen. Wenn Sie 20 Gigabyte Daten verarbeiten müssen, gibt es nur zwei Möglichkeiten, um dies schneller als die Zeit zu machen, die zum Lesen von 20 Gigabyte von der Festplatte benötigt wird: Holen Sie sich eine schnellere Festplatte oder verkleinern Sie die Daten.

Was sagt Amdahls Gesetz über Mikrooptimierungen? Es heißt, dass sie es vielleicht wert sind, wenn sie sich auf ganzer Linie bewerben. Wenn Sie die Laufzeit jeder Funktion in Ihrem Programm um ein Prozent reduzieren können, herzlichen Glückwunsch! Sie haben das Programm um ein Prozent beschleunigt. Hat sich das gelohnt? Nun, als Compiler würde ich mich freuen, eine Optimierung zu finden, die das macht, aber wenn Sie es von Hand machen, würde ich sagen, suchen Sie nach etwas Größerem.

7
zwol

Es hängt davon ab, in welchem ​​Entwicklungsstadium Sie sich befinden. Wenn Sie anfangen, etwas zu schreiben, sollten Mikrooptimierungen keine Rolle spielen, da Sie durch die Verwendung guter Algorithmen mehr Leistungssteigerungen erzielen als durch die Verwendung von Mikrooptimierungen. Überlegen Sie auch, was Sie entwickeln, da zeitkritische Anwendungen mehr Vorteile aus Überlegungen zur Mikrooptimierung ziehen als generische Geschäftsanwendungen.

Wenn Sie Software testen und erweitern, werden Mikrooptimierungen Sie wahrscheinlich verletzen. Sie erschweren das Lesen von Code und führen sogar ihre eigenen Fehler ein, die behoben werden müssen, zusammen mit allen anderen Fehlern, die behoben werden müssen.

Wenn Sie tatsächlich Beschwerden von Benutzern über langsamen Code erhalten, sind diese möglicherweise eine Überlegung wert, aber nur, wenn alles andere gelöst wurde, nämlich:

  • Ist der Code gut geschrieben?
  • Kann die Anwendung problemlos auf ihre Daten zugreifen?
  • Kann ein besserer Algorithmus verwendet werden?

Wenn alle diese Fragen beantwortet wurden und Sie immer noch Leistungsprobleme haben, ist es möglicherweise an der Zeit, Mikrooptimierungen im Code zu verwenden. Es besteht jedoch die Möglichkeit, dass andere Änderungen (z. B. besserer Code, besserer Algorithmus usw.) Sie netto machen eher ein Leistungsgewinn als eine Mikrooptimierung.

6
rjzii

Die Ausführungsgeschwindigkeit ist einer von vielen Faktoren, die zur Qualität eines Programms beitragen. Oft hat die Geschwindigkeit eine umgekehrte Korrelation mit der Lesbarkeit/Wartbarkeit. In fast allen Fällen muss der Code für Menschen lesbar sein, damit der Code beibehalten werden kann. Die Lesbarkeit kann nur beeinträchtigt werden, wenn Geschwindigkeit eine wesentliche Voraussetzung ist. Die Anforderung, Code schneller zu machen, als es die vollständige Lesbarkeit/Wartbarkeit zulässt, ist kaum anwendbar, aber es gibt bestimmte Fälle, in denen dies der Fall ist. Das Wichtigste ist, dass mikrooptimierter Code häufig Hacky-Code ist. Wenn also nicht irgendwo eine definierte Anforderung vorliegt, ist dies fast immer der falsche Weg, um das Problem zu lösen. Beispielsweise wird der Benutzer den Unterschied zwischen Ausführungszeiten von 0,5 Sekunden und 1 Sekunde bei CRUD-Vorgängen fast nie bemerken, sodass Sie nicht an einem Assembly-Interop-Hackfest teilnehmen müssen, um diese 0,5 Sekunden zu erreichen. Ja, ich könnte einen Hubschrauber zur Arbeit fliegen und es wäre zehnmal so schnell, aber ich nicht wegen des Preises und der Tatsache, dass Hubschrauber viel schwieriger zu fliegen sind. Wenn Sie Code unnötig mikrooptimieren, tun Sie genau das: Sie müssen unnötige Komplexität und Kosten hinzufügen, um ein überflüssiges Ziel zu erreichen.

5

Mikrooptimierung ist wichtig, wenn Sie auf eine Einschränkung stoßen. Das, was Sie interessiert, ist möglicherweise Speicher, Durchsatz, Latenz oder Stromverbrauch. Beachten Sie, dass dies Merkmale auf Systemebene sind. Sie müssen (und können) nicht jede Funktion in jeder Hinsicht optimieren.

Eingebettete Systeme benötigen mit größerer Wahrscheinlichkeit eine Mikrooptimierung, da Einschränkungen leichter getroffen werden können. Aber selbst dort bringt Sie die Mikrooptimierung nur so weit; Sie können Ihren Weg aus einem schlechten Design nicht mikrooptimieren. Der Punkt bei gutem Design in einem System ist, dass Sie über das gesamte System nachdenken können. Komponenten, die einer Mikrooptimierung bedürfen, sollten sauber freigelegt und so optimiert werden, dass das Design des Systems nicht beeinträchtigt wird.

Beachten Sie, dass kleine "eingebettete" Systeme heutzutage ziemlich nahe an Vaxen oder PDP-11s von gestern liegen können, sodass diese Probleme früher häufiger auftraten. Auf einem modernen Allzwecksystem, das moderne allgemeine kommerzielle Datenverarbeitung durchführt, ist eine Mikrooptimierung selten. Dies ist wahrscheinlich ein Grund, warum dein Vater die Position einnimmt, die er einnimmt.

Es spielt jedoch keine Rolle, ob es sich um Nanosekunden, Millisekunden, Sekunden oder Stunden handelt. Die Probleme sind die gleichen. Sie müssen im Kontext des Systems bewertet werden und was Sie erreichen möchten.

Dies ist ein Beispiel aus einer kürzlich von mir beantworteten Frage zu Stapelüberlauf für einen Fall, in dem eine Mikrooptimierung erforderlich war: Open-Source-Video-Encoder für ein Embedded System.

5
janm

Das größte Problem bei der Mikrooptimierung besteht darin, dass Sie einen Code schreiben, der schwieriger zu warten ist.

Ein weiteres Problem ist, dass abhängig von der Computerkonfiguration Ihre Mikrooptimierung manchmal die schlechteste Leistung aufweist als ohne die "Optimierung".

Wenn Sie viele Mikrooptimierungen vornehmen, verbrauchen Sie viel Zeit, um gegen etwas zu kämpfen, das nicht wirklich wichtig ist.

Ein besserer Ansatz besteht darin, einen saubereren Code zu erstellen, der einfacher zu warten ist. Wenn Leistungsprobleme auftreten, führen Sie ein Profil aus, um herauszufinden, was Ihren Code wirklich langsam macht. Und wenn Sie genau wissen, was wirklich schlecht ist, können Sie das Problem beheben.

Ich sage nicht, dass das Nicht-Durchführen von Mikrooptimierungen eine Entschuldigung dafür ist, dummen Code zu schreiben.

4
Daniel Moura

Ich habe es schon einmal gesagt, und ich werde es hier sagen: "Vorzeitige Optimierung ist die Wurzel allen Übels". Dies sollte eine der Regeln sein, die im Mittelpunkt des Denkens eines jeden Programmierers stehen.

Code kann bis zu einem gewissen Punkt immer schneller sein als derzeit. Wenn Sie Assembly nicht mit Blick auf einen bestimmten Chip von Hand verpacken, können Sie durch Optimierung immer etwas gewinnen. Wenn Sie jedoch nicht für alles, was Sie tun, eine Handverpackung durchführen möchten, muss es ein quantitatives Ziel geben. Wenn Sie sich einmal getroffen haben, sagen Sie "das ist genug" und hören auf zu optimieren, selbst wenn immer noch ein eklatanter Performance-Trottel anstarrt Sie ins Gesicht.

Schöner, eleganter, extrem performanter Code ist nutzlos, wenn er nicht funktioniert (und mit "Arbeit" meine ich die erwartete Ausgabe bei allen erwarteten Eingaben). Daher sollte die Erstellung von Code, der funktioniert, IMMER oberste Priorität haben. Nachdem es funktioniert hat, bewerten Sie die Leistung und suchen nach Möglichkeiten, um die Leistung zu verbessern, bis sie gut genug ist.

Es gibt einige Dinge, die Sie im Voraus entscheiden müssen, die sich auf die Leistung auswirken. Sehr grundlegende Entscheidungen wie die Sprache/Laufzeit, mit der Sie diese Lösung implementieren. Viele davon wirken sich um viele Größenordnungen stärker auf die Leistung aus als das Aufrufen einer Methode gegen eine andere. Ehrlich gesagt ist PHP als Skriptsprache bereits ein Leistungseinbruch, aber da in C/C++ nur sehr wenige Skriptseiten von unten nach oben erstellt werden, ist es mit anderen Technologien vergleichbar, aus denen Sie wahrscheinlich auswählen würden (Java Servlets, ASP.NET) , usw).

Danach ist die E/A-Nachrichtengröße Ihr nächstgrößter Leistungskiller. Durch die Optimierung der Lese- und Schreibfunktionen auf der Festplatte, den seriellen Schnittstellen, den Netzwerkleitungen usw. wird die Laufzeit des Programms normalerweise um viele Größenordnungen verbessert, selbst wenn die Algorithmen hinter den E/A-Vorgängen effizient waren. Reduzieren Sie danach die Big-O-Komplexität des Algorithmus selbst, und wenn Sie dies unbedingt müssen, können Sie "mikrooptimieren", indem Sie kostengünstigere Methodenaufrufe auswählen und andere esoterische Entscheidungen auf niedriger Ebene treffen.

4
KeithS

Wenn Sie sich über Millisekunden Sorgen machen, sollten Sie PHP] aufgeben und stattdessen C oder Assembly verwenden. Nicht, dass ich dies tun möchte, es macht einfach keinen Sinn, solche Zahlen und zu diskutieren Verwenden Sie eine Skriptsprache. Iteriert Ihr Code mit diesem Befehl sowieso so oft?

Die Umgebungsfaktoren kommen hier nicht in Frage, diese Server laufen sowieso rund um die Uhr und wenn sie tatsächlich etwas verarbeiten, ist dies nur dann von Bedeutung, wenn es sich wirklich um eine Aufgabe handelt, die sehr lange ausgeführt wird.

Höchstwahrscheinlich verbraucht das Licht in Ihrem Büro und die Energie, die unsere Computer beim Schreiben von Fragen und Antworten verbraucht haben, weitaus mehr Energie als jede Art von Mikrooptimierung, die Sie vernünftigerweise auf Ihre Anwendungen anwenden können.

4

Sie erwähnen, dass Ihr Vater ein pensionierter Programmierer ist. Programmierer, die in der Mainframe-Welt arbeiteten, mussten sich große Sorgen um die Leistung machen. Ich kann mich erinnern, eine Aktivität der US Navy studiert zu haben, bei der der Mainframe auf 64 KB Arbeitsspeicher pro Benutzer beschränkt war. In dieser Programmierwelt muss man jedes kleine bisschen heraussuchen, das man kann.

Die Dinge sind jetzt ganz anders und die meisten Programmierer müssen sich nicht so viele Gedanken über Mikrooptimierungen machen. Programmierer für eingebettete Systeme tun dies jedoch immer noch, und Datenbankbenutzer müssen immer noch dringend optimierten Code verwenden.

4
HLGEM

Sie sollten den besten, einfachsten Algorithmus für die Aufgabe auswählen. Der Grund, warum es einfach sein muss, ist, den Code lesbar zu halten. Der Grund, warum es das Beste sein muss, ist zu vermeiden, mit schlechten Laufzeitmerkmalen zu beginnen. Wählen Sie BubbleSort nicht blind, wenn Sie wissen, dass Sie große Datenmengen haben. Es ist jedoch in Ordnung für die gelegentliche Art von 10 Elementen.

DANN, wenn die Profilierungszahlen zeigen, dass Ihre Wahl des besten, einfachen Algorithmus nicht gut genug war, können Sie mit der Optimierung beginnen (was normalerweise den Kosten für die Lesbarkeit entspricht).

4
user1249

Ist die Mikrooptimierung beim Codieren wichtig?

Nein, da es Plattformen wie JVM und . NET gibt, auf denen Code für eine virtuelle Maschine geschrieben wird und daher versucht wird, die Ausführung zu optimieren funktioniert möglicherweise nicht so gut, wie das, was auf dem Desktop eines Entwicklers optimal ist, auf einem Server nicht unbedingt dasselbe ist. Sehen Sie sich an, wie weit einige dieser High-Level-Software von der Hardware entfernt sind. Angesichts der Vielfalt der Hardware ist zu berücksichtigen, wie realistisch es ist, Code für bestimmte Chips wie eine CPU oder GPU zu optimieren, wenn ein neues Modell wahrscheinlich in weniger als einem Jahr herauskommt.

Eine weitere Frage, die hier zu berücksichtigen ist, ist die Leistung, gemessen an welcher Metrik: Ausführungsgeschwindigkeit, bei der Ausführung verwendeter Speicher, Geschwindigkeit der Entwicklung neuer Funktionen, Größe der Codebasis auf einem Server in kompilierter oder dekompilierter Form, Skalierbarkeit, Wartbarkeit usw. .? Wenn man es allgemein genug betrachtet, wird die Frage trivial, aber ich bin mir nicht sicher, wie allgemein Sie die Leistung als wirklich ansehen wollten, das kann fast alles sein, solange es auf irgendeine Weise gemessen werden kann.


Einige Mikrooptimierungen funktionieren möglicherweise, andere möglicherweise nicht. Hier kann man sich fragen, wie sinnvoll es ist, solche Arbeiten im Vergleich zu anderen Arbeiten durchzuführen, die als viel höher eingestuft werden, z. B. neue Funktionen oder das Beheben von Fehlern. Die andere Frage wäre, ob ein Upgrade von Hardware oder Software auch einige dieser Optimierungen zunichte machen kann.

3
JB King

Code sollte so geschrieben werden, dass absolut klar ist, was er tut. Dann wenn und nur wenn es ist zu langsam, geh zurück und beschleunige es. Code kann jederzeit geändert werden, um später schneller zu sein, wenn er verstanden werden kann - aber viel Glück beim Ändern, um klar zu sein, ob er schnell ist.

3
DeadMG

Es ist wichtig, wenn:

1) Jemandes Leben hängt von Ihrem Code ab. Eine Funktion, deren Ausführung im Herzfrequenzmesser einer Person 25 ms dauert, ist wahrscheinlich eine schlechte Idee.

Ich persönlich verfolge einen zweigleisigen Ansatz - es gibt Mikrooptimierungen, die die Lesbarkeit nicht beeinträchtigen - offensichtlich möchten Sie diese verwenden. Aber wenn es die Lesbarkeit beeinträchtigt, halten Sie sich zurück - Sie werden nicht viel davon profitieren und es kann tatsächlich länger dauern, bis Sie auf lange Sicht debuggen.

3
ansiart

IMHO Code-Lesbarkeit ist wichtiger als Mikrooptimierung , da sich Mikrooptimierung in den meisten Fällen nicht lohnt.

Artikel über unsinnige Mikrooptimierungen :

Wie die meisten von uns bin ich es leid, Blog-Beiträge über unsinnige Mikrooptimierungen wie das Ersetzen von Druck durch Echo, ++ $ i durch $ i ++ oder doppelte Anführungszeichen durch einfache Anführungszeichen zu lesen. Warum? Da 99,999999% der Zeit, ist es irrelevant. Warum? In 99,99% der Fälle sollten Sie einen PHP Beschleuniger wie APC) installieren oder diese fehlenden Indizes zu Ihren Datenbankspalten hinzufügen oder versuchen, die 1000 Datenbankanforderungen zu vermeiden, die Sie auf der Homepage haben .

print verwendet einen weiteren Opcode, da tatsächlich etwas zurückgegeben wird. Wir können daraus schließen, dass das Echo schneller ist als das Drucken. Aber ein Opcode kostet nichts, wirklich nichts.

Ich habe eine Neuinstallation versucht WordPress. Das Skript wird angehalten, bevor es mit einem "Busfehler" auf meinem Laptop endet, aber die Anzahl der Opcodes lag bereits bei mehr als 2,3 Millionen. Genug gesagt.

In den meisten Fällen spart die Mikrooptimierung 1 Operation unter Millionen, verschlechtert jedoch die Lesbarkeit.

1
webvitaly

Ich denke, dass es einen großen Unterschied zwischen guter Programmierung und Mikrooptimierung gibt.

Wenn es zwei Möglichkeiten gibt, dieselbe Aufgabe auszuführen, wobei eine schneller als die andere ist und beide dieselbe Lesbarkeit aufweisen, sollten Sie die schnellere verwenden. Immer. Und das ist eine gute Programmierung. Es gibt keinen Grund, keinen besseren Algorithmus zur Lösung eines Problems zu verwenden. Und selbst die Dokumentation ist einfach: Geben Sie den Namen des Algorithmus an, jeder kann ihn googeln und weitere Informationen zur Funktionsweise finden.

Und gute Algorithmen sind bereits optimiert. Sie werden schnell sein. Sie werden klein sein. Sie verwenden den minimal erforderlichen Speicher.

Selbst wenn Ihr Programm diese Leistung nicht bietet, können Sie eine Mikrooptimierung in Betracht ziehen. Und Sie müssen die Sprache wirklich kennen, um mikrooptimieren zu können.

Und es gibt immer Platz, um mehr Geld für Hardware auszugeben. Hardware ist billig, Programmierer sind teuer . Geben Sie nicht zu viel Zeit/Geld aus, indem Sie optimieren, wann Sie nur Hardware kaufen können.

1
woliveirajr

"Wert es" braucht Kontext, wie viel einfacher es ist zu schreiben und zu lesen und zu pflegen, als wie viel schneller es etwas für den Benutzer deutlich reaktionsschneller, interaktiver und weniger Wartezeit.

Ein paar Cent zu sparen, um eine Dose Soda zu kaufen, bringt mir nicht viel, wenn ich eine Strecke zurücklegen muss, um diese Pennys zu sparen, zumal ich heutzutage selten Soda trinke. Ein paar Cent pro Dose beim Kauf einer Million Dosen Soda zu sparen, könnte eine große Sache sein.

In der Zwischenzeit ein paar Cent sparen, wenn zwei Leute direkt neben mir sind und einer genau das gleiche für ein paar Cent billiger anbietet und der andere nicht, und ich wähle den teureren, weil ich ihren Hut besser mag, scheint ein dummer Fall zu sein der Pessimisierung.

Was ich oft als "Mikrooptimierungen" bezeichne, scheint merkwürdigerweise frei von Messungen, Kontext und Diskussionen am Ende des Benutzers zu sein, wenn es unbedingt alle drei geben sollte, um solche Optimierungen in Betracht zu ziehen, wenn sie nicht trivial anzuwenden sind. Für mich bezieht sich eine richtige Mikrooptimierung heutzutage auf Dinge wie Speicherlayouts und Zugriffsmuster, und obwohl sie im Fokus "mikro" erscheinen mögen, sind sie nicht mikroeffektiv.

Ich habe es vor nicht allzu langer Zeit geschafft, einen Vorgang von 24 Sekunden auf 25 Millisekunden (ungefähr 960-mal schneller) mit identischen Ausgaben (gesichert durch automatisierte Tests) ohne Änderung der algorithmischen Komplexität für die volumetrische Wärmediffusionshaut zu reduzieren "Mikrooptimierungen" (die größte davon resultierte aus einer Änderung des Speicherlayouts, die auf etwa 2 Sekunden reduziert wurde, der Rest waren Dinge wie SIMD und eine weitere Analyse von Cache-Fehlern in VTune und eine weitere Neuordnung des Speicherlayouts).

Wolfire erklärt die Technik hier und kämpfte mit der erforderlichen Zeit: http://blog.wolfire.com/2009/11/volumetric-heat-diffusion-skinning/

Meine Implementierung hat es geschafft, dies in Millisekunden zu tun, während er sich bemühte, es auf weniger als eine Minute zu reduzieren: enter image description here

Nachdem ich es von 24 Sekunden auf 25 ms "mikrooptimiert" hatte, war dies ein grundlegender Wandel im Workflow. Jetzt können Künstler ihre Rigs in Echtzeit mit über 30 FPS wechseln, ohne jedes Mal 24 Sekunden warten zu müssen, wenn sie kleine Änderungen an ihrem Rig vornehmen. Und das hat tatsächlich das gesamte Design meiner Software verändert, da ich keinen Fortschrittsbalken und solche Dinge mehr brauchte. Alles wurde einfach interaktiv. Das könnte also eine "Mikrooptimierung" in dem Sinne sein, dass alle Verbesserungen ohne Verbesserung der algorithmischen Komplexität erfolgten, aber es war eine eher "Mega-Optimierung", die einen ehemals schmerzhaften, nicht interaktiven Prozess auslöste in eine interaktive Echtzeit, die die Arbeitsweise der Benutzer grundlegend veränderte.

Messung, Benutzeranforderungen, Kontext

Ich mochte Roberts Kommentar hier wirklich und vielleicht habe ich nicht den Punkt gemacht, den ich wollte:

Na komm schon. Niemand wird argumentieren, dass diese Art der Veränderung nicht "wert" ist. Sie konnten einen greifbaren Nutzen nachweisen; Viele sogenannte Mikrooptimierungen können das nicht.

Dies ist trotz der Arbeit in einem sehr leistungskritischen Bereich mit häufig Echtzeitanforderungen das einzige Mal, dass ich eine Mikrooptimierung in Betracht ziehe, bei der ich mich aus dem Weg räumen muss.

Und ich möchte nicht nur die Messungen hervorheben, sondern auch die Benutzerseite. Ich bin insofern seltsam, als ich zuerst als Benutzer/Fan, dann als Entwickler zu meinem aktuellen Feld (und früher zu Gamedev) kam. Ich war also nie so begeistert von den üblichen Dingen, die Programmierer wie das Lösen technischer Rätsel begeistern. Ich fand sie eine Belastung, würde sie aber durch den User-End-Traum tragen, den ich mit anderen Benutzern geteilt habe. Aber das hat mir geholfen, sicherzustellen, dass wenn ich etwas optimiere, es einen echten Einfluss auf die Benutzer mit echten Vorteilen hat. Es ist mein Schutz gegen ziellose Mikrooptimierung.

Das ist meiner Meinung nach genauso wichtig wie der Profiler, denn ich hatte Kollegen, die Dinge wie die mikrooptimierte Unterteilung eines Würfels in eine Milliarde Facetten taten, um nur an realen Produktionsmodellen wie Charakteren und Fahrzeugen zu ersticken. Ihr Ergebnis war in gewissem Sinne "Tech-Demo" beeindruckend, aber für tatsächliche Benutzer fast nutzlos, da sie Fälle profilierten, maßen und verglichen, die nicht mit realen Anwendungsfällen übereinstimmten. Daher ist es so wichtig zu verstehen, was für Benutzer zuerst wichtig ist, entweder indem Sie lernen, die Software wie eine zu denken und zu verwenden, oder indem Sie mit ihnen zusammenarbeiten (idealerweise beide, aber zumindest mit ihnen zusammenarbeiten). Das Wichtigste für mich, wenn wir Mikro bekommen und anfangen wollen, Rasierzyklen und Cache-Fehler usw. zu rasieren, ist, wirklich gut zu priorisieren, wo wir uns bemühen, dies zu tun (was natürlich mit der Kenntnis aller Orte korrespondiert, die wir nicht sollten Tun Sie das nicht, wofür sowohl das Verständnis des Profilers als auch des Benutzers sehr wichtig sind.

1
Dragon Energy

Andere Antworten stimmen mit dem Geld überein. Aber ich werde noch einen weiteren Punkt hinzufügen, an dem man unterscheiden muss, was vorzeitige Optimierung/Mikrooptimierung ist und performanten Code schreibt, der ein Verständnis des Verhaltens der Sprach-/Framework-Konstrukte widerspiegelt (Entschuldigung, ich konnte kein Wort für das letzte finden). Der letzte ist ein gute Codierungspraxis und sollte man generell tun!

Ich werde erklären. Eine schlechte Optimierung (vorzeitige Lese-/Mikrooptimierung) liegt nicht vor, wenn Sie Codeabschnitte ohne Profilerstellung optimieren, um festzustellen, ob es sich tatsächlich um Engpässe handelt. Es ist, wenn Sie basierend auf Ihren Annahmen, Hörensagen und undokumentierten Verhaltensweisen optimieren. Wenn es dokumentiert ist und etwas effizienter/ logisch macht, wie klein es auch sein mag, nenne ich es gute Optimierung . Wie andere gesagt haben, haben beide Nachteile und fast keine Vorteile, wenn es darum geht, Ihnen gute Geschäfte zu machen, aber ich mache immer noch das letztere, nicht das erstere, wenn es nicht so ist die Lesbarkeit vollständig zunichte machen. Ja, Lesbarkeit/Wartbarkeit ist von größter Bedeutung und es geht darum, wo Sie die Grenze ziehen.

Ich werde die Punkte, die andere hier gemacht haben, als Sinnlosigkeit sowohl guter als auch schlechter Optimierungen wiederholen:

  1. Ihre Abhängigkeiten von einem bestimmten Problem können sich ändern, und jede Zeit, die Sie für die Optimierung vor dem Ausfüllen des logischen Abschnitts Ihrer Anwendung benötigen, ist Zeitverschwendung. Ich meine, relativ früh zu optimieren. Heute haben Sie einen List<T> Und als Ihre App ausgeliefert wurde, mussten Sie ihn in LinkedList<T> Ändern. Jetzt war das Benchmarking eine Verschwendung von Zeit und Mühe.

  2. Meistens könnte der eigentliche Engpass Ihrer Anwendung (als messbarer Unterschied gelesen) 5% Ihres Codes betragen (meistens der SQL-Code), und die Optimierung der anderen 95% bringt Ihren Kunden keinen Nutzen.

  3. Normalerweise bedeutet "technisch" leistungsfähigerer Code mehr Ausführlichkeit, was wiederum mehr fehleranfälligen Code bedeutet, was wiederum eine schwierigere Wartbarkeit und mehr Zeit bedeutet, was wiederum bedeutet, dass Sie weniger Geld verdienen.

  4. Der CO2-Fußabdruck, den Sie durch einen Leistungszuwachs von 1% für die ganze Welt sparen, wird leicht durch Treibhausgase in den Schatten gestellt, die Ihr Team beim Debuggen und Verwalten dieses Codes emittieren muss.

Die Negative von schlechte Optimierung sind insbesondere:

  1. Es gibt Ihnen nicht oft die Leistung, die Sie erwarten. Siehe diese Frage auf SO, wo Optimierungen sind falsch gelaufen . Tatsächlich hat es kann nachteilige Auswirkungen. Das ist das Problem mit undokumentiertem Verhalten.

  2. Meistens erledigen moderne Compiler das sowieso für Sie.

Ich werde einige Beispiele für schlechte und gute Optimierung geben:

Das Schlechte -

  1. verwendung kleinerer Integer-Typen anstelle von Int32.

  2. ++i Wird anstelle von i++ Verwendet.

  3. for anstelle von foreach (das Schlimmste, das ich je gesehen habe, besiegt die Logik völlig)

  4. vermeiden geschlossener Variablen

    string p;
    foreach (var item in collection)
        p = ...;
    
  5. verwenden von char anstelle von Zeichenfolge während der Zeichenfolgenverkettung, wie z.

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

Das Gute (aus der .NET-Welt. Sollte selbsterklärend sein) -

  1. Doppelte Suche

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

    anstatt

    if (Dictionary<K, V>.ContainsKey(K))
        do something with Dictionary<K, V>[K]
    
  2. Lade sie alle

    DirectoryInfo.EnumerateFiles();
    

    anstatt

    DirectoryInfo.GetFiles();
    
  3. Zweistufiges Casting:

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

    anstatt

    if (o is string)
        s = (string)o;
    
  4. Wenn die Reihenfolge keine Rolle spielt

    if (counter < X || expensiveFunction())
    

    anstatt

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

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

    anstatt

    void M(object o)
    {
    
    }
    

Wenn Sie mich fragen, ob diese einen spürbaren Leistungsvorteil bieten, würde ich nein sagen. Aber ich würde vorschlagen, dass man sie verwenden sollte, weil es aus einem Verständnis des Verhaltens dieser Konstrukte resultiert. Warum zwei Anrufe tätigen, wenn Sie nur einen machen können? Aus philosophischer Sicht ist es eine gute Codierungspraxis. Und 1 & 3 sind streng genommen auch etwas weniger lesbar, aber übertreffen sie die Lesbarkeit? Nein, nicht viel, also benutze ich. Das ist der Schlüssel - ein anständiges Verhältnis von Leistung zu Lesbarkeit beizubehalten. Und wenn es das ist, geht es darum, wo Sie die Linie ziehen.

1
nawfal

Ich habe vor fast 31 Jahren angefangen zu programmieren, wo Speicher und CPU knapp sind. Vielleicht stimme ich deshalb deinem Vater zu.

Ich glaube, ein guter Codierer muss sich um die Optimierung in jeder Codezeile kümmern. Aber ich würde diesem Satz hinzufügen: so viel es wert ist und immer versuchen Lesbarkeit gegenüber Optimierung an Orten bevorzugen, an denen Berechnungen nicht kritisch sind.

In einem anderen Thread fragte beispielsweise ein Mann nach dem folgenden Code, welche Lösung er wählen würde: CPU oder Speicher.

public class Main {

    public static int totalRevenue;
    public static int totalProfit;

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

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

Dieser Code generiert den folgenden Bytecode:

public class Main {
  public static int totalRevenue;

  public static int totalProfit;

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

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

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

Der Verständlichkeit halber laden 'iload_' Daten vom Stapel und 'istore_' Daten im Stapel.

Es ist leicht zu bemerken, dass Sie wirklich eine Speicherzuordnung in einer Lösung gespeichert haben und mehr CPU-Zyklen verbraucht haben. Diese Art von Frage kann sich selbst für erfahrene Programmierer stellen.

In diesem Beispiel gibt es jedoch einen Haken: Der Stapelspeicher ist in Blöcken vorab zugewiesen, nicht auf Byte-Ebene. Jedes Mal, wenn ein Thread ausgeführt wird, weist er eine bestimmte Menge an Speicher zu, die für Stapeloperationen verwendet werden soll. Wenn Sie also nicht das Glück haben, dass diese 4 Bytes Ihren Stapel überlaufen (und Sie eine größere Stapelgröße einrichten müssen), werden Sie am Ende dieselbe Speichermenge ausgeben, um beide Beispiele auszuführen. Aber im zweiten Fall verbringen Sie mehr Zyklen mit mathematischen Berechnungen und Ihr Code ist viel weniger lesbar.

Ich habe es hierher gebracht, um ein Beispiel zu geben, dass es nicht böse ist, über Optimierungen in kleinen Teilen des Codes zu diskutieren. Ein Typ schloss diese Frage und zeigte auf diesen Thread. Aber dieser Thread beantwortet diese spezielle Frage nicht. Es wird nur über "Keine Sorge um Optimierung" gesprochen. Und aufgrund dieses dummen Mantras glauben die Menschen, dass es richtig ist, nicht zu tiefem Verständnis zu gelangen.

Es gibt eine vernünftige Antwort auf diese Frage, und vielleicht kann man sogar eine bessere Antwort auf die Interna geben. Einmal gelernt, kann ein guter Programmierer dieses Muster instinktiv wiederholen und wird ein besserer Programmierer. Programmierer müssen kritisch über ihren Code nachdenken und versuchen, so viel wie möglich zu verstehen, wie die Maschine ihn verarbeitet.

Ich befürworte hier nicht, dass wir alle kleine Dinge optimieren müssen. Denken Sie daran, dass ich empfohlen habe, die Lesbarkeit gegenüber Mikrooptimierungen zu bevorzugen.

Ich glaube nur, dass das Wiederholen des Mantras "Mach dir keine Sorgen um Optimierung" die Dinge nicht besser macht. Es macht nur Programmierer faul. Programmierer müssen dazu angeregt werden, zu wissen, wie die Dinge hinter den Kulissen funktionieren. Auf diese Weise können die Leute versuchen, besseren Code zu schreiben, und wählen Sie mit Bedacht aus, wann Sie nicht optimieren möchten.

0

Ich werde es so ausdrücken - Mikrooptimierung ist ein Prozess zur Optimierung von etwas, das überhaupt kein Engpass ist. Wenn Ihr Programm beispielsweise zwei Funktionen A und B aufruft und A 100 Millisekunden benötigt und B 2 Mikrosekunden benötigt und Sie die Funktion B weiter optimieren. Das ist nicht nur nicht wichtig, das ist absolut falsch. Die Optimierungsfunktion B wird jedoch als Optimierung und nicht als Mikrooptimierung bezeichnet. Die Bedeutung der Optimierung hängt davon ab. Angenommen, Sie haben nichts anderes zu tun und Ihr Programm ist fehlerfrei. Dann ist es wichtig. Aber im Allgemeinen haben Sie Prioritäten. Angenommen, Sie müssen die Funktion C hinzufügen/schreiben. Wenn Sie der Meinung sind, dass Sie mit der Schreibfunktion C mehr Geld verdienen, als Ihr Programm ohne diese Funktionalität schneller zu machen, sollten Sie sich für eine Optimierung entscheiden. Ansonsten Funktionalität verfolgen. Erfahrene Programmierer, die sich auf Leistung konzentrieren, verbringen nicht viel Zeit mit der Optimierung, sondern schreiben nur schnelle Programme. Zumindest wissen sie, welche Tools sie verwenden müssen und was sie tun müssen, um nicht jahrelang bedeutungslose (Lese-Mikro-) Optimierungen vorzunehmen.

0
user11408

Es gibt Mikrooptimierungen und Mikrooptimierungen. In VB (sowohl VB6 als auch VB.NET, aber ohne Berücksichtigung des Angebots IsNullOrEmpty aus dem Framework) verwende ich immer Len(str) <> 0 anstelle von str <> "". Normalerweise "repariere" ich jedoch nicht den Code anderer, in dem sie letzteren verwendet haben.

Ja, letzteres ist besser lesbar, aber in diesem Fall ist ersteres nicht unlesbar.

Die Leistung sollte beim Entwerfen des Codes eine Überlegung sein, jedoch nicht zu Lasten der Lesbarkeit und Wartbarkeit.

0
Mark Hurd