'neues' Schlüsselwort im Getter Performance Hit?

8

Ich habe den folgenden Code:

%Vor%

Jetzt irgendwo anders in meinem Code, mache ich etwa 2500 Aufrufe in einer Schleife zu Character.LevelPosition. Das bedeutet, dass pro Update-Zyklus 5000 "neue" Vector2s erstellt werden und auf meinem Laptop die Framerate wirklich abfällt.

Ich habe es vorübergehend durch Erstellen von

behoben %Vor%

bevor ich die Schleife einleite, aber ich fühle irgendwie seinen hässlichen Code, um dies jedes Mal zu tun, wenn ich auf eine ähnliche Situation stoße. Vielleicht ist es der Weg zu gehen, aber ich will sicher gehen.

Gibt es einen besseren oder allgemein akzeptierten Weg, dies zu tun?

Ich verwende das XNA-Framework, das Vector2 's.

    
Taelia 06.03.2012, 12:30
quelle

3 Antworten

5

Von dem, was ich verstehe, sollten Sie vermeiden, viele Objekte aus dem Heap in XNA zuzuweisen, weil das schlechte Leistung verursacht. Aber da Vector2 ein struct ist, ordnen wir hier nichts auf dem Heap zu, so dass das hier nicht das Problem sein sollte.

Nun, wenn Sie eine enge Schleife haben, wie Sie es tun, in einer performance-kritischen Anwendung, wie ein Spiel, müssen Sie immer über die Leistung nachdenken, da gibt es kein Problem.

Wenn wir uns den Code für LevelPosition ansehen, rufen Sie zweimal den Getter für WorldPosition und wahrscheinlich noch ein paar weitere Getter auf. Der Getter für WorldPosition ruft wahrscheinlich nur wenige andere Getter auf. (Es ist schwer zu sagen, was genau passiert, ohne die Quelle zu haben, da Getter-Aufruf und Feldzugriff genau gleich aussehen.)

Aufruf an einen Getter, der eigentlich nur ein Aufruf einer speziellen Methode ist, ist normalerweise ziemlich schnell und kann sogar schneller sein, wenn der Compiler sich entscheidet, inlining zu verwenden. Aber alle Anrufe summieren sich zusammen, besonders wenn Sie sie in einer Schleife aufrufen.

Die Lösung dafür ist eine Art Caching. Eine Möglichkeit wäre, LevelPosition zu einem Feld zu machen und ein System zu entwickeln, um es bei Bedarf zu aktualisieren. Das könnte funktionieren, aber es könnte auch die Leistung beeinträchtigen, wenn Sie es häufiger aktualisieren müssen, als Sie es lesen.

Eine andere Lösung ist, wie Sie herausgefunden haben, das Ergebnis in einer lokalen Variablen zwischenzuspeichern. Wenn Sie wissen, dass dies korrekt ist, d. H. Dass sich der Wert der Eigenschaft während der Ausführung der Schleife nicht ändert, dann ist das großartig! Sie haben Ihr Leistungsproblem gelöst, und Sie haben es mit nur einer einzigen Codezeile getan, die für jeden Programmierer leicht verständlich ist. Was willst du mehr?

Lassen Sie mich das wiederholen. Sie haben eine Lösung für Ihr Leistungsproblem gefunden:

  1. funktioniert
  2. ist einfach zu implementieren
  3. ist leicht zu verstehen

Ich denke, dass eine solche Lösung sehr schwer zu schlagen sein wird.

    
svick 06.03.2012, 13:29
quelle
4

Das Erstellen vieler Objekte in einer Schleife kann eine teure Operation sein (*). Vielleicht, wenn es helfen würde, das Vector2 im Voraus zu erzeugen (zum Beispiel wenn sich die Koordinaten ändern) und in Zukunft einfach die Koordinaten ändern.

Beispiel:

%Vor%

BEARBEITEN
Das Gleiche sollte auch für die Eigenschaft LevelPosition getan werden. Siehe geänderten Quellcode.

(*)
Tim Schmelter wies mich darauf hin, diese Frage mit einer ausführlichen Diskussion darüber zu stellen die Auswirkungen von Objekten instanzieren. Ich habe meinen ersten Satz umformuliert, dass die Objekterstellung immer teuer ist. Während das Erstellen von Objekten nicht immer eine teure Operation ist, kann es in bestimmten Fällen die Leistung beeinträchtigen.

    
Thorsten Dittmar 06.03.2012 12:35
quelle
2

Sie können ein privates Feld erstellen, um den Wert zu speichern und nicht jedes Mal zu berechnen. Sie können eine Methode zum Aktualisieren der privaten Felder erstellen und die Änderungen von Movement.Position auf irgendeine Weise abonnieren. Auf diese Weise wird der Wert nur einmal bei Positionsänderungen berechnet.

    
Stilgar 06.03.2012 12:35
quelle