"Vorzeitige Optimierung ist die Wurzel allen Übels" haben fast alle von uns gehört / gelesen. Ich bin gespannt, welche Art von Optimierung nicht verfrüht ist, dh in jeder Phase der Softwareentwicklung (High-Level-Design, Detail-Design, High-Level-Implementierung, Detail-Implementierung usw.), welchen Grad an Optimierung wir in Betracht ziehen können, ohne dass dies auf die dunkle Seite übergeht.
optimization
Gaurav
quelle
quelle
Antworten:
Wenn Sie sich auf Erfahrung stützen? Nicht böse "Jedes Mal, wenn wir X gemacht haben, haben wir einen brutalen Leistungseinbruch erlitten. Lassen Sie uns dieses Mal entweder X optimieren oder ganz vermeiden."
Wann ist es relativ schmerzfrei? Nicht böse "Das als Foo oder Bar umzusetzen, wird genauso viel Arbeit kosten, aber theoretisch sollte Bar viel effizienter sein. Lassen Sie es uns blockieren."
Wenn Sie beschissene Algorithmen vermeiden, die sich schrecklich skalieren lassen? Nicht böse "Unser technischer Leiter sagt, dass unser vorgeschlagener Algorithmus zur Pfadauswahl in Fakultätszeit abläuft. Ich bin mir nicht sicher, was das bedeutet, aber sie schlägt vor, dass wir Seppuku begehen, um überhaupt darüber nachzudenken. Lassen Sie uns etwas anderes überlegen."
Das Böse entsteht, wenn Sie viel Zeit und Energie aufwenden, um Probleme zu lösen, von denen Sie nicht wissen, dass sie tatsächlich existieren. Wenn die Probleme definitiv existieren oder wenn die Phantom-Psudo-Probleme billig gelöst werden können, verschwindet das Böse.
Steve314 und Matthieu M. heben Punkte in den Kommentaren hervor, die berücksichtigt werden sollten. Grundsätzlich lohnen sich einige "schmerzlose" Optimierungen auch nicht, da die von ihnen angebotene einfache Leistungssteigerung nicht die Verschleierung des Codes wert ist. Sie duplizieren Verbesserungen, die der Compiler bereits durchführt, oder beides. In den Kommentaren finden Sie einige nette Beispiele für allzu kluge Nichtverbesserungen.
quelle
i
es nicht signiert ist,i / 2
kann es durch ersetzt werdeni >> 1
. Es ist schneller. Aber es ist auch kryptischer (nicht jeder wird den Effekt bemerken, auch diejenigen, die Zeit verlieren). Aber das Schlimmste ist, dass der Compiler es trotzdem macht. Warum also den Quellcode verschleiern?i/2
in der Tat ein Hot Spot ist und dieser (unglaublich, aber nehmen wir an)i>>1
ihn schneller macht, tun Sie es und kommentieren Sie, dass diese Profilerstellung gezeigt hat, dass dies schneller ist. Wenn dies tatsächlich irgendwo benötigt wird (was ich bezweifle, da Compiler, wie Matthieu sagte, klug genug sein sollten, dies selbst zu tun), werden Anfänger etwas lernen, wenn dies nicht der Fall ist (was wahrscheinlich ist), warum möchten Sie einstecken ihre Köpfe mit unnötiger Folklore?Der Anwendungscode sollte nur so gut wie nötig sein, der Bibliothekscode sollte jedoch so gut wie möglich sein, da Sie nie wissen, wie Ihre Bibliothek verwendet wird. Wenn Sie also Bibliothekscode schreiben, muss dieser in jeder Hinsicht gut sein, sei es in Bezug auf Leistung, Robustheit oder eine andere Kategorie.
Außerdem müssen Sie beim Entwerfen Ihrer Anwendung und beim Auswählen von Algorithmen über die Leistung nachdenken . Wenn es nicht als performant ausgelegt ist, kann es durch keinen Grad an Hackerleistung nachträglich performant gemacht werden und keine Mikrooptimierungen überwiegen einen überlegenen Algorithmus.
quelle
Die Art, die aufgrund bekannter Probleme auftritt.
quelle
Es ist schwer zu sagen, was gut und was böse ist. Wer hat das Recht? Wenn wir uns die Natur ansehen, scheinen wir auf das Überleben programmiert zu sein, mit einer umfassenden Definition von "Überleben", die die Weitergabe unserer Gene an die Nachkommen einschließt.
Zumindest nach unseren Grundfunktionen und unserer Programmierung würde ich sagen, dass Optimierung nicht schlecht ist, wenn sie sich am Ziel der Reproduktion ausrichtet. Für die Jungs gibt es die Blondinen, Brünetten, Rothaarigen, viele schöne. Für Mädchen gibt es Männer, und einige von ihnen scheinen in Ordnung zu sein.
Vielleicht sollten wir auf diesen Zweck hin optimieren, und dort hilft es, einen Profiler zu verwenden. Mit dem Profiler können Sie Ihre Optimierungen und Zeit effektiver priorisieren und erhalten detaillierte Informationen zu Hotspots und deren Ursachen. Dies gibt Ihnen mehr Freizeit für die Fortpflanzung und ihr Streben.
quelle
Das vollständige Zitat definiert, wann die Optimierung nicht verfrüht ist:
Sie können kritischen Code auf viele Arten identifizieren: Kritische Datenstrukturen oder Algorithmen (z. B. stark genutzt oder der "Kern" des Projekts) können wichtige Optimierungen liefern, viele kleinere Optimierungen werden durch Profiler identifiziert und so weiter.
quelle
Sie sollten auf der Grundlage Ihrer Erfahrungen in jedem Fall eine "ausreichend gute" Lösung wählen.
Der Optimierungsspruch bezieht sich auf das Schreiben von "komplexerem Code als" gut genug ", um ihn schneller zu machen", bevor man tatsächlich weiß, dass er notwendig ist, wodurch der Code komplexer als nötig wird. Komplexität ist das, was die Dinge schwer macht, also ist das keine gute Sache.
Dies bedeutet, dass Sie keine überkomplexe Sortierroutine wählen sollten, die 100-GB-Dateien durch transparentes Wechseln auf die Festplatte sortieren kann, wenn eine einfache Sortierung durchgeführt wird. Sie sollten jedoch auch eine gute Wahl für die einfache Sortierung treffen. Blinde Auswahl von "Blasensortierung" oder "Wähle alle Einträge nach dem Zufallsprinzip aus und überprüfe, ob sie in der richtigen Reihenfolge sind. Wiederholen". ist selten gut.
quelle
Meine allgemeine Faustregel: Wenn Sie nicht sicher sind, ob Sie die Optimierung benötigen, gehen Sie davon aus, dass Sie dies nicht tun. Denken Sie jedoch daran, wann Sie optimieren müssen. Es gibt jedoch einige Probleme, über die Sie im Vorfeld Bescheid wissen können. Dies beinhaltet normalerweise die Auswahl guter Algorithmen und Datenstrukturen. Wenn Sie beispielsweise die Mitgliedschaft in einer Sammlung überprüfen müssen, können Sie ziemlich sicher sein, dass Sie eine bestimmte Datenstruktur benötigen.
quelle
Nach meiner Erfahrung liegt die Antwort in der detaillierten Implementierungsphase in der Profilerstellung des Codes. Es ist wichtig zu wissen, was schneller sein muss und was akzeptabel schnell ist.
Es ist auch wichtig zu wissen, wo genau sich der Leistungsengpass befindet - die Optimierung eines Teils des Codes, der nur 5% der Gesamtlaufzeit benötigt, nützt nichts.
Die Schritte 2 und 3 beschreiben eine nicht vorzeitige Optimierung:
quelle
Es ist keine Optimierung, wenn Sie Dinge auswählen, die sich nur schwer ändern lassen, z. B .: Hardware-Plattform.
Die Auswahl von Datenstrukturen ist ein gutes Beispiel - entscheidend, um sowohl funktionale als auch nicht funktionale (Leistungs-) Anforderungen zu erfüllen. Nicht leicht zu ändern und doch wird es alles andere in Ihrer App fahren. Ihre Datenstrukturen ändern die verfügbaren Algorithmen usw.
quelle
Ich kenne nur einen Weg, um diese Frage zu beantworten, nämlich Erfahrung in der Leistungsoptimierung zu sammeln. Das bedeutet: Schreiben Sie Programme, und suchen Sie nach dem Schreiben nach Beschleunigungen, und wiederholen Sie diese. Hier ist ein Beispiel.
Hier ist der Fehler, den die meisten Leute machen: Sie versuchen, das Programm zu optimieren, bevor sie es tatsächlich ausführen. Wenn sie einen Programmierkurs besucht haben (von einem Professor, der nicht viel praktische Erfahrung hat), werden sie eine Brille in O-Farben haben und sie werden denken, darum geht es . Es ist alles das gleiche Problem, vorherige Optimierung. **
Jemand sagte: Mach es erst richtig, dann mach es schnell. Sie hatten Recht.
Aber jetzt zum Kicker: Wenn Sie dies einige Male getan haben, erkennen Sie die dummen Dinge, die Sie zuvor getan haben und die Geschwindigkeitsprobleme verursachen, und vermeiden sie instinktiv. (Dinge wie die Überlastung Ihrer Klassenstruktur, das Überfüllen mit Benachrichtigungen, das Verwechseln der Größe von Funktionsaufrufen mit ihren Zeitkosten, die Liste geht weiter und weiter ...) Sie vermeiden diese instinktiv, aber raten Sie mal, wie es für die Geringeren aussieht. erlebt: vorzeitige optimierung!
Also diese albernen Debatten gehen weiter und weiter :)
** Eine andere Sache, die sie sagen, ist, dass Sie sich keine Sorgen mehr machen müssen, weil Compiler so gut sind und Maschinen heutzutage so schnell sind. (KIWI - Kill It With Iron.) Es gibt keine exponentiellen Hardware- oder Systembeschleunigungen (durchgeführt von sehr intelligenten, hart arbeitenden Ingenieuren), die möglicherweise exponentielle Software-Verlangsamungen (durchgeführt von Programmierern, die so denken) ausgleichen könnten.
quelle
Wenn es die Anforderungen oder der Markt speziell verlangen.
Beispielsweise ist die Leistung in den meisten Finanzanwendungen eine Anforderung, da eine geringe Latenz von entscheidender Bedeutung ist. Abhängig von der Art des gehandelten Instruments kann die Optimierung von der Verwendung nicht sperrender Algorithmen in einer Hochsprache über die Verwendung einer Niedrigsprache bis hin zum Extrem gehen - Implementierung der Algorithmen zur Ordnungsanpassung in Hardware selbst (z. B. mit FPGA) ).
Ein anderes Beispiel wären einige Arten eingebetteter Geräte. Nehmen Sie zum Beispiel die ABS-Bremse; Erstens gibt es die Sicherheit, wenn Sie die Pause schlagen, sollte das Auto langsamer werden. Aber es gibt auch Leistung, Sie möchten keine Verzögerungen, wenn Sie die Pause treffen.
quelle
Die meisten Leute würden die Optimierung als verfrüht bezeichnen, wenn Sie etwas optimieren, das aufgrund der Leistung nicht zu einem "Soft Failure" (es funktioniert, aber es ist immer noch nutzlos) des Systems führt.
Beispiele aus der Praxis.
Wenn die Ausführung meiner Blasensortierung 20 ms dauert, wird die Optimierung auf 1 ms Quicksort den Gesamtnutzen trotz einer Leistungssteigerung von 2000% nicht in nennenswerter Weise verbessern.
Wenn das Laden einer Webseite 20 Sekunden dauert und wir sie auf 1 Sekunde verringern, kann dies den Nutzen der Website von 0 auf nahezu unendlich erhöhen. Grundsätzlich ist etwas, das kaputt war, weil es zu langsam war, jetzt nützlich.
quelle
Welche Art von Optimierung ist nicht verfrüht?
Eine Optimierung, die ein bekanntes Leistungsproblem mit Ihrer Anwendung behebt, oder eine Optimierung, die es Ihrer Anwendung ermöglicht, gut definierte Akzeptanzkriterien zu erfüllen.
Nachdem die Lösung ermittelt wurde, sollte einige Zeit in Anspruch genommen und der Leistungsvorteil gemessen werden.
(dh es ist nicht - "Ich denke, dieses Teil des Codes scheint langsam zu sein, ich werde X ändern, um stattdessen Y zu verwenden, und das wird schneller sein").
Ich habe viel vorzeitige "Optimierung" erlebt, die den Code letztendlich langsamer gemacht hat - in diesem Fall meine ich "nicht durchdacht". Die Leistung sollte vor und nach der Optimierung verglichen werden, und nur Code, der die Leistung tatsächlich verbessert, sollte beibehalten werden.
quelle
Wahr. Leider ist es auch eines der am häufigsten (in böswilliger Absicht) missbrauchten Programmierzitate aller Zeiten. Seit Donald Knuth das Mem geprägt hat, lohnt es sich, einen originellen Kontext aus dem Zitat hinzuzufügen:
Beachten Sie, dass Knuth speziell über die Ausführungsgeschwindigkeit in der Laufzeit sprach .
Außerdem schrieb er den Artikel 1974, als alle Maschinenressourcen, bei denen eine hohe und negative Korrelation zwischen Ausführungsgeschwindigkeit und Wartbarkeit des Programms (höhere Geschwindigkeit - weniger wartbar) bestand, wahrscheinlich stärker waren als jetzt.
OK, um Ihre Frage zu beantworten, laut Donald Knuth ist die Optimierung NICHT verfrüht, wenn sie einen schwerwiegenden Leistungsengpass behebt, der identifiziert wurde (idealerweise gemessen und während der Profilerstellung genau bestimmt ).
Wie ich bereits sagte, ist "vorzeitige Optimierung" eines der am häufigsten missbrauchten Memes. Daher wird die Antwort nicht vollständig sein, ohne einige Beispiele von Dingen, die keine vorzeitigen Optimierungen sind, sondern manchmal als solche abgeschüttelt werden:
Weitere Aspekte beziehen sich nicht einmal auf die Ausführungsgeschwindigkeit:
durchdachtes Upfront-Design
statische Eingabe (!)
usw. / jede Form von geistiger Anstrengung
quelle