Wo ich gearbeitet habe, verwenden wir immer mehrere Ebenen der Profilerstellung. Wenn Sie ein Problem feststellen, blättern Sie einfach ein bisschen weiter nach unten, bis Sie herausgefunden haben, was los ist:
- Der "menschliche Profiler", auch bekannt als " nur spielen" ; Fühlt es sich gelegentlich langsam oder "hitch" an? Ruckelige Animationen bemerken? (Beachten Sie als Entwickler, dass Sie für einige Arten von Leistungsproblemen sensibler und für andere weniger empfänglich sind. Planen Sie zusätzliche Tests entsprechend.)
- Schalten Sie die FPS-Anzeige ein , bei der es sich um eine durchschnittliche FPS von 5 Sekunden im Schiebefenster handelt. Sehr wenig Aufwand zum Berechnen und Anzeigen.
- Aktivieren Sie die Profilleisten , bei denen es sich nur um eine Reihe von Quads (ROYGBIV-Farben) handelt, die verschiedene Teile des Frames darstellen (z. B. Leerzeichen, Preframe, Aktualisierung, Kollision, Rendern, Postframe), indem Sie einen einfachen Stoppuhr-Timer um jeden Codeabschnitt verwenden . Um zu betonen, was wir wollen, setzen wir einen Balken mit einer Bildschirmbreite, der für einen 60-Hz-Zielrahmen repräsentativ ist. So ist es wirklich leicht zu erkennen, ob Sie beispielsweise 50% unter dem Budget (nur einen halben Balken) oder 50% über dem Budget ( Die Leiste wird zu anderthalb Leisten. Es ist auch ziemlich einfach zu erkennen, was im Allgemeinen den größten Teil des Frames ausmacht: Rot = Rendern, Gelb = Aktualisieren usw.
- Erstellen Sie einen speziellen instrumentierten Build , der "Stoppuhr" -ähnlichen Code um jede Funktion einfügt. (Beachten Sie, dass Sie dabei unter Umständen einen massiven Performance-, Dcache- und Icache-Schlag erleiden müssen. Dies ist auf jeden Fall aufdringlich. Wenn Sie jedoch keinen ordnungsgemäßen Sampling-Profiler oder keine angemessene Unterstützung für die CPU haben, ist dies eine akzeptable Option. Sie können auch clever sein über das Aufzeichnen eines Minimums an Daten bei der Eingabe / Ausgabe von Funktionen und das spätere Wiederherstellen von Aufrufen.) Als wir unsere erstellten, ahmten wir einen Großteil des Ausgabeformats von gprof nach .
- Führen Sie am besten einen Stichproben-Profiler aus . VTune und CodeAnalyst sind für x86 und x64 verfügbar. Sie haben verschiedene Simulations- oder Emulationsumgebungen, die Ihnen hier möglicherweise Daten liefern.
(Es gibt eine lustige Geschichte aus der GDC eines Grafikprogrammierers aus dem vergangenen Jahr, der vier Bilder von sich selbst gemacht hat - fröhlich, gleichgültig, genervt und wütend - und in der Ecke der internen Builds ein entsprechendes Bild basierend auf der Framerate angezeigt hat Inhaltsersteller lernten schnell, komplizierte Shader nicht für alle ihre Objekte und Umgebungen zu aktivieren: Sie würden den Programmierer verärgern.
Beachten Sie, dass Sie auch lustige Dinge tun können, wie die "Profilleisten" fortlaufend grafisch darstellen, so dass Sie Spitzenmuster ("wir verlieren alle 7 Bilder ein Bild") oder ähnliches sehen können.
Zur Beantwortung Ihrer Frage direkt, aber: in meiner Erfahrung, während es verlockend (und oft belohnt - ich in der Regel etwas lernen) einzelne Funktionen / Module zur Optimierung der Anzahl von Befehlen oder icache oder dCache Leistung neu zu schreiben, und wir tatsächlich brauchten zu tun Dies ist manchmal der Fall, wenn wir ein besonders unangenehmes Leistungsproblem haben. Die überwiegende Mehrheit der Leistungsprobleme, mit denen wir uns regelmäßig befassen, hängt vom Design ab . Beispielsweise:
- Sollten wir im RAM zwischenspeichern oder die "Angriffs" -Status-Animations-Frames für den Player von der Festplatte neu laden? Wie wäre es mit jedem Feind? Wir haben keinen RAM, um sie alle zu erledigen, aber das Laden von Festplatten ist teuer! Sie können das Hitching sehen, wenn 5 oder 6 verschiedene Feinde gleichzeitig hereinkommen! (Okay, wie wäre es mit taumelndem Laichen?)
- Führen wir eine einzelne Operation für alle Partikel oder für alle Operationen für ein einzelnes Partikel aus? (Dies ist ein Icache / Dcache-Kompromiss, und die Antwort ist nicht immer klar.) Wie wäre es, wenn Sie alle Partikel auseinander ziehen und die Positionen zusammen speichern (die berühmte "Struktur von Arrays") und alle Partikeldaten an einem Ort aufbewahren (" Array von Strukturen ").
Sie hören es, bis es in irgendwelchen Informatikkursen auf Universitätsniveau unangenehm wird, aber: es dreht sich wirklich alles um die Datenstrukturen und Algorithmen. Wenn Sie etwas Zeit mit dem Entwurf von Algorithmen und Datenflüssen verbringen, werden Sie im Allgemeinen mehr fürs Geld bekommen. (Vergewissern Sie sich, dass Sie die hervorragenden Fallstricke objektorientierter Programmierung von einem Sony Developer Services-Kollegen gelesen haben, um sich hier einen Überblick zu verschaffen .) Das "fühlt" sich nicht nach Optimierung an. Die meiste Zeit wird mit einem Whiteboard oder UML-Tool verbracht oder es werden viele Prototypen erstellt, anstatt den aktuellen Code schneller laufen zu lassen. Aber es lohnt sich in der Regel viel mehr.
Und noch eine nützliche Heuristik: Wenn Sie sich dem "Kern" Ihrer Engine nähern, lohnt es sich möglicherweise, zusätzliche Anstrengungen und Experimente zu unternehmen, um diese zu optimieren (z. B. diese Matrixmultiplikationen zu vektorisieren!). Je weiter Sie vom Kern entfernt sind, desto weniger sollten Sie sich darüber Gedanken machen, es sei denn, eines Ihrer Profilerstellungstools teilt Ihnen etwas anderes mit.
Denken Sie aber auch an "vorzeitige Pessimisierung". Es ist zwar nicht erforderlich, in jeder Codezeile Hardcore zu betreiben, aber es gibt Gründe dafür, zu erkennen, dass Sie tatsächlich an einem Spiel arbeiten, das Auswirkungen auf die Echtzeitleistung hat.
Während Sie alle angewiesen haben, die Hotspots zu messen und zu optimieren, zeigt Ihnen diese Technik keine Leistung, die an verborgenen Orten verloren geht. Wenn zum Beispiel jede '+' - Operation in Ihrem Code doppelt so lange dauert wie sie sollte, wird sie nicht als Hotspot angezeigt und Sie werden sie daher niemals optimieren oder gar realisieren, da sie jedoch im gesamten Code verwendet wird Platzieren Sie es könnte Sie eine Menge Leistung kosten. Sie wären überrascht, wie viele dieser Zyklen verrinnen, ohne jemals entdeckt zu werden. Also sei dir bewusst, was du tust.
Abgesehen davon neige ich dazu, mich regelmäßig zu profilieren, um eine Vorstellung davon zu bekommen, was da ist und wie viel Zeit pro Frame verbleibt. Für mich ist die Zeit pro Frame die logischste, da sie mir direkt sagt, wo ich mit Framerate-Zielen bin. Versuchen Sie auch herauszufinden, wo sich Peaks befinden und was sie verursacht. Ich bevorzuge eine stabile Framerate gegenüber einer hohen Framerate mit Spikes.
quelle
Sobald ein Spiel veröffentlicht werden kann (entweder final oder beta) oder es merklich langsam ist, ist es wahrscheinlich die beste Zeit, um Ihre App zu profilieren . Natürlich können Sie den Profiler jederzeit ausführen. Aber ja, vorzeitige Optimierung ist die Wurzel allen Übels. Unbegründete Optimierung auch; Sie benötigen aktuelle Daten, um zu zeigen, dass ein Teil des Codes langsam ist, bevor Sie versuchen sollten, ihn zu "optimieren". Ein Profiler erledigt das für Sie.
Wenn Sie keinen Profiler kennen, lernen Sie ihn! Hier ist ein guter Blog-Beitrag , der die Nützlichkeit eines Profilers demonstriert.
Wenn Ihr kleines Spiel mit 200 FPS läuft, obwohl es einen ineffizienten Algorithmus enthält, haben Sie dann wirklich einen Grund zur Optimierung? Sie sollten eine gute Vorstellung von den Spezifikationen Ihres Zielcomputers haben und sicherstellen, dass das Spiel auf diesem Computer gut läuft, aber alles, was darüber hinausgeht, ist (vermutlich) verschwendete Zeit, die besser für das Codieren oder Polieren des Spiels aufgewendet werden könnte.
quelle
Ich finde es nützlich, Profile einzubauen. Auch wenn Sie nicht aktiv optimieren, ist es gut, eine Vorstellung davon zu haben, was Ihre Leistung zu einem bestimmten Zeitpunkt einschränkt. Viele Spiele haben eine Art überlagerndes HUD, das eine einfache grafische Darstellung (normalerweise nur ein farbiger Balken) anzeigt, wie lange verschiedene Teile der Spielschleife jeden Frame benötigen.
Es wäre eine schlechte Idee, die Leistungsanalyse und -optimierung zu spät durchzuführen. Wenn Sie das Spiel bereits erstellt haben und 200% Ihres CPU-Budgets überschreiten und dies durch Optimierung nicht finden können, sind Sie fertig.
Sie müssen beim Schreiben die Budgets für Grafik, Physik usw. kennen. Sie können das nicht tun, wenn Sie keine Ahnung haben, wie Ihre Leistung aussehen wird, und Sie können das nicht erraten, ohne zu wissen, was Ihre Leistung ist und wie viel Schlappheit es geben könnte.
Bauen Sie also vom ersten Tag an einige Leistungsstatistiken ein.
Auch hier ist es wahrscheinlich am besten, nicht zu spät zu warten, damit Sie nicht die Hälfte Ihres Motors überarbeiten müssen. Auf der anderen Seite sollten Sie sich nicht zu sehr mit der Optimierung von Dingen beschäftigen, um jeden Zyklus zu optimieren, wenn Sie der Meinung sind, dass Sie den Algorithmus morgen vollständig ändern könnten oder wenn Sie keine echten Spieldaten durchlaufen haben.
Nehmen Sie die niedrig hängenden Früchte mit, packen Sie die großen Dinge regelmäßig an, und es sollte Ihnen gut gehen.
quelle
Wenn er sich Knuths Zitat in seinem Kontext ansieht, erklärt er weiter, dass wir es optimieren sollten, aber mit Werkzeugen wie einem Profiler.
Sie sollten Ihre Anwendung ständig profilieren und speichern, nachdem die grundlegende Architektur festgelegt wurde.
Durch die Profilerstellung können Sie nicht nur die Geschwindigkeit erhöhen, sondern auch Fehler finden. Wenn Ihr Programm plötzlich die Geschwindigkeit drastisch ändert, liegt dies normalerweise an einem Fehler. Wenn Sie kein Profil erstellen, bleibt dies möglicherweise unbemerkt.
Der Trick bei der Optimierung besteht darin, dies von Grund auf zu tun. Warten Sie nicht bis zur letzten Minute. Stellen Sie sicher, dass Sie mit dem Design Ihres Programms die Leistung erhalten, die Sie benötigen, ohne sich auf böse Tricks in der inneren Schleife einzulassen.
quelle
Für mein Projekt wende ich normalerweise einige SEHR benötigte Optimierungen in meiner Grundmaschine an. Zum Beispiel implementiere ich immer gerne eine solide SIMD-Implementierung mit SSE2 und 3DNow! Dies stellt sicher, dass meine Gleitkomma-Mathematik genau dort ist, wo ich sie haben möchte. Eine weitere bewährte Methode besteht darin, Optimierungen beim Codieren zur Gewohnheit zu machen, anstatt zurückzukehren. Meistens sind diese kleinen Übungen genauso zeitaufwendig wie das, was Sie ohnehin programmiert haben. Stellen Sie vor dem Codieren einer Funktion sicher, dass Sie nach den effizientesten Methoden suchen.
Fazit: Meiner Meinung nach ist es SCHWER, Ihren Code effizienter zu machen, nachdem er bereits gelutscht hat.
quelle
Ich würde sagen, der einfachste Weg wäre, Ihren gesunden Menschenverstand zu benutzen - wenn etwas so aussieht, als würde es langsam laufen, dann schauen Sie es sich an. Überprüfen Sie, ob es sich um einen Engpass handelt.
Verwenden Sie einen Profiler, um zu sehen, welche Geschwindigkeitsfunktionen ausgeführt werden und wie oft sie aufgerufen werden.
Es macht absolut keinen Sinn, etwas zu optimieren oder Zeit damit zu verbringen, etwas zu optimieren, das es nicht benötigt.
quelle
Wenn Ihr Code langsam ausgeführt wird, führen Sie einen Profiler aus und überprüfen Sie, was genau dazu führt, dass er langsamer ausgeführt wird. Sie können auch proaktiv sein und bereits einen Profiler ausführen, bevor Sie Leistungsprobleme bemerken.
Sie möchten optimieren, wenn Ihre Framerate auf einen Punkt fällt, unter dem das Spiel zu leiden beginnt. Ihr wahrscheinlichster Schuldiger wird sein, dass Ihre CPU zu stark ausgelastet ist (100%).
quelle
Sie sollten Ihren Code optimieren ... so oft Sie möchten.
Was ich in der Vergangenheit getan habe, ist, das Spiel mit aktivierter Profilerstellung ununterbrochen laufen zu lassen (zumindest immer einen Frameraten-Zähler auf dem Bildschirm). Wenn das Spiel langsam wird (z. B. unter Ihrer Zielframerate auf Ihrem Minispezifikationscomputer), schalten Sie den Profiler ein und prüfen Sie, ob Hotspots angezeigt werden.
Manchmal ist es nicht der Code. Viele der Probleme, auf die ich in der Vergangenheit gestoßen bin, waren gpu-orientiert (zugegeben, das war auf dem iPhone). Probleme mit der Füllrate, zu viele Zeichenaufrufe, nicht genügend Geometrie, ineffiziente Shader ...
Abgesehen von ineffizienten Algorithmen für schwierige Probleme (z. B. Pfadfindung, Physik) bin ich nur selten auf Probleme gestoßen, bei denen der Code selbst der Schuldige war. Und diese schwierigen Probleme sollten Dinge sein, mit denen Sie sich viel Mühe geben, um den richtigen Algorithmus zu finden und sich nicht um kleinere Dinge zu kümmern.
quelle
Für mich ist das am besten vorbereitete Datenmodell zu befolgen. Und die Optimierung - vor dem Hauptschritt nach vorne. Ich meine, bevor ich anfange, etwas Großes Neues zu implementieren. Ein weiterer Grund für die Optimierung ist, wenn ich die Kontrolle über Ressourcen verliere, die App viel CPU-Last / GPU-Last oder Speicher benötigt und ich nicht weiß, warum :) oder es ist zu viel.
quelle