Ich möchte die maximale Anzahl erhalten, die ich brauche, um eine Schleife auszuführen, die x Millisekunden dauert, um fertig zu werden.
Für zB.
%Vor%Wie mache ich so etwas?
Ich möchte die maximale Anzahl erhalten, die ich brauche, um eine Schleife auszuführen, die x Millisekunden dauert, um fertig zu werden.
Zunächst einmal, tu das einfach nicht. Wenn Sie eine bestimmte Anzahl von Millisekunden warten müssen nicht beschäftigt - warten Sie in einer Schleife . Stattdessen starten Sie einen Timer und kehren zurück. Wenn der Timer tickt, rufen Sie eine Methode auf, die dort fortgesetzt wird, wo Sie aufgehört haben. Die Task.Delay
-Methode könnte eine gute sein, zu verwenden; es kümmert sich um die Timer-Details für Sie.
Wenn es in Ihrer Frage darum geht, wie viel Zeit der Code benötigt, brauchen Sie viel mehr als nur einen guten Timer. Es gibt eine Menge Kunst und Wissenschaft, um genaue Zeiten zu bekommen.
Zuerst sollten Sie immer Stopwatch
verwenden und niemals DateTime.Now
für diese Zeiten verwenden. Die Stoppuhr ist ein hochpräziser Timer, der angibt, wie viel Zeit vergangen ist. DateTime.Now
ist ein Timer mit niedriger Präzision, der Ihnen sagt, wenn es Zeit ist, Doctor Who noch zu sehen . Sie würden keine Wanduhr benutzen, um eine olympische Rasse zu messen; Sie würden die Stoppuhr mit der höchsten Präzision verwenden, die Sie in die Hände bekommen konnten. Verwende also das für dich bereitgestellte.
Zweitens müssen Sie sich daran erinnern, dass C # -Code Just In Time kompiliert wird. Das erste Mal, wenn Sie eine Schleife durchlaufen, kann daher aufgrund der Kosten des Jitters, der den von der Schleife aufgerufenen Code analysiert, hunderte oder tausende Male teurer sein als jedes nachfolgende Mal. Wenn Sie beabsichtigen, die "warmen" Kosten einer Schleife zu messen, müssen Sie die Schleife einmal ausführen, bevor Sie mit der Zeitmessung beginnen. Wenn Sie beabsichtigen, die durchschnittlichen Kosten einschließlich der JIT-Zeit zu messen, müssen Sie entscheiden, wie oft eine angemessene Anzahl von Versuchen ausfällt, so dass der Durchschnitt korrekt ausfällt .
Drittens müssen Sie sicherstellen, dass Sie keine Bleigewichte tragen, wenn Sie ausführen. Niemals Leistungsmessungen während des Debuggens > durchführen. Es ist erstaunlich, wie viele Menschen das tun. Wenn Sie sich im Debugger befinden, kann es sein, dass die Laufzeitumgebung mit dem Debugger redet, um sicherzustellen, dass Sie die gewünschte Debugging-Erfahrung erhalten und dass das Chatten Zeit braucht. Der Jitter erzeugt schlechteren Code als normalerweise, so dass Ihre Debugging-Erfahrung konsistenter ist. Der Garbage Collector sammelt weniger aggressiv . Und so weiter. Führen Sie Ihre Leistungsmessungen immer außerhalb des Debuggers und mit aktivierten Optimierungen aus.
Denken Sie daran, dass virtuelle Speichersysteme ähnliche Kosten verursachen wie Jitter . Wenn Sie bereits ein verwaltetes Programm ausführen oder kürzlich eines ausgeführt haben, sind die Seiten der CLR, die Sie benötigen, wahrscheinlich "heiß" - bereits im RAM - wo sie schnell sind. Wenn nicht, dann sind die Seiten möglicherweise auf der Festplatte kalt und müssen mit Seitenfehlern versehen werden. Das kann die Zeiten enorm verändern.
Fünftens, denken Sie daran, dass der Jitter zu Optimierungen führen kann, die Sie nicht erwarten . Wenn Sie versuchen, Zeit:
%Vor%Der Jitter ist vollständig innerhalb seiner Rechte, die gesamte Schleife zu entfernen . Es kann erkennen, dass die Schleife keinen Wert berechnet, der sonst irgendwo im Programm verwendet wird, und sie vollständig entfernen, indem sie eine Zeit von null angibt. Tut es das? Könnte sein. Vielleicht nicht. Das liegt an dem Jitter. Sie sollten die Leistung von realistischem Code messen, wobei die berechneten Werte tatsächlich verwendet werden. der Jitter wird dann wissen, dass er sie nicht optimieren kann.
Sechstens, Zeiten von Tests, die viel Müll erzeugen, können vom Müllsammler abgeworfen werden. Angenommen, Sie haben zwei Tests, einen, der viel Müll produziert, und einen, der ein bisschen macht. Die Kosten der Sammlung des durch den ersten Test erzeugten Mülls können auf die für den zweiten Test benötigte Zeit "aufgeladen" werden, wenn der erste Test glücklicherweise ohne eine Sammlung läuft, der zweite jedoch einen auslöst. Wenn Ihre Tests eine Menge Müll produzieren, dann ist (1) mein Test realistisch? Es macht keinen Sinn, eine Performance-Messung eines unrealistischen Programms durchzuführen, weil Sie keine guten Schlüsse ziehen können, wie sich Ihr echtes Programm verhalten wird. Und (2) sollte ich die Kosten der Müllabfuhr für den Test berechnen, der den Müll produzierte? Wenn ja, stellen Sie sicher, dass Sie eine vollständige Sammlung erzwingen, bevor das Timing des Tests abgeschlossen ist.
Siebtens, Sie führen Ihren Code in einer Multithread-Umgebung mit mehreren Prozessoren aus, in der Threads nach Belieben umgeschaltet werden können und wo die Thread-Quantum (die Zeit, die das Betriebssystem einen anderen Thread gibt, bis Ihre eine Chance bekommt, wieder zu laufen ) beträgt etwa 16 Millisekunden. 16 Millisekunden sind ungefähr fünfzig Millionen Prozessorzyklen . Das genaue Timing von Untermillisekunden-Operationen kann ziemlich schwierig sein, wenn der Thread-Wechsel in einem der mehreren Millionen Prozessorzyklen stattfindet, die Sie zu messen versuchen. Berücksichtigen Sie das.
Gute Punkte von Eric Lippert. Ich war für einige Zeit Benchmarking und Unit-Tests und ich würde empfehlen, sollten Sie jeden First-Pass auf Sie Code Ursache JIT Compilation verwerfen. Also in einem Benchmark-Code, die Schleife und Stoppuhr verwenden, denken Sie daran, dies am Ende der Schleife zu setzen:
%Vor%