Tipps zur Optimierung von C # /. NET-Programmen [geschlossen]


78

Es scheint, dass Optimierung heutzutage eine verlorene Kunst ist. Gab es nicht eine Zeit, in der alle Programmierer jede Unze Effizienz aus ihrem Code herausgepresst haben? Tun Sie dies oft, während Sie fünf Meilen im Schnee laufen?

Welche Tipps kennen Sie für einfache (oder möglicherweise komplexe) Änderungen zur Optimierung des C # /. NET-Codes, um eine verlorene Kunst zurückzubringen? Da es eine so breite Sache ist, die davon abhängt, was man erreichen will, würde es helfen, den Kontext mit Ihrem Tipp zu versehen. Zum Beispiel:

  • Wenn Sie viele Zeichenfolgen miteinander verketten, verwenden Sie StringBuilderstattdessen. Siehe Link unten für Vorbehalte dazu.
  • Verwenden Sie string.Comparediese Option , um zwei Zeichenfolgen zu vergleichen, anstatt so etwas zu tunstring1.ToLower() == string2.ToLower()

Der bisherige allgemeine Konsens scheint entscheidend zu sein. Diese Art verfehlt den Punkt: Das Messen sagt Ihnen nicht, was falsch ist oder was Sie dagegen tun müssen, wenn Sie auf einen Engpass stoßen. Ich bin einmal auf den Engpass bei der Verkettung von Zeichenfolgen gestoßen und hatte keine Ahnung, was ich dagegen tun sollte. Daher sind diese Tipps hilfreich.

Mein Punkt, um dies überhaupt zu veröffentlichen, ist es, einen Platz für häufige Engpässe zu haben und wie sie vermieden werden können, bevor sie überhaupt auftreten. Es geht nicht unbedingt um Plug-and-Play-Code, dem jeder blind folgen sollte, sondern vielmehr darum, ein Verständnis dafür zu erlangen, dass über die Leistung zumindest etwas nachgedacht werden sollte und dass einige häufige Fallstricke zu beachten sind.

Ich kann jedoch sehen, dass es nützlich sein kann, auch zu wissen, warum ein Tipp nützlich ist und wo er angewendet werden sollte. Für den StringBuilderTipp habe ich die Hilfe gefunden, die ich vor langer Zeit hier auf Jon Skeets Website gemacht habe .


10
Es ist auch wichtig, zwischen Optimierung und Lesbarkeit zu wechseln.
Ryan Elkins

3
Die "Handvoll Saiten"; Die Nummer ist nicht das Problem - es ist, ob sie sich in einer einzelnen zusammengesetzten Verkettungsanweisung oder in mehreren Anweisungen befinden.
Marc Gravell

2
StringBuilder ist oft langsamer als der Operator +. Der C # -Compiler übersetzt wiederholt + automatisch in die entsprechenden Überladungen von String.Concat.
Richard Berg

2
Sie werden es schwer haben, gegen die CLR zu kämpfen, während die Laufzeit IL optimiert, und Sie haben versucht, dasselbe zur Kompilierungszeit zu tun - Tauziehen. In den guten alten Zeiten haben Sie die Anweisungen für die Maschine optimiert und die Maschine hat sie dumm ausgeführt.
John K

Antworten:


106

Es scheint, dass Optimierung heutzutage eine verlorene Kunst ist.

Es gab einmal am Tag, als die Herstellung von beispielsweise Mikroskopen als Kunst praktiziert wurde. Die optischen Prinzipien wurden schlecht verstanden. Es gab keine Standardisierung von Teilen. Die Röhren, Zahnräder und Linsen mussten von hochqualifizierten Arbeitern von Hand gefertigt werden.

Heutzutage werden Mikroskope als technische Disziplin hergestellt. Die zugrunde liegenden Prinzipien der Physik sind sehr gut verstanden, handelsübliche Teile sind weit verbreitet, und Ingenieure, die Mikroskope bauen, können fundierte Entscheidungen treffen, wie sie ihr Instrument am besten für die Aufgaben optimieren können, für die es entwickelt wurde.

Dass die Leistungsanalyse eine "verlorene Kunst" ist, ist eine sehr, sehr gute Sache. Diese Kunst wurde als Kunst praktiziert . Die Optimierung sollte so angegangen werden, wie sie ist: ein technisches Problem, das durch sorgfältige Anwendung solider technischer Prinzipien gelöst werden kann.

Ich wurde im Laufe der Jahre Dutzende Male nach meiner Liste von "Tipps und Tricks" gefragt, mit denen Leute ihr vbscript / ihr jscript / ihre aktiven Serverseiten / ihren VB / ihren C # -Code optimieren können. Ich widersetze mich immer dem. Das Hervorheben von "Tipps und Tricks" ist genau der falsche Weg, um sich der Leistung zu nähern. Auf diese Weise entsteht Code, der schwer zu verstehen, schwer zu überlegen und schwer zu warten ist und der normalerweise nicht merklich schneller ist als der entsprechende einfache Code.

Der richtige Weg, sich der Leistung zu nähern, besteht darin, sie wie jedes andere Problem als technisches Problem zu betrachten:

  • Setzen Sie sich aussagekräftige, messbare und kundenorientierte Ziele.
  • Erstellen Sie Testsuiten, um Ihre Leistung unter realistischen, aber kontrollierten und wiederholbaren Bedingungen anhand dieser Ziele zu testen.
  • Wenn diese Suiten zeigen, dass Sie Ihre Ziele nicht erreichen, verwenden Sie Tools wie Profiler, um herauszufinden, warum.
  • Optimieren Sie das, was der Profiler als das Subsystem mit der schlechtesten Leistung identifiziert. Erstellen Sie bei jeder Änderung ein Profil, damit Sie die Auswirkungen der einzelnen Änderungen klar verstehen.
  • Wiederholen Sie diesen Vorgang, bis eines von drei Ereignissen eintritt: (1) Sie erreichen Ihre Ziele und versenden die Software. (2) Sie überarbeiten Ihre Ziele nach unten, um etwas zu erreichen, das Sie erreichen können. (3) Ihr Projekt wird abgebrochen, weil Sie Ihre Ziele nicht erreichen konnten.

Dies ist dasselbe, wie Sie jedes andere technische Problem lösen würden, z. B. das Hinzufügen eines Features - setzen Sie kundenorientierte Ziele für das Feature, verfolgen Sie den Fortschritt bei der Erstellung einer soliden Implementierung, beheben Sie Probleme, wie Sie sie durch sorgfältige Debugging-Analyse finden, und wiederholen Sie sie bis Sie versenden oder scheitern. Leistung ist ein Merkmal.

Die Leistungsanalyse komplexer moderner Systeme erfordert Disziplin und Konzentration auf solide technische Prinzipien, nicht auf eine Tasche voller Tricks, die eng auf triviale oder unrealistische Situationen anwendbar sind. Ich habe noch nie ein reales Leistungsproblem durch Anwendung von Tipps und Tricks gelöst.


1
Ich wollte einen ähnlichen Estrich schreiben, aber deiner ist besser. Bravo.
Richard Berg

7
Es gibt nur einige Fälle, in denen es einen bekanntermaßen besseren Weg gibt, die gleiche Aufgabe zu erfüllen, während man weniger mit Ressourcen beschäftigt ist. Ich kaufe nicht, dass es vollkommen in Ordnung ist zu programmieren, wie Sie wollen, solange Sie ein Ziel erreichen und es in Ordnung zu sein scheint. Oder dass es am besten ist, zu programmieren, dann einen Profiler auszuführen und dann zurück zu gehen und Problembereiche zu ändern. Was ist falsch daran, wenn man eine gute Vorstellung davon hat, was erforderlich ist, um bestimmte Codebits zu optimieren, bevor sie überhaupt beginnen?
Bob

5
@ Bob: Es ist nichts Falsches daran, klug mit Ressourcen umzugehen. Wenn etwas schief geht, verbringen die Leute (1) viel Zeit (= Geld) mit Mikrooptimierungen, die keinen Unterschied machen, (2) schreiben Programme, die falsch sind , und (3) schreiben Programme, die unklar sind. Was Sie optimieren sollten, ist zunächst die Korrektheit. Zweitens guter Codierungsstil. Drittens Leistung. Sobald der Code korrekt und elegant ist, ist es viel einfacher, ihn performant zu machen.
Eric Lippert

3
Das ist in Ordnung, aber Sie werden feststellen, dass ich nicht sage, dass man nicht zuerst auf Korrektheit oder dann auf Stil codieren sollte oder was Sie haben. Es ist jedoch auch wahr, dass Programmierer manchmal (oder heutzutage oft) die Leistung oder Optimierung überhaupt nicht berücksichtigen. Reicht es aus, nur 1 & 2 zu haben, um eine Gesamtzahl von 3 auszugleichen? Ich kann nicht sehen, wie es eine schlechte Idee ist, der Optimierung etwas Respekt zu zollen und ein oder zwei Dinge darüber zu lernen, was es braucht
Bob

7
@ Bob: Ich stimme zu, dass einige Programmierer sich nicht um die Leistung kümmern. Aber ich folge Ihrem Standpunkt nicht. Eine Liste von Tipps und Tricks wird sie nicht plötzlich zu Menschen machen, denen Leistung wichtig ist. Angenommen, Sie können Menschen, die derzeit nicht interessiert sind, zu interessierten Menschen machen, und eine Liste mit Tipps und Tricks hilft ihnen nicht dabei, eine gute Leistung zu erzielen. Sie können den ganzen Tag über Tipps und Tricks auf einen Code anwenden und wissen nie, ob Sie gegen Ihre Ziele überhaupt Fortschritte erzielen. Sie müssen Ziele haben und Ihren Fortschritt messen.
Eric Lippert

45

Holen Sie sich einen guten Profiler.

Versuchen Sie nicht einmal, C # (wirklich jeden Code) ohne einen guten Profiler zu optimieren. Es hilft tatsächlich dramatisch, sowohl einen Sampling- als auch einen Tracing-Profiler zur Hand zu haben.

Ohne einen guten Profiler erstellen Sie wahrscheinlich falsche Optimierungen und vor allem Routinen, die überhaupt kein Leistungsproblem darstellen.

Die ersten drei Schritte zur Profilerstellung sollten immer 1) Messen, 2) Messen und dann 3) Messen sein ....


1
Ich würde sagen, nicht messen , erfassen . stackoverflow.com/questions/406760/…
Mike Dunlavey

23
Sie haben vergessen4) measure
Nifle

1
@Nifle: Wenn du Elefanten jagst, musst du sie messen?
Mike Dunlavey

1
@RobbieDee: Siehe Conrad Albrechts Antwort .
Mike Dunlavey

1
@ MikeDunlavey Sorry, ich hatte nur ein bisschen Spaß mit dir, aber danke ... :-)
Robbie Dee

21

Optimierungsrichtlinien:

  1. Tu es nicht, es sei denn du musst
  2. Tun Sie es nicht, wenn es billiger ist, neue Hardware anstelle eines Entwicklers auf das Problem zu werfen
  3. Tun Sie dies nur, wenn Sie die Änderungen in einer produktionsäquivalenten Umgebung messen können
  4. Tun Sie dies nur, wenn Sie wissen, wie eine CPU und ein Speicherprofiler verwendet werden
  5. Tun Sie es nicht, wenn Ihr Code dadurch unlesbar oder nicht mehr wartbar wird

Da Prozessoren immer schneller werden, ist der Hauptengpass in den meisten Anwendungen nicht die CPU, sondern die Bandbreite: Bandbreite zum Off-Chip-Speicher, Bandbreite zur Festplatte und Bandbreite zum Netz.

Beginnen Sie am anderen Ende: Verwenden Sie YSlow, um festzustellen, warum Ihre Website für Endbenutzer langsam ist. Gehen Sie dann zurück und korrigieren Sie die Datenbankzugriffe so, dass sie nicht zu breit (Spalten) und nicht zu tief (Zeilen) sind.

In den sehr seltenen Fällen, in denen es sich lohnt, Maßnahmen zur Optimierung der CPU-Auslastung zu ergreifen, achten Sie darauf, dass Sie die Speichernutzung nicht negativ beeinflussen: Ich habe Optimierungen gesehen, bei denen Entwickler versucht haben, die Ergebnisse mithilfe des Speichers zwischenzuspeichern, um CPU-Zyklen zu speichern. Der Nettoeffekt bestand darin, den verfügbaren Speicher auf Cache-Seiten und Datenbankergebnisse zu reduzieren, wodurch die Anwendung weitaus langsamer lief! (Siehe Regel zum Messen.)

Ich habe auch Fälle gesehen, in denen ein "dummer" nicht optimierter Algorithmus einen "cleveren" optimierten Algorithmus geschlagen hat. Unterschätzen Sie niemals, wie gut Compiler-Writer und Chip-Designer darin geworden sind, "ineffizienten" Loop-Code in supereffizienten Code umzuwandeln, der mit Pipelining vollständig im On-Chip-Speicher ausgeführt werden kann. Ihr 'cleverer' baumbasierter Algorithmus mit einer unverpackten inneren Schleife, die rückwärts zählt und von Ihnen als 'effizient' eingestuft wurde, kann einfach deshalb geschlagen werden, weil er während der Ausführung nicht im On-Chip-Speicher verbleibt. (Siehe Regel zum Messen.)


10
Seien Sie auch nicht besessen von Big-O-Analysen. Der naive O (nm) -Suchalgorithmus für Zeichenfolgen ist für gängige Geschäftsfälle tausende Male schneller als die O (n + m) -Algorithmen, die die Suchmuster nach Mustern vorverarbeiten. Die naive Zeichenfolgensuche, die mit dem ersten Zeichen übereinstimmt, wird häufig auf eine einzelne Maschinenanweisung reduziert, die auf modernen Prozessoren, die optimistische Speichercaches stark nutzen, unglaublich schnell ist.
Eric Lippert

16

Beachten Sie bei der Arbeit mit ORMs N + 1 Selects.

List<Order> _orders = _repository.GetOrders(DateTime.Now);
foreach(var order in _orders)
{
    Print(order.Customer.Name);
}

Wenn die Kunden nicht eifrig geladen werden, kann dies zu mehreren Roundtrips zur Datenbank führen.


14
  • Verwenden Sie keine magischen Zahlen, sondern Aufzählungen
  • Werte nicht fest codieren
  • Verwenden Sie nach Möglichkeit Generika, da diese typsicher sind und das Ein- und Auspacken vermeiden
  • Verwenden Sie einen Fehlerbehandler, wo er unbedingt benötigt wird
  • Entsorgen, entsorgen, entsorgen. CLR weiß nicht, wie Sie Ihre Datenbankverbindungen schließen sollen. Schließen Sie sie daher nach der Verwendung und entsorgen Sie nicht verwaltete Ressourcen
  • Verwenden Sie gesunden Menschenverstand!

15
So sehr ich zustimme, dass sie gute Dinge zu tun sind, haben die ersten beiden Dinge hier keinen Einfluss auf die Leistung - nur Wartbarkeit ...
Reed Copsey

stimmt, aber es ist immer noch ein optimierter Code.
SoftwareGeek

4
Darüber hinaus ist die 3. (Boxen) selten eine echte Quetschstelle; es ist als Problem übertrieben; ebenso wie Ausnahmen - normalerweise kein Problem.
Marc Gravell

1
"aber es ist immer noch ein optimierter Code" - das ist ein großer Anspruch; Das einzige, was ich dort als bedeutendes Problem erwarten würde, ist "entsorgen". und das taucht eher als Ausnahmen (außerhalb der Handles usw.) auf, nicht als Leistungsabfall.
Marc Gravell

Tatsächlich ist das Finalizer-Muster ziemlich schlecht, wenn die Optimierung Ihr Ziel ist. Objekte mit Finalisierern werden automatisch zu Gen-1 (oder schlechter) befördert. Darüber hinaus ist es normalerweise nicht optimal, Ihren Finalizer-Code zum Ausführen auf dem GC-Thread zu zwingen, wenn auf dieser Todo-Liste etwas entfernt Teueres steht. Fazit: Es handelt sich um eine Funktion, die auf Bequemlichkeit und Korrektheit abzielt und nicht auf Geschwindigkeit ausgelegt ist. Details: msdn.microsoft.com/en-us/magazine/bb985010.aspx
Richard Berg

9

OK, ich muss meinen Favoriten einwerfen: Wenn die Aufgabe lang genug für die menschliche Interaktion ist, verwenden Sie eine manuelle Unterbrechung im Debugger.

Vs. Als Profiler erhalten Sie einen Aufrufstapel und Variablenwerte, mit denen Sie wirklich verstehen können, was los ist.

Wenn Sie dies 10 bis 20 Mal tun, erhalten Sie eine gute Vorstellung davon, welche Optimierung wirklich einen Unterschied machen kann.


1
++ Amen. Ich mache das schon, bevor es Profiler gab. & Ihr Programm DrawMusic sieht fantastisch aus!
Mike Dunlavey

6
Dies ist im Wesentlichen das, was Profiler tun, außer dass sie es auf etwa tausend verschiedene Arten besser machen als Sie (schneller, häufiger, genauer usw.). Sie geben auch Call-Stacks. Dies ist die Lösung des armen Mannes (und des alten Mannes, der Angst hat, neue Dinge zu lernen).
BlueRaja - Danny Pflughoeft

@ BlueRaja-DannyPflughoeft: Sie täuschen dich. Sie sagen Ihnen mit großer Präzision, dass nicht viel zu tun ist. Der Unterschied zwischen dieser Methode und Profilern besteht darin, dass Sie in dieser Methode Dinge sehen können, die beschleunigt werden müssen und die nicht aus einfachen Statistiken herausgearbeitet werden können. Stattdessen nehmen sie Tausende von Proben, wenn die Informationen, die Sie zum Problem führen können, in den ersten 10 offensichtlich sind, wenn Sie die Rohproben tatsächlich sehen können. Ich bin sicher, Sie haben diesen Beitrag gesehen .
Mike Dunlavey

@ BlueRaja-DannyPflughoeft: Sehen Sie sich die Ergebnisse an. Was ist das größte Beschleunigungsverhältnis, das Sie jemals mit einem Profiler erzielt haben?
Mike Dunlavey

2
@ BlueRaja-DannyPflughoeft: Ich bin sicher, du würdest nicht, und wenn du in meinem Alter bist, wirst du Leuten wie dir begegnen. Aber lassen wir das beiseite. Hier ist ein Quellcode Wenn Sie es um 3 Größenordnungen beschleunigen können, ohne zu sehen, wie ich es gemacht habe, mit einer anderen Methode, haben Sie prahlerische Rechte :)
Mike Dunlavey

9

Wenn Sie eine Methode als Engpass identifizieren, aber nicht wissen, was Sie dagegen tun sollen, stecken Sie im Wesentlichen fest.

Also werde ich ein paar Dinge auflisten. All diese Dinge sind keine Silberkugeln und Sie müssen Ihren Code trotzdem profilieren . Ich mache nur Vorschläge für Dinge, die Sie tun könnten und die manchmal helfen können. Besonders die ersten drei sind wichtig.

  • Versuchen Sie, das Problem nur mit (oder: hauptsächlich) Low-Level-Typen oder Arrays davon zu lösen.
  • Probleme sind oft klein - die Verwendung eines intelligenten, aber komplexen Algorithmus bringt Sie nicht immer zum Sieg, insbesondere wenn der weniger intelligente Algorithmus in Code ausgedrückt werden kann, der nur (Arrays von) Low-Level-Typen verwendet. Nehmen wir zum Beispiel InsertionSort vs MergeSort für n <= 100 oder Tarjans Dominator-Suchalgorithmus vs die Verwendung von Bitvektoren, um die Datenflussform des Problems für n <= 100 naiv zu lösen. (Die 100 ist natürlich nur, um Ihnen eine Idee zu geben - Profil !)
  • Erwägen Sie, einen Sonderfall zu schreiben, der nur mit einfachen Typen (häufig Probleminstanzen mit einer Größe <64) gelöst werden kann, selbst wenn Sie den anderen Code für größere Probleminstanzen beibehalten müssen.
  • Lernen Sie bitweise Arithmetik, um Ihnen bei den beiden oben genannten Ideen zu helfen.
  • BitArray kann Ihr Freund sein, verglichen mit Dictionary oder schlimmer noch List. Beachten Sie jedoch, dass die Implementierung nicht optimal ist. Sie können selbst eine schnellere Version schreiben. Anstatt zu testen, ob Ihre Argumente außerhalb des Bereichs usw. liegen, können Sie Ihren Algorithmus häufig so strukturieren, dass der Index ohnehin nicht außerhalb des Bereichs liegt. Sie können die Prüfung jedoch nicht aus dem Standard-BitArray entfernen und sie ist nicht kostenlos .
  • Als Beispiel dafür, was Sie nur mit Arrays von Low-Level-Typen tun können, ist die BitMatrix eine ziemlich leistungsfähige Struktur, die nur als Array von Ulongs implementiert werden kann, und Sie können sie sogar mit einem Ulong als "Front" durchlaufen, weil Sie nehmen können das Bit mit der niedrigsten Ordnung in konstanter Zeit (verglichen mit der Warteschlange in der Breitensuche - aber offensichtlich ist die Reihenfolge unterschiedlich und hängt eher vom Index der Elemente ab als nur von der Reihenfolge, in der Sie sie finden).
  • Division und Modulo sind sehr langsam, es sei denn, die rechte Seite ist eine Konstante.
  • Gleitkomma-Mathematik ist im Allgemeinen nicht mehr langsamer als Ganzzahl-Mathematik (nicht "etwas, das Sie tun können", sondern "etwas, das Sie überspringen können")
  • Die Verzweigung ist nicht kostenlos . Wenn Sie dies mit einer einfachen Arithmetik (alles andere als Division oder Modulo) vermeiden können, können Sie manchmal eine gewisse Leistung erzielen. Es ist fast immer eine gute Idee, einen Zweig nach außerhalb einer Schleife zu verschieben.

Einige gute Sachen, die mir sehr geholfen haben - danke!
Robbie Dee

8

Die Leute haben lustige Ideen darüber, worauf es wirklich ankommt. Der Stapelüberlauf ist voller Fragen, zum Beispiel, ++iob er "performanter" ist als i++. Hier ist ein Beispiel für eine echte Leistungsoptimierung , und es ist im Grunde das gleiche Verfahren für jede Sprache. Wenn Code einfach auf eine bestimmte Weise geschrieben wird, "weil er schneller ist", ist das eine Vermutung.

Sicher, Sie schreiben nicht absichtlich dummen Code, aber wenn das Erraten funktioniert, wären keine Profiler und Profiling-Techniken erforderlich.


6

Die Wahrheit ist, dass es keinen perfekt optimierten Code gibt. Sie können jedoch für einen bestimmten Teil des Codes auf einem bekannten System (oder einer Reihe von Systemen) auf einem bekannten CPU-Typ (und einer bekannten Anzahl), einer bekannten Plattform (Microsoft? Mono ?), Einer bekannten Framework- / BCL- Version, optimieren. eine bekannte CLI-Version, eine bekannte Compiler-Version (Fehler, Spezifikationsänderungen, Optimierungen), eine bekannte Menge an Gesamt- und verfügbarem Speicher, ein bekannter Assembly-Ursprung ( GAC ? disk? remote?) mit bekannter Hintergrundsystemaktivität aus anderen Prozessen.

Verwenden Sie in der realen Welt einen Profiler und sehen Sie sich die wichtigen Elemente an. Normalerweise sind die offensichtlichen Dinge alles, was mit E / A zu tun hat, alles, was mit Threading zu tun hat (dies ändert sich wiederum enorm zwischen den Versionen) und alles, was Schleifen und Suchvorgänge beinhaltet, aber Sie könnten überrascht sein, welcher "offensichtlich schlechte" Code eigentlich kein Problem ist. und welcher "offensichtlich gute" Code ist ein großer Schuldiger.


5

Sagen Sie dem Compiler, was zu tun ist, nicht wie . Zum Beispiel foreach (var item in list)ist besser als for (int i = 0; i < list.Count; i++)und m = list.Max(i => i.value);ist besser als list.Sort(i => i.value); m = list[list.Count - 1];.

Indem Sie dem System mitteilen, was Sie tun möchten, können Sie den besten Weg finden, dies zu tun. LINQ ist gut, da die Ergebnisse erst berechnet werden, wenn Sie sie benötigen. Wenn Sie immer nur das erste Ergebnis verwenden, muss es den Rest nicht berechnen.

Letztendlich (und dies gilt für alle Programmierungen) minimieren Sie Schleifen und minimieren Sie, was Sie in Schleifen tun. Noch wichtiger ist es, die Anzahl der Schleifen in Ihren Schleifen zu minimieren. Was ist der Unterschied zwischen einem O (n) -Algorithmus und einem O (n ^ 2) -Algorithmus? Der O (n ^ 2) -Algorithmus hat eine Schleife innerhalb einer Schleife.


ironischerweise fügt LINQ zusätzliche Wurst hinzu, und man sollte sich fragen, ob es eine Lösung ohne diese gibt.
user3800527

2

Ich versuche nicht wirklich, meinen Code zu optimieren, aber manchmal werde ich etwas wie Reflektor verwenden, um meine Programme wieder in den Quellcode zu versetzen. Es ist interessant, dann zu vergleichen, was ich falsch mache, mit dem, was der Reflektor ausgibt. Manchmal finde ich, dass das, was ich in einer komplizierteren Form getan habe, vereinfacht wurde. Kann die Dinge nicht optimieren, hilft mir aber, einfachere Lösungen für Probleme zu finden.

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.