Ist die Mikrooptimierung beim Codieren wichtig?


178

Ich habe kürzlich eine Frage zu Stack Overflow gestellt, um herauszufinden, warum isset () in PHP schneller war als strlen () . Dies warf Fragen zur Wichtigkeit 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 Kodierer keine guten Programmierer sind, wenn er die Leistung in seinem Code selbst auf Mikroebene nicht berücksichtigt.

Ich bin mir nicht so sicher - vielleicht bedeutet die Erhöhung der Rechenleistung, dass wir diese Art von Verbesserungen der Mikro-Performance nicht mehr in Betracht ziehen 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 Websites repliziert wird.

Ich möchte 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, keine offensichtlichen Fehlentscheidungen bei der Codierung zu treffen, wie z

if (expensiveFunction() || counter < X)

Sollte sein

if (counter < X || expensiveFunction())

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


123
Der Rat Ihres Vaters ist veraltet . Ich würde nicht fragen, wie viel es die Leistung verbessert. Ich würde fragen, wo der Engpass ist. Es spielt keine Rolle, ob Sie die Leistung eines Codeabschnitts verbessern, wenn dies keinen allgemeinen Unterschied macht. Ihre langsamste Verbindung bestimmt die Geschwindigkeit. In PHP wird in das Netzwerk geschrieben (es sei denn, Sie können nachweisen, dass der IE etwas anderes misst). was bedeutet, dass lesbarer Code geschrieben wird, ist wichtiger.
Martin York

61
Wenn das Schlüsselwort in Betracht gezogen wird, liegt er nicht falsch. Sie müssen eine Ahnung davon haben.
JeffO

37
Ich bin traurig, weil das berühmte Zitat von Premature Optimization noch nicht erwähnt wurde: "Programmierer verschwenden enorm viel Zeit damit, über die Geschwindigkeit unkritischer Teile ihrer Programme nachzudenken oder sich Gedanken zu machen, und diese Effizienzversuche haben tatsächlich ein starkes Negativ Auswirkungen auf das Debugging und die Wartung sind zu berücksichtigen. In 97% der Fälle sollten wir die geringen Wirkungsgrade außer Acht lassen: Die vorzeitige Optimierung ist die Wurzel allen Übels . Dennoch sollten wir unsere Chancen bei diesen kritischen 3% nicht auslassen. "
Tamara Wijsman

13
Können Sie eine Quelle für "10% der Weltenergie" bereitstellen?
Michael Easter

17
coder does not consider performance in their code even at the micro level, they are not good programmersunterscheidet sich stark von der Mikrooptimierung. Es ist nur eine gute Codierung.
Woliveirajr

Antworten:


90

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 CPU-gebundenen Codeabschnitten verbracht wird.

Das Problem bei der Mikrooptimierung besteht darin, dass in der Regel keine Vorstellung davon besteht, wie Programme tatsächlich mehr Zeit als erforderlich verbringen.

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

Was es zeigt, ist, dass Sie nicht wirklich erraten oder verstehen können, wo die Probleme liegen werden. Wenn Sie eine Diagnose durchführen, bei der es sich in meinem Fall um eine zufällige Pause handelt , werden Codezeilen, die für einen erheblichen Teil der Zeit verantwortlich sind, bevorzugt freigelegt. 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, benötigen immer noch so viel Zeit wie zuvor, aber da sich die Gesamtzeit verringert hat, benötigen diese Dinge jetzt einen größeren Bruchteil. Wenn Sie also alles noch einmal machen, kann dieser Bruchteil auch beseitigt werden. Wenn Sie dies über mehrere Iterationen hinweg tun, können Sie massive Beschleunigungen erzielen, ohne jemals eine Mikrooptimierung durchgeführt zu haben .

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


120

Mikrooptimierung ist nur wichtig, wenn die Zahlen es aussagen.

Für die Anforderungen, gegen die Sie sich entwickeln, sollten einige Leistungsdaten angegeben werden, wenn die Leistung für den Client oder den 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 erreichen. 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 (nach meiner Erfahrung ist hochoptimierter Code weniger lesbar und fehlerhaft) wartbar, aber nicht immer). Wenn Sie zusätzliche Leistungssteigerungen erzielen können, ohne die anderen Qualitätsmerkmale des Systems zu beeinträchtigen,

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 Betriebsreihenfolge 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 ist der Arbeitsspeicher, die CPU-Leistung und die Leistung (wie bei der Akkuleistung) normalerweise begrenzt. Daher müssen Sie die Größe Ihrer Binärdateien und die Anzahl der Berechnungen reduzieren, um die Systemlebensdauer zu maximieren.


Wenn es andererseits ein Problem zwischen der Verwendung einer langsameren und einer schnelleren Funktion gibt, gibt es keinen Grund, die langsamere Funktion zu verwenden - wie hier im Fall von isset.
Mavrik

7
@Mavrik Das stimmt. Wenn Sie zwei Funktionen haben, X und Y, und Y ist schneller als X (zumindest für Ihre speziellen Bedingungen), gibt es keinen Grund, Y nicht zu verwenden, wenn der Code noch so lesbar und wartbar ist. Wenn Sie jedoch nichts über Y wissen und den Code umgestalten müssen, um Y anstelle von X zu verwenden, und die Leistung (dieses Codesegments) kein Problem darstellt, gibt es keinen Grund, diese Änderung vorzunehmen. Es dreht sich alles um Kompromisse - Leistung, Zeit, Kosten, Aufwand, Lesbarkeit / Wartbarkeit und so weiter.
Thomas Owens

2
Ich stimme voll und ganz zu, ich wollte nur diesen Punkt in Bezug auf die Mikrooptimierung ansprechen - wenn es Sie in Bezug auf Lesbarkeit / Zeit nichts kostet, tun Sie es. Ansonsten nicht.
Mavrik

+1 hochoptimierter Code ist weniger lesbar und wartbar ... aber nicht immer.
Boz

Weitere Fälle, in denen Leistung wichtig ist: (1) Gaming; (2) große Datenmengen; (3) stark frequentierte Website; (4) Reaktionsfähigkeit einer hochkomplexen Benutzeroberfläche; (5) Dienst, der im Hintergrund ausgeführt werden soll, wie eine Virenprüfung; (6) Finanzen; (7) Smartphone; und so weiter. Es ist kaum auf esoterische Fälle wie RTS und eingebettete Systeme beschränkt.
Rex Kerr

103

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

Die erste Regel zur Programmoptimierung: Tun Sie es nicht.

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

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

Die zweite Regel impliziert, dass Sie Ihr Code- Profil erstellen und nur Zeit damit verbringen, Dinge zu optimieren, die den Unterschied ausmachen.

Bei der Programmierung in der Baugruppe stimmte die Aussage Ihres Vaters. Aber das ist dem Metal viel näher, als die meisten Leute heutzutage programmieren. Heutzutage kann sogar der Versuch , sich selbst zu optimieren (ohne Profilerstellung), dazu führen, dass Ihr Code langsamer ausgeführt wird, als wenn Sie etwas auf die üblichere Weise getan hätten, da es wahrscheinlicher ist, dass der übliche Weg von modernen JIT- Compilern optimiert wird .

Sogar in C muss man ziemlich gut optimieren können, um mehr darüber zu wissen, wie man einen Codeabschnitt optimiert als der Compiler.

Wenn Sie nicht viel über das wissen , worüber Ulrich Drepper in seinem exzellenten Artikel Was jeder Programmierer über Speicher wissen sollte , dann sind Sie wahrscheinlich auf einem Verlierer, der sogar versucht, sich selbst zu optimieren. Im Gegensatz zum Titel der Arbeit (der eigentlich eine Hommage an David Goldbergs gleichermaßen fantastisches Wissen über Gleitkomma-Arithmetik ist ) bedeutet ein solches Verständnis jedoch nicht zwangsläufig, dass Sie ein guter Programmierer sind, sondern eine andere Art von Programmierer Programmierer.

isset()vs. strlen()in PHP

Ich kenne PHP nicht, es ist also nicht klar, was isset()damit gemeint ist. Ich kann es aus dem Kontext ableiten, aber dies bedeutet, dass es für unerfahrene PHP-Programmierer ähnlich undurchsichtig sein wird und sogar erfahrene Programmierer dazu veranlassen könnte, zweimal zu arbeiten. Dies ist die Art der idiomatischen Verwendung einer Sprache, die die Wartung zu einem Albtraum machen kann.

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

Jede Optimierung hat das Potenzial, eine zukünftige Anti-Optimierung zu werden. Daher sollte ein möglicher Code-Geruch in Betracht gezogen werden, um das Risiko so gering wie möglich zu halten.

Ein Beispiel aus eigener Erfahrung

Als Beispiel für eine solche Anti-Optimierung musste ich einmal eine riesige Codebasis bereinigen, die mit Code des Formulars gefüllt war, if x==0 z=0 else z=x*yweil jemand die Annahme gemacht hatte, dass eine Gleitkomma-Multiplikation immer teurer sein würde als eine Verzweigung. Bei der ursprünglichen Zielarchitektur führte diese Optimierung dazu, dass der Code eine Größenordnung schneller ausgeführt wurde, die Zeiten sich jedoch änderten.

Als wir versuchten, diesen Code auf einer moderneren CPU zu verwenden, die eine hohe Pipeline-Auslastung aufwies, war die Leistung furchtbar schlecht - jede dieser Anweisungen führt zu einem Pipeline-Flush. Durch die Vereinfachung all dieser Codezeilen konnte z=x*ydas Programm auf der neuen Architektur um eine Größenordnung schneller ausgeführt werden und die durch die Antioptimierung verlorene Leistung wiederhergestellt werden .

Die Probleme , die wir haben in der Regel für heute zu optimieren , sind sehr unterschiedlich zu denen , die wir vor 20 oder sogar 10 Jahren gehabt zu optimieren.

Dann wir besorgt über die meiste Arbeit pro Taktzyklus zu tun, jetzt sind wir eher über Pipeline Wallungen sein besorgniserregend, Verzweigungsfehlvorhersagen und Cache - Misses auf CPU - Ebene, sondern Schlösser und Interprozess- Kommunikation werden immer viel mehr Bedeutung , da wir multi- bewegen Prozess- und Multiprozessor-Architekturen. Dreppers Artikel kann wirklich helfen, viele dieser Probleme zu verstehen.


3
Pipeline Flush und Cache Miss wollen Sie vermeiden: D Sie haben schreckliche Kosten. aber nur auf Teile des Codes, die sie viele, viele, viele, viele Male anregen.
Deadalnix

7
Eine Sache, die ich hinzufügen möchte, ist, dass Compiler einen langen Weg zurückgelegt haben und viele Dinge für Sie optimieren werden. AFAIK, sie optimieren sauberen, lesbaren Code besser als die kniffligen Dinge.
Becuzz

3
+1 für die Bereitstellung eines realen Beispiels für eine Mikrooptimierung, die Zeit verschwendete - und enthüllte, dass Michael Jackson ein Programmierer war.
Boz

1
+1 Für das Beispiel. Es zeigt perfekt, warum Sie einfache Transformationen dem Compiler überlassen sollten.
back2dos

1
@Rex Kerr> im Beispiel stammen die Kosten aus der Verzweigung, wodurch die CPU-Pipeline geleert wird. Gleitkommamultiplikation ist auch teuer. Was teurer ist, hängt stark von der FPU und der Pipeline-Länge der CPU ab, auf der der Code ausgeführt wird. Es würde mich nicht wundern, wenn dieser Code auf älteren CPUs schneller laufen würde, die eine kürzere Pipeline und eine weniger effiziente FPU haben als die aktuelle CPU.
Deadalnix

84
  1. Schreiben Sie Code, der übersichtlich, übersichtlich, einfach und selbsterklärend ist.
  2. Führen Sie Leistungstests durch, um Engpässe zu identifizieren.
  3. Optimieren Sie kritische Abschnitte.

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

Jeder Idiot kann Mikrooptimierungen durchführen und jeder anständige Compiler / Runtime wird dies für Sie tun.
Das Optimieren von gutem Code ist trivial. Das Schreiben von optimiertem Code und der Versuch, ihn danach wieder gut zu machen, ist bestenfalls mühsam und im schlimmsten Fall nicht nachhaltig.

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

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 zum Aufschieben. Damit können Sie den wirklich wichtigen Teilen der Softwareentwicklung entfliehen: dem Entwurf skalierbarer, flexibler, erweiterbarer und robuster Systeme.


2
Die beste Antwort auf meine Frage war bemerkenswerterweise im Bugzilla-Entwicklerhandbuch zu finden: "Wenn Sie versuchen, klug zu sein, anstatt lesbar zu sein, versuchen Sie vielleicht, die Dinge" schneller "zu machen?" Wenn ja, denken Sie daran : Lösen Sie ein Problem nicht, bevor Sie wissen, dass es existiert. Wenn Sie nicht wissen (durch tatsächliche, detaillierte Tests), dass Ihr Code langsam ist, sorgen Sie sich nicht darum, ihn "schneller" zu machen. Dies ist nicht nur auf beschränkt Optimierung - viele Programmierer lösen ständig Probleme, die noch niemand erlebt hat. Tun Sie das nicht. " bugzilla.org/docs/developer.html#general
Marco

7
Ich stimme im Allgemeinen zu - abgesehen von einer Zeile, behaupte ich, dass "jeder Idiot denkt , dass er Mikrooptimierung kann" ...;)
Nim

@ Nim: Point taken;)
back2dos

26

Ich stimme Ihrem Vater zu: "Wenn ein Programmierer die Leistung in seinem Code selbst auf Mikroebene nicht berücksichtigt, sind sie keine guten Programmierer." Der Schlüssel ist, "Leistung zu betrachten". Das ist nicht gleichbedeutend mit "Mikrooptimierungen bei jedem Schritt durchführen".

Ich stimme den meisten anderen Kommentaren zu - was früher C-Programme schneller gemacht hat, ist heute vielleicht nicht mehr so ​​-, aber es gibt noch andere ernste 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 berücksichtigen, 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 mit der Optimierung Code schwerer zu lesen sein kann. Das Schreiben von Code 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 ganz anders sein als zu dem Zeitpunkt, als Sie ihn geschrieben haben. Plötzlich können sich die Leute interessieren.

Angenommen, Sie haben 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 heutzutage sind Doppelkerne mit 2,5 GHz im Grunde genommen das Minimum und Ihr Spiel funktioniert gut genug. Dann kommen Smartphones und Sie möchten es portieren. Oh verdammt, ein 600 MHz ARM- Kern?

Denken Sie an eine Website - etwas, das an einem Wochenende wie Hot or Not zusammengewürfelt wird . Sie verwenden eine beliebige Datenbank, schreiben alles im Hinblick auf eine schnelle Entwicklung und senden Ihren Freunden per E-Mail eine URL. 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. Die größten Websites haben Stromrechnungen, die in Hunderten von Kilowatt oder sogar Megawatt gemessen werden. Denken Sie darüber nach, es gibt Megawatt, die durch Codeoptimierung eingespart werden müssen.

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

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


3
Sicher, Sie sollten es in Betracht ziehen (im Hinterkopf) und es in der Regel ablehnen, es sei denn, es hat sich als wertvoll erwiesen. Sie müssen berücksichtigen, dass Optimierungen in der Regel die Lesbarkeit des Codes verringern und die Zeit für Code und Wartung um den Faktor 10 verlängern können. Wenn das Programm nicht CPU-intensiv ist, wird es häufig nicht benötigt. Erkennen Sie, dass Ihr Compiler in der Regel viel besser optimiert als Sie und dass viele Ihrer Optimierungen die Leistung tatsächlich beeinträchtigen. Wenn es Ihre Zeit zum Testen Ihrer Optimierungen und Ihres Profils nicht wert ist, ist es Ihre Zeit zum Optimieren nicht wert.
Dr. jimbob

3
Ihr Angry Birds-Beispiel zeigt genau, warum Sie nicht vorzeitig optimieren sollten . Bei der Portierung vom Desktop zur Konsole auf mobile Geräte handelt es sich um (mindestens) drei sehr unterschiedliche Hardwaretypen, und die Optimierung für einen kann möglicherweise schaden, anstatt für einen anderen zu helfen. Schlimmer noch, durch die Optimierung wird es schwieriger, den Code zu verstehen, und ist daher schwerer zu portieren. Wählen Sie von Anfang an effiziente Algorithmen aus, aber sparen Sie sich die Mikrooptimierung für die Phase der Leistungsoptimierung, wenn Sie anhand realer Daten feststellen, wo auf jeder Plattform die Probleme liegen.
Caleb

@Caleb: Das Angry Birds-Beispiel zeigt, warum nicht für bestimmte Hardware optimiert werden sollte. Es wird auch gezeigt, wie Sie eine gesamte App erstellen können, ohne sich die Mühe machen zu müssen, allgemeinere Optimierungen auf "C-Ebene" vorzunehmen und sich dann zu verbrennen. Eigentlich nicht verbrannt, aber Probleme, die über Ihre ursprüngliche Absicht hinausgehen.
Phkahler

25

Nehmen wir zuerst Ihren Fall: PHP

  • Ich glaube nicht, dass PHP eine Art Sprache ist (sowohl aufgrund seiner Natur als auch aufgrund seines Hauptanwendungsbereichs), die 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, sondern meistens E / A- gebunden, sodass diese Optimierungen Ihre Zeit sowieso nicht wert sind.
  • Alles, was Sie optimieren MÜSSEN, sollte wahrscheinlich in eine C-Erweiterung geschlichen und dann dynamisch in die PHP-Laufzeit geladen werden
  • Sie sehen also, wir bekommen keinen Anreiz, wenn wir unseren Code in PHP mikrooptimieren. Wenn Sie jedoch diese Zeit damit verbringen, PHP-Code lesbarer und wartbarer zu machen, zahlen Sie sich mehr aus.

Im Allgemeinen,

Ich würde "TOOOOO" nicht viel Zeit damit verbringen, meinen Code in einer dynamischen Sprache wie Python oder Ruby zu optimieren - denn sie sind NICHT für CPU-intensive Aufgaben beim Knacken von Zahlen konzipiert. Sie lösen verschiedene Problemklassen, bei denen es wichtiger ist, eine reale Situation auf eine aufwändige Art und Weise zu modellieren (die leicht zu lesen und zu pflegen ist) - was als Expressivität bezeichnet wird - als Geschwindigkeit. Wenn Geschwindigkeit das Hauptanliegen wäre, wären sie nicht in erster Linie dynamisch.

Bei kompilierten Programmen (C ++, Java) ist die Optimierung wichtiger. Aber auch hier müssen Sie sich zuerst die Art / Domäne / den Zweck des Programms ansehen, das Sie schreiben. Sie sollten auch die Zeit für die Mikrooptimierung sorgfältig mit den Vorteilen aus dieser Optimierung abwägen. Wenn Sie noch mehr Optimierung benötigen, können Sie auch überlegen, einen Schritt nach unten zu gehen - und diese Teile Ihres Codes in Assembler zu codieren.

Um Ihre ursprüngliche Frage zu beantworten: "Ist die Mikrooptimierung beim Codieren wichtig?" - Die Antwort ist - es kommt darauf an -

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

Die Mikrooptimierung (eigentlich die 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 einzelne Codedateien zu optimieren.


18

Es scheint viele Antworten zu geben, die besagen, dass es sich um Mikrooptimierung handelt

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

Aber ich weiß, dass es einige Optimierungen gibt, bei denen die Lesbarkeit nicht beeinträchtigt wird, und ich mache diese nur zum Spaß. Ich habe bei einigen meiner Schulaufgaben (die alle geschwindigkeitsabhängig waren) festgestellt, dass es immer gut ist, die Mikrooptimierung in Betracht zu ziehen, wenn ich bedingte Anweisungen 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 (nicht immer), aber ich fühle mich besser, wenn ich ihn so schreibe.

Ich weiß nicht, ob jemand dies überhaupt als Optimierung ansieht, aber ich denke, ein Programmierer sollte diese Dinge kennen und berücksichtigen, wenn er seinen Code schreibt.


2
Dies ist in diesem speziellen Fall möglicherweise nicht wichtig . Aber ich denke , es ist sehr wichtig, um Optimierungen wie diese zu erkennen , so dass , wenn es tut Sache, die Sie nicht unnötig Zeit Profilerstellung und Optimierung nach der Tat zu verbringen.
tskuzzy

4
Dies ist ein sehr gefährliches Beispiel. Eine Optimierung sollte niemals das Verhalten ändern . Sogar zu vermuten, dass dies cheap() && expensive()eine Optimierung ist, die dazu expensive () && cheap()einlädt, blindlings untereinander zu ersetzen, ohne Rücksicht auf die signifikante semantische Veränderung, die sie hervorruft (in Sprachen, in denen &&der Kurzschlussoperator verwendet wird).
Mark Booth

5
Wenn die Funktionen keine Nebenwirkungen haben, sind sie gleichwertig und eine ist schneller. Wenn sie Nebenwirkungen haben, sollte man den Code nicht in erster Linie so schreiben. Ich würde sogar sagen, dass dies aus Gewohnheit geschehen sollte - es sei denn, es ändert tatsächlich das Verhalten.
Phkahler

3
@MarkBooth da muss ich phkahler zustimmen, keine dieser funktionen sollte nebeneffekte haben! Die Reihenfolge der Bedingungen in einer if-Anweisung darf sich nicht auf das Ergebnis des Programms auswirken. Mein Beispiel wäre besser geschrieben als if (x<100 && isPrime(x)), nur um es klarer zu machen.
Zidarsk8

1
@ zidarsk8 - Ändert eine Optimierung etwas anderes als die Ausführungsgeschwindigkeit, handelt es sich nicht um eine Optimierung . Als Programmierer müssen wir oft pragmatisch sein , und manchmal können wir nicht garantieren, dass alle mit einem Kurzschlussoperator verwendeten Funktionen rein sind - insbesondere, wenn unser Code Bibliotheken von Drittanbietern aufruft, auf die wir keinen Einfluss haben. In dieser Situation müssen Sie darauf achten, dass unerfahrene Programmierer nicht dazu ermutigt werden, Fehler im Namen der Optimierung einzuführen .
Mark Booth

11

Zu Beginn meiner Karriere führten pauschale Aussagen wie "Nicht mikrooptimieren" zu viel Verwirrung. Alles ist umständlich; Daher sagen die Leute eher "Best Practice" als "Do This".

"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 arbeiten wir mit SQL Server 2000 . SQL Server 2000 unterstützt kein Entity Framework. Best Practices erfordern:

  • Ich verkaufe meinem Chef die Idee, eine neue Version von SQL Server zu kaufen, was mehrere tausend Dollar bedeutet.
  • Entwickler über die Idee des Lernens neuer Technologien informieren.

Ich weiß aus Erfahrung, dass dies nicht passieren wird. So konnte ich aufhören, mich ohne Ende anstrengen oder nicht den Best Practices folgen.

Bei Entscheidungen, die sich auf das Gesamtergebnis auswirken, sind politische, technische und monetäre Erwägungen zu berücksichtigen. Denken Sie daran, 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. "


1
Übrigens können Sie Dapper als Mikro-ORM-Alternative zu Inline-SQL verwenden.
Dan

2
LINQ and Entity Framework should be used in lieu of inline SQL- Bis Sie tatsächlich Inline-SQL benötigen, um etwas zu optimieren; Die von EF erzeugte SQL ist nicht immer optimal.
Robert Harvey

1
fwiw, wenn Ihr Chef über die Lizenzkosten von SQL 2k8 (oder was auch immer aktuell sein mag) besorgt ist, sollten Sie darauf hinweisen, dass es alt genug ist, um sehr bald auf EOL zu erscheinen (wenn es nicht schon
geschehen ist

@warren - Manche Unternehmen berücksichtigen solche Dinge nicht. Für einige "funktioniert" es immer noch, dann werden sie nicht aktualisieren. Mit Arbeit meine ich, der Server läuft immer noch. Wir sehen bereits einen Mangel an Unterstützung bei EF. Das ist einfach nicht genug, um sie zu überzeugen, Geld auszugeben.
P. Brian Mackey

1
Damit Sie wissen, können Sie EF mit SQL 2000 verwenden. Der Designer funktioniert nicht, aber das eigentliche Entitätsframework unterstützt SQL 2000. Um die Einschränkung des Designers zu umgehen, können Sie eine lokale Datenbank in SQL 2008 Express mit demselben Schema erstellen Zeigen Sie als SQL 2000-Datenbank auf den Designer, um alle Klassen zu generieren. Wechseln Sie dann in die EDMX-Datei und ändern Sie die Version der Zieldatenbank in 2000, und verweisen Sie die Verbindungszeichenfolge auf Ihre SQL Server 2000-Datenbank. Nicht die beste Lösung, aber wenn Sie nicht aktualisieren können, funktioniert es.
Neil

8

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 verdienen (das ist eine Vereinfachung, aber der wichtigste Punkt ist hier).

Entwicklerzeit kostet Geld. Maschinenleistung kostet auch Geld. Normalerweise sind diese zweiten Kosten viel niedriger als die ersten. Es ist also von großer Bedeutung, über einen lesbaren und wartbaren Code zu verfügen, damit Entwickler die meiste Zeit damit verbringen können, Wert zu liefern.

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

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

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

Manchmal liegt der Wert in dieser Optimierung (denken Sie an latenzkritische Programme wie in Videospielen oder dem Autopiloten eines Flugzeugs). Dies muss jedoch 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 beschleunigen, ohne den Engpass zu identifizieren und an diesem Teil zu arbeiten.

Wenn Sie Ihre Frage so stellen, wie Sie es getan haben, zeigt sich, 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 es schneller war oder nicht. Das haben Sie gefragt, bevor Sie ein Problem hatten. Hier liegt das Problem. Sie haben das Problem der Optimierung falsch behandelt.

Da Wartung und Weiterentwicklung in der Regel wertvoller sind als die Mikrooptimierung, sollten Sie zunächst die richtige Benutzeroberfläche auswählen. 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 als vertrauenswürdig eingestuft zu werden.


"Es gibt immer einen Kompromiss". Wenn Sie eine Variable reduzieren, erhöht sich die andere, wenn sich das Programm auf der Kompromisskurve befindet . Nach meiner Erfahrung befinden sich die meisten Programme bei weitem nicht in der Nähe der Kompromisskurve und bieten viel Raum, um beide Variablen zu reduzieren.
Mike Dunlavey

+1 Wartung und Weiterentwicklung sind wertvoller als Mikrooptimierung. Obwohl ich mir sicher bin, dass es in der Computerbranche nicht nur um Geld geht? Zum Beispiel Open Source, Bildung, Innovation, Governance, Community usw. Ich bin mir sicher, dass Geld an der Wurzel steckt, aber das gilt für die meisten Dinge.
Boz

@Boz kay> Das ist teilweise richtig. Erstens, weil Ihr Chef und Ihre Kunden meistens nichts über diese Dinge wissen und sich um Geld kümmern. Wenn Sie für einige Open-Source-Tools werben möchten, müssen Sie ihnen mitteilen, wie sie die Marke des Unternehmens verbessern oder die Entwicklungskosten senken. Darüber hinaus ist es eine Möglichkeit, Entwickler glücklich zu machen, um einen guten Entwickler in Ihrem Unternehmen zu finden. Guter Entwickler verdient Geld (meistens mit Qualität und Innovation). Am Ende ist Geld der Schlüssel. Und ich schreibe, dass mein Linux-Computer einen großartigen Supporter für freie Software darstellt. Gleiches gilt für die Bildung.
Deadalnix

8

Leistung ist ein Merkmal

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

Konzentrieren Sie sich jedoch erst dann auf die Mikrooptimierung, wenn dies erforderlich ist. Sie können kostengünstigere Optimierungen durchführen. Konzentrieren Sie sich auf die Architektur, nicht auf den Code. Die meisten Websites, die ich gesehen habe und die nur langsam ausgeführt wurden, hatten Probleme auf hoher Ebene (unnötige Webserviceschicht, schlechtes Datenbankdesign, übermäßig komplizierte Architekturen), die nicht nur die Leistung beeinträchtigten, sondern 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 frühzeitig finden.


7

Entwicklerzeit kostet mehr als Computerzeit. Das ist normalerweise das, was Sie optimieren möchten. 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) >= 1ist nicht das Gleiche wie select exists(select 1 from foo).
  • Einige Sprachausdrücke sind einfach deshalb beliebt, weil sie schneller sind. Es ist in Ordnung, diese zu verwenden, da die fließendsten Benutzer der Sprache mit ihnen vertraut sind. (Ihr Beispiel ist ein gutes Beispiel).

7

Was möchten Sie optimieren?

  • Software-Leistung?
  • 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 so üblich. Wenn Benutzer den Unterschied zwischen 50 und 100 Mikrosekunden nicht bemerken, gibt es praktisch keinen Unterschied zwischen den beiden im Code, der nur gelegentlich ausgeführt wird. Hier ist ein Beispiel:

Wenn Sie die Anzeige der Länge der Benutzereingaben und die Zeitdauer, die eine der beiden Routinen benötigt, um diese Länge zu ermitteln, ständig aktualisieren müssen, ist die Zeit zwischen zwei aufeinander folgenden Tastenanschlägen sehr viel kürzer. Dabei spielt es keine Rolle, welche Routine verwendet wird Sie verwenden. Wenn Sie andererseits die Länge von einer Milliarde Zeichenfolgen bestimmen müssen, sollten Sie die Leistungsunterschiede zwischen den verschiedenen Routinen genau beachten. Im ersten Fall möchten Sie möglicherweise Code schreiben, der einfach zu verstehen und zu überprüfen ist. Im zweiten Fall sind Sie möglicherweise bereit, Lesbarkeit gegen Geschwindigkeit zu tauschen.

In jedem Fall sollten Sie, wenn Sie Ihren Code optimieren möchten, vor und nach jeder Änderung ein Profil für Ihren Code erstellen. Programme sind heutzutage so kompliziert, dass es oft schwierig ist zu sagen, wo die Engpässe liegen. Mithilfe der Profilerstellung können Sie den richtigen Code optimieren und anschließend zeigen, dass die von Ihnen vorgenommenen Optimierungen wirklich erfolgreich waren.

Sie haben nicht gesagt, wann Ihr Vater in den Ruhestand ging oder welche Art von Programmierung er durchführte, aber seine Reaktion ist nicht überraschend. In der Vergangenheit waren Speicher, sekundärer Speicher und Rechenzeit alle 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 so zu optimieren, wie es Programmierer niemals schaffen würden. Die Zeiten, in denen Programmierer mit kleinen Tricks ein paar Maschinenanweisungen hier und da bumsen, sind meist vorbei.


1
+1 Ganz zu schweigen davon, dass mobile Geräte in den letzten Jahren wieder stark von Codeoptimierung abhängig geworden sind. Jemand, der keinen optimierten Code schreibt oder zumindest in Betracht zieht, kann es schwierig sein, seine CPU-intensive App auf einem mobilen Gerät reibungslos laufen zu lassen.
Styler

+1 sehr ähnlich Ihrer Liste möglicher Optimierungen. Er benutzte assembly / fortran
Boz

@Styler: Es würde nicht lange dauern, bis mobile Geräte eine Quad-Core-CPU mit GB Speicher haben. Wir haben bereits Dual-Core-Smartphones.
Lie Ryan

@Lie Ryan: Ja, das stimmt, aber wie die meisten Pioniere mussten sie mit Holzbooten fahren;)
Styler

7

Es ist nicht wichtig, beim Schreiben des Codes eine Mikrooptimierung vorzunehmen. Die Optimierung sollte mithilfe eines Profilers erfolgen, der den Code dort optimiert, wo er wichtig ist.

JEDOCH , ein Programmierer sollte versuchen zu tun offensichtlich dumme Dinge zu vermeiden , während Sie den Code zu schreiben.

Führen Sie zum Beispiel keine teuren Wiederholungsoperationen in 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 keine Dinge wie Zeichenfolgenvergleiche oder reguläre Ausdrücke immer wieder durch, wenn Sie eine Ebene höher gehen, den Vergleich durchführen und ihn in eine Ganzzahl, eine Funktionsreferenz oder eine abgeleitete Klasse umwandeln können.

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


Als mir klar wurde, dass ich bei der Bearbeitung meiner Fragen klarer werden muss, sagte ich dasselbe - ich habe es aktualisiert.
Boz

7

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, ist:

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 gesamte Programm nur um 5% beschleunigt.

Aus diesem Grund sagen die Leute immer, es lohnt sich nicht, Teile Ihres Programms zu optimieren, die nicht mehr als ein paar Prozent der Gesamtlaufzeit beanspruchen. Dies ist jedoch nur ein Sonderfall eines allgemeineren Prinzips. Amdahls Gesetz besagt, dass Sie jedes Teil um durchschnittlich 50% beschleunigen müssen, wenn das gesamte Programm doppelt so schnell ausgeführt werden soll . Wenn Sie zwanzig Gigabyte Daten verarbeiten müssen, gibt es nur zwei Möglichkeiten, um diese schneller zu machen als die Zeit, die zum Lesen von zwanzig Gigabyte von der Festplatte benötigt wird: eine schnellere Festplatte beschaffen oder die Daten verkleinern.

Was sagt Amdahls Gesetz über Mikrooptimierungen? Es sagt, dass sie es vielleicht wert sind, wenn sie sich auf der ganzen Linie bewerben. Wenn Sie die Laufzeit aller Funktionen in Ihrem Programm um ein Prozent verkürzen können, herzlichen Glückwunsch! Sie haben das Programm um ein Prozent beschleunigt. War es das wert? Nun, als Compiler-Typ würde ich mich freuen, eine Optimierung zu finden, die dies ermöglicht, aber wenn Sie es von Hand tun, würde ich sagen, suchen Sie nach etwas Größerem.


1
+1 für Amdahl-Zitat, aber ich bin nicht einverstanden mit "Um das gesamte Programm doppelt so schnell laufen zu lassen, müssen Sie jedes Teil beschleunigen". Ich würde sagen, Sie beschleunigen eigentlich kein "Stück". Sie finden eher unnötige Arbeit und beseitigen sie. Besonders Funktionsaufrufe, wenn das Programm größer als ein Spielzeug ist. Ein Großteil der gängigen Überlegungen zur Leistung scheint die Wichtigkeit völlig zu ignorieren, ganze unnötige Zweige des Aufrufbaums (die einzelne Anweisungen sein können) zu finden und sie wegzulassen.
Mike Dunlavey

Der Teufel ist im Wort "Durchschnitt" da. Mathematisch gesehen muss jedes Teil, um ein Programm um 50% zu beschleunigen, durchschnittlich um 50% beschleunigt werden . Wenn Sie das Programm nun in einen Job aufteilen können, der 75% der Laufzeit beansprucht, und einen anderen, der 25% beansprucht, und den ersteren 3x beschleunigen, erhalten Sie insgesamt 50%, obwohl Sie den letzteren Job nicht bearbeitet haben. Viel häufiger ist es jedoch, dass es Dutzende von "Jobs" gibt, die jeweils weniger als 5% der Laufzeit beanspruchen - und dann müssen Sie viele davon beschleunigen oder loswerden.
zwol

Ich denke, es gibt einen noch häufigeren Fall. Es gibt einen "Job", der 50% der Zeit in Anspruch nimmt, den Sie jedoch nicht benötigen. Entfernen Sie ihn also vollständig, indem Sie die Gesamtzeit um diesen Betrag reduzieren und dann wiederholen. Ich weiß, dass das schwer zu akzeptieren ist - dass Programme große Teile der Zeit damit verbringen können, Dinge zu tun, die (im Nachhinein) absolut unnötig sind. Aber hier ist mein kanonisches Beispiel .
Mike Dunlavey

6

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

Wenn Sie Software testen und erweitern, werden Sie wahrscheinlich durch Mikrooptimierungen verletzt, da sie das Lesen von Code erschweren und sogar ihre eigenen Fehler einführen, die behoben werden müssen, zusammen mit allem anderen, das behoben werden muss.

Wenn Sie tatsächlich Beschwerden von Benutzern über langsamen Code erhalten, sind diese möglicherweise eine Überlegung wert, aber nur, wenn alles andere behoben 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, mit der Verwendung von Mikrooptimierungen im Code zu beginnen. Es besteht jedoch die Möglichkeit, dass andere Änderungen (z. B. besserer Code, besserer Algorithmus usw.) Sie in Mitleidenschaft ziehen Dies ist eher ein Leistungsgewinn als eine Mikrooptimierung.


5

Die Ausführungsgeschwindigkeit ist einer von vielen Faktoren, die zur Qualität eines Programms beitragen. Oft steht die Geschwindigkeit in umgekehrter Beziehung zur Lesbarkeit / Wartbarkeit. In fast allen Fällen muss der Code für den Menschen lesbar sein, damit der Code beibehalten werden kann. Die Lesbarkeit kann nur dann beeinträchtigt werden, wenn Geschwindigkeit eine wesentliche Voraussetzung ist. Die Forderung, 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, an das Sie sich erinnern sollten, 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 einer Ausführungszeit von 0,5 Sekunden und einer Ausführungszeit von 1 Sekunde bei CRUD-Operationen so gut wie nie bemerken. Sie müssen also nicht in ein Assembly-Interop-Hackfest gehen, um diese 0,5 Sekunden zu erreichen. Ja, ich könnte mit einem 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 ist.Wenn Sie Code unnötig mikrooptimieren, ist dies genau das, was Sie tun: Hinzufügen unnötiger Komplexität und Kosten, um ein überflüssiges Ziel zu erreichen.


5

Mikrooptimierung ist wichtig, wenn Sie eine Einschränkung treffen. 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. Aber selbst dort bringt Sie die Mikrooptimierung nur so weit. Sie können Ihren Weg aus einem schlechten Design nicht mikrooptimieren. Der Punkt über gutes Design in einem System ist, dass Sie über das System als Ganzes 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 den Vaxen oder PDP-11 von früher ziemlich nahe kommen können , sodass diese Probleme früher häufiger auftraten. Auf einem modernen Allzwecksystem, das moderne allgemeine kommerzielle Datenverarbeitung ausführt, ist eine Mikrooptimierung selten. Dies ist wahrscheinlich ein Grund, warum Ihr Vater die Position einnimmt, die er einnimmt.

Es spielt jedoch keine Rolle, ob Sie es mit Nanosekunden, Millisekunden, Sekunden oder Stunden zu tun haben. Die Probleme sind die gleichen. Sie müssen im Zusammenhang mit dem System und dem, was Sie erreichen möchten, bewertet werden.

Dies ist ein Beispiel aus einer kürzlich gestellten Frage zu Stack Overflow für einen Fall, in dem eine Mikrooptimierung erforderlich war: Open-Source-Videocodierer für ein eingebettetes System .


4

Das größte Problem bei der Mikrooptimierung ist, dass Sie einen Code schreiben müssen, 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, benötigen Sie viel Zeit, um gegen etwas anzukämpfen, das nicht wirklich wichtig ist.

Ein besserer Ansatz besteht darin, einen saubereren Code zu erstellen, der einfacher zu warten ist. Wenn Sie Leistungsprobleme haben, 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 Mikrooptimierungen keine Entschuldigung dafür sind, dummen Code zu schreiben.


4

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

Die Umweltfaktoren stehen hier außer Frage, diese Server sind sowieso rund um die Uhr in Betrieb und wenn sie tatsächlich etwas verarbeiten, ist es nur wichtig, wenn es sich wirklich um eine Aufgabe handelt, die sehr lange ausgeführt wird.

Höchstwahrscheinlich wird das Licht in Ihrem Büro und die Energie, die unsere Computer verbraucht haben, während wir alle Fragen und Antworten getippt haben, viel mehr Energie verbrauchen, als jede Art von Mikrooptimierung, die Sie vernünftigerweise auf Ihre Anwendungen anwenden können, jemals einsparen wird.


+1 Licht ausschalten oder Fragen nicht beantworten.
Boz

4

Sie sollten den besten, einfachen 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, besteht darin, zu vermeiden, mit schlechten Laufzeitmerkmalen zu beginnen. Wählen Sie BubbleSort nicht blind, wenn Sie wissen, dass Sie große Datenmengen haben werden. Es ist jedoch in Ordnung für die gelegentliche Art von 10 Elementen.

DANN können Sie mit der Optimierung beginnen (was normalerweise die Kosten für die Lesbarkeit sind), wenn die Profiling-Zahlen belegen, dass Ihre Wahl des besten einfachen Algorithmus nicht gut genug war.


BubbleSort kann tatsächlich besser sein als QuickSort oder Mergesort, wenn Ihre Daten mit nur wenigen Streuelementen, die nicht zu weit vom endgültigen Ziel entfernt sind, nahezu sortiert sind. Für alle anderen Aufgaben sollten Sie die integrierte Sortierfunktion verwenden, die Ihre Programmiersprache für Sie bereitstellt. Dies ist der einfachste Einstieg (und die integrierte Sortierfunktion in den meisten Sprachen bietet eine gute Leistung). SCHLECHTER HINWEIS: Beginnen start out with bad runtime characteristicSie nicht absichtlich mit einem schlechten Laufzeitverhalten.
Lie Ryan

@Lie, wenn Sie WISSEN, dass Ihre Daten fast sortiert sind und Sie daher bubblesort verwenden können, wählen Sie Ihren Algorithmus nicht genau blind aus ... Auch danke, dass Sie auf den Tippfehler hingewiesen haben.

4

Ich habe es schon einmal gesagt, und ich sage es hier: "Vorzeitige Optimierung ist die Wurzel allen Übels" . Dies sollte eine der Regeln sein, die den Programmierer in den Mittelpunkt stellen.

Code kann bis zu einem gewissen Punkt immer schneller sein als es derzeit ist. Wenn Sie die Baugruppe nicht mit einem bestimmten Chip von Hand verpacken, kann durch Optimierung immer etwas erreicht werden. Wenn Sie jedoch nicht für alles, was Sie tun, von Hand verpacken möchten, muss es ein quantitatives Ziel geben, bei dem Sie nach dem Erreichen des Ziels "das ist genug" sagen und die Optimierung beenden, auch wenn Sie immer noch einen krassen Leistungssauger anstarren dir ins gesicht.

Schöner, eleganter, extrem performanter Code ist nutzlos, wenn er nicht funktioniert (und mit "funktionieren" meine ich die erwartete Ausgabe bei allen erwarteten Eingaben). Daher sollte das Produzieren von Code, der funktioniert, IMMER die erste Priorität sein. Nachdem es funktioniert, bewerten Sie die Leistung, und wenn es Ihnen fehlt, suchen Sie nach Möglichkeiten, die Leistung zu verbessern, bis zu dem Punkt, an dem es gut genug ist.

Es gibt einige Dinge, die Sie im Vorfeld entscheiden müssen, um die Leistung zu beeinträchtigen. Grundlegende Entscheidungen wie die Sprache / Laufzeit, mit der Sie diese Lösung implementieren. Viele davon wirken sich um ein Vielfaches auf die Leistung aus, als wenn eine Methode gegen eine andere aufgerufen wird. Ehrlich gesagt ist PHP als Skriptsprache bereits ein Leistungstreffer, aber da in C / C ++ nur sehr wenige Skriptseiten von Grund auf 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ächster Leistungskiller. Durch die Optimierung des Lese- und Schreibvorgangs auf Festplatte, seriellen Anschlüssen, Netzwerk-Pipes usw. wird die Laufzeit des Programms in der Regel um viele Größenordnungen verbessert, selbst wenn die Algorithmen für die E / A-Vorgänge effizient waren. Reduzieren Sie danach die Big-O-Komplexität des Algorithmus selbst, und wenn Sie dies unbedingt tun müssen, können Sie eine "Mikrooptimierung" durchführen, indem Sie kostengünstigere Methodenaufrufe auswählen und andere esoterische Entscheidungen auf niedriger Ebene treffen.


2
+1 Das Produzieren von Code, der funktioniert, sollte IMMER die erste Priorität haben.
Boz

2
@Keith, eigentlich hat Knuth es zuerst gesagt, und er hat noch einiges mehr gesagt.

"Lass es funktionieren, dann lass es so schnell funktionieren, wie es funktionieren muss", Anon.
John Saunders

1
Eigentlich ist Religion die Wurzel allen Übels, aber ich schweife ab.
Thomas Eding

4

Sie erwähnen, dass Ihr Vater ein pensionierter Programmierer ist. Programmierer, die in der Mainframe-Welt arbeiteten, mussten sich sehr um die Leistung sorgen. Ich kann mich erinnern, eine US Navy-Aktivität untersucht zu haben, bei der der Mainframe auf 64 KB Arbeitsspeicher pro Benutzer beschränkt war. In dieser Programmierwelt muss man jedes noch so kleine Stück herausfinden.

Die Dinge sind jetzt völlig anders und die meisten Programmierer müssen sich nicht mehr so ​​sehr um Mikrooptimierungen kümmern. Programmierer für eingebettete Systeme tun dies jedoch immer noch, und Datenbankmitarbeiter müssen immer noch optimierten Code verwenden.


3

Code sollte so geschrieben werden, dass absolut klar ist, was er tut. Dann, wenn und nur wenn es zu langsam ist, gehen Sie zurück und beschleunigen Sie es. Code kann immer 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

Es ist wichtig, wenn:

1) Jemandes Leben hängt von Ihrem Code ab. Eine Funktion, deren Ausführung im Pulsmesser 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. Natürlich möchten Sie diese verwenden. Wenn sich dies jedoch auf die Lesbarkeit auswirkt, halten Sie inne - Sie werden nicht viel davon profitieren und es könnte auf lange Sicht sogar länger dauern, bis Sie das Debuggen abgeschlossen haben.


2
Nur ein paar kleine Punkte zu Ihrem Beispiel: Eine Funktion in einem Herzfrequenzmonitor, die 25 ms dauert, wäre kein Problem, solange andere notwendige Aufgaben mit der erforderlichen Reaktionszeit ausgeführt werden könnten. Interrupts sind dafür gut. Und eine Latenz von 25 ms für etwas, das nur reale Ereignisse überwacht, um ein Display für den menschlichen Verzehr zu aktualisieren, ist wahrscheinlich kein Problem.
9.

3

Ist die Mikrooptimierung beim Codieren wichtig?

Nein, da es Plattformen wie JVM und .NET gibt, auf denen Code für eine virtuelle Maschine geschrieben ist, und der Versuch, die Ausführung zu optimieren, möglicherweise nicht so gut funktioniert, wie es auf dem Desktop eines Entwicklers auf einem Server erforderlich ist. Schauen Sie sich an, wie weit einige dieser Teile der High-Level-Software von der Hardware entfernt sind. In Anbetracht der Vielfalt der Hardware ist zu bedenken, wie realistisch es ist, Code für bestimmte Chips wie eine CPU oder eine GPU zu optimieren, wenn ein neues Modell wahrscheinlich in weniger als einem Jahr herauskommt.

Eine weitere zu berücksichtigende Frage ist die Leistung, gemessen an welcher Metrik: Ausführungsgeschwindigkeit, bei der Ausführung verwendeter Speicher, Geschwindigkeit der Entwicklung neuer Features, Größe der Codebasis auf einem Server in kompilierten oder dekompilierten Formen, Skalierbarkeit, Wartbarkeit usw .? Wenn man es allgemein nimmt, 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 in irgendeiner Weise gemessen werden kann.


Einige Mikrooptimierungen funktionieren möglicherweise und einige funktionieren möglicherweise nicht. Hier kann man sich fragen, wie lohnend es ist, solche Arbeiten im Vergleich zu anderen Arbeiten durchzuführen, die als viel prioritärer angesehen werden, wie beispielsweise neue Funktionen oder das Beheben von Fehlern. Die andere Frage wäre, ob ein Upgrade der Hardware oder Software möglicherweise auch einige dieser Optimierungen beeinträchtigt.


1
Beachten Sie, dass Sie können absolut Mikro-Optimierungen auf Plattformen wie die JVM und .NET zu tun, sie nur leicht unterschiedliche Formen annehmen. Das Gleiche gilt jedoch, wenn Sie einen alten, einfachen C-Compiler mit einem moderneren, hochoptimierenden Compiler vergleichen: Die Optimierungen, die der Benutzer vornehmen kann, sehen anders aus.
Joachim Sauer

1

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

Wenn es zwei Möglichkeiten gibt, die gleiche Aufgabe auszuführen, wobei eine schneller als die andere ist und beide die gleiche Lesbarkeit aufweisen, sollten Sie die schnellere verwenden. Immer. Und das ist eine gute Programmierung. Es gibt keinen Grund, keinen besseren Algorithmus zu verwenden, um ein Problem zu lösen. Und selbst das Dokumentieren ist ganz einfach: Geben Sie den Namen des Algorithmus an, und jeder kann ihn googeln und weitere Informationen darüber finden, wie er funktioniert.

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

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

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


1

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 müde, Blog-Posts über unsinnige Mikrooptimierungen wie das Ersetzen von print durch echo, ++ $ i durch $ i ++ oder doppelte Anführungszeichen durch einfache Anführungszeichen zu lesen. Warum? Weil 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 Startseite haben.

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

Ich habe eine neue WordPress-Installation ausprobiert. 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 eine Operation unter Millionen, verschlechtert jedoch die Lesbarkeit.


1

Andere Antworten stimmen auf das Geld. Aber ich werde einen weiteren Punkt hinzufügen, an dem man unterscheiden muss, was vorzeitige Optimierung / Mikrooptimierung ist, und Performant-Code schreiben muss, der ein Verständnis des Verhaltens der Sprache / Framework-Konstrukte widerspiegelt (Entschuldigung, für das letzte Wort konnte kein Wort gefunden werden). . Der letzte ist eine gute Codierungspraxis und sollte im Allgemeinen durchgeführt werden!

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örsagen und undokumentierten Verhaltensweisen optimieren. Wenn es dokumentiert ist und etwas effizienter / logischer 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, gute Geschäfte zu machen, aber ich mache immer noch das letztere, nicht das erstere, wenn es die Lesbarkeit nicht völlig zunichte macht. Ja, Lesbarkeit / Wartbarkeit ist von größter Bedeutung und es geht darum, wo Sie die Grenze ziehen.

Ich werde die von anderen hier gemachten Punkte als die Sinnlosigkeit von sowohl guten als auch schlechten Optimierungen wiederholen:

  1. Ihre Abhängigkeiten von einem bestimmten Problem können sich ändern, und jeder Zeitaufwand für die Optimierung, bevor der logische Abschnitt Ihrer Anwendung abgeschlossen ist, ist Zeitverschwendung. Ich meine, relativ früh zu optimieren. Heute haben Sie eine List<T>und zu dem Zeitpunkt, an dem Ihre App ausgeliefert wurde, mussten Sie diese ändern. LinkedList<T>Jetzt war das Benchmarking eine Verschwendung von Zeit und Mühe.

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

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

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

Die Nachteile einer schlechten Optimierung sind insbesondere:

  1. Es gibt Ihnen nicht oft die Leistung, die Sie erwarten. Siehe diese Frage zu SO, wo Optimierungen fehlgeschlagen sind . In der Tat kann es nachteilige Auswirkungen haben. Das ist das Problem mit undokumentiertem Verhalten.

  2. Die meisten modernen Compiler erledigen das sowieso für Sie.

Ich gebe einige Beispiele für schlechte und gute Optimierung:

Das Schlechte -

  1. Verwendung von kleineren Integer-Typen anstelle von Int32.

  2. ++i verwendet statt i++

  3. forstatt foreach(das Schlimmste, das ich gesehen habe, besiegt die Logik total)

  4. Ausgeschlossene Variablen vermeiden

    string p;
    foreach (var item in collection)
        p = ...;
    
  5. Verwenden von charanstelle von String während der String-Verkettung, wie:

    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 von

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

    DirectoryInfo.EnumerateFiles();
    

    Anstatt von

    DirectoryInfo.GetFiles();
    
  3. Zweistufiges Casting:

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

    Anstatt von

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

    if (counter < X || expensiveFunction())
    

    Anstatt von

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

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

    Anstatt von

    void M(object o)
    {
    
    }
    

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


1

"Wert es" braucht Kontext, wie viel einfacher es ist, zu schreiben und zu lesen und zu pflegen, im Vergleich dazu, wie viel schneller es dem Benutzer etwas deutlich reaktionsfähiger macht , interaktiv, und weniger Zeit für das Warten benötigt.

Ein paar Pfennige zu sparen, um eine Dose Soda zu kaufen, nützt mir nicht viel, wenn ich eine Strecke zurücklegen muss, um diese Pfennige zu sparen, zumal ich heutzutage selten Soda trinke. Ein paar Cent pro Dose bei einem Einkauf von einer Million Dosen Limonaden zu sparen, könnte ein riesiges Geschäft sein.

In der Zwischenzeit spart man ein paar Cent, wenn zwei Leute direkt neben mir sind und einer genau dasselbe für ein paar Cent billiger anbietet und der andere nicht, und ich wähle den teureren, weil mir der Hut besser gefällt, wie ein dummer Fall der Pessimisierung.

Was ich oft als "Mikrooptimierungen" bezeichne, scheint merkwürdigerweise frei von Messungen, Kontext und Benutzerdiskussion zu sein, wenn es absolut alle drei gibt, die solche Optimierungen in Betracht ziehen, wenn sie nicht einfach anzuwenden sind. Für mich bezieht sich eine richtige Mikrooptimierung heutzutage auf Dinge wie Speicherlayouts und Zugriffsmuster, und obwohl sie im Fokus "Mikro" zu sein scheinen, sind sie in ihrer Wirkung nicht Mikro.

Es ist mir vor nicht allzu langer Zeit gelungen, eine Operation von 24 Sekunden auf 25 Millisekunden (etwa 960-mal schneller) mit identischen Ausgaben (gesichert durch automatisierte Tests) zu reduzieren, ohne die algorithmische Komplexität für die volumetrische Wärmediffusionshautbildung zu ändern "Mikrooptimierungen" (die größten resultierten aus einer Änderung des Speicherlayouts, die auf ungefähr 2 Sekunden zurückging, der Rest waren Dinge wie SIMD und die 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: Bildbeschreibung hier eingeben

Nachdem ich es von 24 Sekunden auf 25 Millisekunden "mikrooptimiert" hatte, war das ein Grundstein für den 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 keine Fortschrittsanzeige und solche Dinge mehr benötigte. Es wurde einfach alles interaktiv. Das mag also eine "Mikrooptimierung" in dem Sinne sein, dass alle Verbesserungen ohne eine Verbesserung der algorithmischen Komplexität erfolgten, aber es war eine eher "Megaoptimierung" in der Wirkung, die einen ehemals schmerzhaften, nicht interaktiven Prozess ausmachte in eine interaktive Echtzeitumgebung, die die Arbeitsweise der Benutzer grundlegend verändert hat.

Messung, Benutzeranforderungen, Kontext

Ich mochte Roberts Kommentar hier wirklich und habe vielleicht 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, die es erforderlich macht, mir aus dem Weg zu gehen.

Und ich möchte nicht nur die Messungen betonen, sondern auch die benutzerseitige Seite. Ich bin insofern ein Kuriosum, als ich zuerst als Benutzer / Fan, dann als Entwickler zu meinem derzeitigen Fach (und früher zu Gamedev) kam. Daher war ich nie so begeistert von den üblichen Dingen, die Programmierer zum Lösen technischer Rätsel anregen. Ich fand sie eine Last, würde sie aber durch den Benutzer-End-Traum tragen, den ich mit anderen Benutzern teilte. Aber das hat mir geholfen, um sicherzustellen, dass ich, wenn ich etwas optimiere, einen echten Einfluss auf die Benutzer mit echten Vorteilen habe. Es ist mein Schutz vor zielloser Mikrooptimierung.

Das ist meiner Meinung nach genauso wichtig wie der Profiler, weil ich Kollegen hatte, die Dinge wie die mikrooptimierte Unterteilung eines Würfels in eine Milliarde Facetten taten, um sich nur an realen Produktionsmodellen wie Charakteren und Fahrzeugen zu verschlucken. Ihr Ergebnis war in gewissem Sinne beeindruckend, aber für die tatsächlichen Benutzer nahezu nutzlos, da sie Profile erstellten und Fälle maßen und vergleichten, die nicht mit tatsächlichen Anwendungsfällen übereinstimmten. Deshalb ist es so wichtig zu verstehen, worauf es den Benutzern ankommt, indem sie lernen, die Software wie eine zu denken und zu verwenden oder mit ihnen zusammenzuarbeiten (im Idealfall beides, aber zumindest mit ihnen zusammenzuarbeiten).


2
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.
Robert Harvey

1
@RobertHarvey Es war irgendwie der Punkt , den ich hatte gehofft , zu machen, da das, was manche Leute nennen „Mikro-Optimierung“ ist nicht unbedingt mikroskopisch in der Tat, aber es ist so abhängig von Kontext, Messungen usw. issetvs. strlenmehr miniscule scheint Fokus in Ohne Kontext und Maße. :-D
Dragon Energy

1
@RobertHarvey Ich hatte gehofft, wenn auch indirekt, zu sagen, dass bei einem negativen Kontext für "Mikrooptimierungen" dieser Typ tendenziell ohne diese Messungen, Kontexte und Benutzerendbedürfnisse auskommt. Ich könnte auch über den letzten Fall weitermachen, da ich einen Kollegen hatte, der die Hölle aus etwas heraus optimierte, das cool war, außer dass niemand es benutzte. Ich denke sogar, dass eine ordnungsgemäße Optimierung ein gewisses Verständnis der Benutzer erfordert. Andernfalls könnten wir Dinge profilieren und optimieren, die den Benutzern nicht wichtig sind.
Dragon Energy

1
Einige Optimierungen werden durch dringende Bedürfnisse vorangetrieben, während andere durch Neugier (intellektuelles Streben und Abenteuerlust) vorangetrieben werden. Wir brauchen beides. In der Geschichte von Dragon Energy handelte es sich wahrscheinlich nicht um ein "dringendes Bedürfnis", da sich die Künstler anscheinend nicht laut darüber beschwerten, bis 24 Sekunden nach jeder Bearbeitung keine Rendering-Ergebnisse zu sehen. Tatsächlich wissen Benutzer möglicherweise nicht, wie schnell es gewesen sein könnte, bis ein Programmierer alle Anstrengungen unternommen hat, um den Geschwindigkeitsrekord zu übertreffen. Die Beschränkung auf die getriebene Nachfrage macht geschäftlich Sinn, es werden jedoch einige erstaunliche Optimierungsmöglichkeiten oder Änderungen verpasst.
rwong

1
Apropos Geschäftssinn, es gibt auch die Frage der Monetarisierung. Jeder Schritt (z. B. ein Programmierer, der an der Leistungsoptimierung arbeitet) kostet Geld, und die Kosten müssen wieder hereingeholt werden, um geschäftlich sinnvoll zu sein. Man muss sich also fragen, ob die bahnbrechende Geschwindigkeitsverbesserung "verkauft" werden kann oder wie viel Geld "gespart" würde, wenn der Programmierer die Zustimmung eines Geschäftsführers einholen muss.
rwong

0

Ich werde es so ausdrücken - Mikrooptimierung ist ein Prozess der Optimierung von etwas, das überhaupt kein Engpass ist. Wenn Ihr Programm beispielsweise zwei Funktionen A und B aufruft und die Ausführung von A 100 Millisekunden dauert und B 2 Mikrosekunden dauert und Sie die Funktion B weiter optimieren. Das ist nicht nur unwichtig, das ist absolut falsch. Die Optimierungsfunktion B heißt jedoch Optimierung und nicht Mikrooptimierung. Die Wichtigkeit 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 wenn Sie Ihr Programm ohne diese Funktionalität schneller machen, dann optimieren Sie es. Andernfalls verfolgen Sie die Funktionalität. Ebenfalls, Erfahrene Programmierer, die sich auf Leistung konzentrieren, verbringen nicht viel Zeit mit der Optimierung. Sie 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.


Dieser Beitrag ist ziemlich schwer zu lesen (Textwand). Hätten Sie etwas dagegen bearbeiten sie in eine bessere Form ing?
gnat
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.