2009-10-17 11 views
7

Ich arbeite an einem Spiel für die Xbox360, mit XNA. Auf der Xbox schneidet der Garbage Collector im Vergleich zu dem auf einem PC eher schlecht ab. Daher ist es für ein reibungslos funktionierendes Spiel von entscheidender Bedeutung, den generierten Müll auf ein Minimum zu reduzieren.Erzeugt mit einem Delegaten Müll erstellen

Ich erinnere mich, einmal zu lesen, dass das Aufrufen eines Delegaten Müll erstellt, aber jetzt für das Leben von mir kann keine Verweise auf Delegaten finden, Müll zu erstellen. Habe ich das gerade erfunden oder sind die Delegierten chaotisch?

Wenn Delegierte unordentlich sind, Bonuspunkte für das Vorschlagen einer Problemumgehung.

public delegate T GetValue<T>(T value, T[] args); 

public static T Transaction<T>(GetValue<T> calculate, ref T value, params T[] args) where T : class 
{ 
    T newValue = calculate(value, args); 
    return foo(newValue); 
} 

Mein Code sieht vage wie das im Moment die einzige Lösung, die ich denken kann mich von Delegierten zu befreien ist in einer Klasse übergeben, die eine Schnittstelle IValueCalculator erbt, und dann kann ich die Methode auf das nennen Schnittstelle, das ist aber nicht wirklich sehr ordentlich!

+0

Delegierten wirklich klein sein sollte, und ein nicht schaffen sollte ganz viel Müll, wenn Sie sie ausführen. (Wenn sie Müll erzeugen, sollte es eine Faust voller Bytes für jedes sein). Wenn Sie eine Schnittstellenreferenz übergeben und diese nicht verwenden, wird auch Unrat erzeugt. – CodingBarfield

Antwort

10

Ein Delegat ist selbst ein Objekt, also, wenn Sie einen Delegaten, vielleicht für eine anonyme Methode, erstellen und dies einer anderen Methode zur Ausführung geben, und den Delegierten nicht für zukünftige Referenz speichern, dann ja, das wird Müll produzieren.

Zum Beispiel diese:

collection.ForEach(delegate(T item) 
{ 
    // do something with item 
}); 

In diesem Fall wird ein neuer Delegatobjekt erstellt wird, sondern darüber hinaus den Ruf zu ForEach ist es nicht Bezug genommen wird, und somit für die Garbage Collection in Betracht.

Allerdings Aufruf Delegierten selbst produziert nicht Müll, mehr als jede andere Methode des gleichen Typs aufrufen würde. Wenn Sie beispielsweise einen Delegaten aufrufen, der einen Object-Parameter verwendet und einen Int32-Wert übergibt, wird dieser Wert eingerahmt, aber das würde passieren, wenn Sie eine normale Methode genauso aufrufen würden.

Die Verwendung von Delegaten sollte also in Ordnung sein, aber die übermäßige Erstellung von Delegatobjekten ist ein Problem.


bearbeiten: Ein guter Artikel über die Speicherverwaltung für Xbox und XNA ist hier: Managed Code Performance on Xbox 360 for XNA: Part 2 - GC and Tools. Beachten Sie dieses Angebot:

Also, wie steuert man GC-Latenzzeit? Wie NetCF für Geräte ist die Xbox GC nicht generationsübergreifend. Das bedeutet, dass jede Sammlung eine vollständige Sammlung auf dem verwalteten Heap ist. Daher stellen wir fest, dass die GC-Latenz ungefähr linear zur Anzahl der Live-Objekte ist ... und fügen Sie dann die Kosten für die Heap-Komprimierung hinzu. Unsere Benchmarks zeigen, dass der Unterschied zwischen tiefen Objekthierarchien und oberflächlichen Objekthierarchien vernachlässigbar ist. Daher ist es hauptsächlich die Anzahl der Objekte, auf die es ankommt. Kleine Objekte sind auch etwas billiger als große Objekte.

Wie Sie sehen können, versuchen Sie zu vermeiden, viele unnötige Objekte zu erstellen, und Sie sollten besser fahren.

+0

Ich sehe, gut, das ist gut zu wissen, obwohl der Versuch, Delegierte zu verwenden, ohne irgendwelche zu erstellen (außer zur Ladezeit), wird interessant sein. – Martin

+1

Fast alles in C# erstellt auf diese Weise Müll. Ich würde nicht empfehlen, die Verwendung von kurzlebigen Referenzen zu vermeiden. –

+3

Normalerweise würde ich auch nicht, aber auf der Xbox, mit der XNA-Plattform, wenn Sie GC verschieben können (dh es weniger oft laufen lassen) ohne negative Auswirkungen, das ist wirklich eine gute Idee, da es * macht für abgehackt Gameplay, wenn es zu oft vorkommt. Es ist also eine gute Idee, wenn Sie wissen, was zu GC beiträgt und wann Sie es beheben möchten. Zum Beispiel, in dem Code, den ich gezeigt habe, wenn Sie diese ForEach-Schleife häufig ausführen, sollten Sie den Delegaten möglicherweise irgendwo in einer Variablen speichern, wenn das Verhalten nicht geändert wird. Spieloptimierungen unterscheiden sich normalerweise von normalen Desktop-DB-Apps. –

14

In der Desktop-Umgebung Müll ist effektiv frei. Dort, worüber du dir Sorgen machen willst ist, wie viel nicht Müll du produzierst. Denken Sie daran, wie der Garbage Collector funktioniert: Er markiert zuerst alle bekannten Objekte, dann löscht er die Markierung auf allen Live-Objekten und komprimiert die Live-Objekte. Der teure Schritt dort ist "Markierung der Live-Objekte".Den Müll zu zerstören ist billig; Es identifiziert die Live-Objekte, die teuer sind, und diese Kosten hängen von der Anzahl der Live-Objekte ab, die Sie haben (und der Komplexität ihrer Referenztopologie), und nicht von der Anzahl der toten Objekte, die Sie haben.

Allerdings läuft der Garbage Collector auf XBOX und anderen kompakten Frameworks ziemlich häufig und wird häufiger ausgeführt, wenn neue Zuordnungen erstellt werden, also sind Sie richtig, wenn Sie sich Sorgen über das Erstellen von Garbage machen. Sie wollen sowohl das Live-Set klein halten und keine neuen Zuweisungen machen (so wie eine Sammlung billig zu machen) (weil diese Sammlungen auslöst.)

Erstellen ein Delegierter Speicher zuteilt, aber Aufruf ist nichts mehr als das Aufrufen einer Methode namens Invoke für eine Klasse. Ein Delegat ist nicht viel mehr als eine Klasse mit einer Methode namens Invoke, die zufällig ruft eine andere Methode, wenn es aufgerufen wird.

Unabhängig davon, ob Sie ein Problem mit der Speicherleistung haben, dann ist es das Richtige, den Speicherprofiler zu entfernen und damit Ihr Programm zu analysieren. Casting über zufällig, sich zu fragen, ob dies oder das geschieht, um Speicher zuzuweisen, ist wie zu versuchen, Ihren Garten mit Nagelschere zu jäten; Es braucht viel Zeit und erreicht nicht wirklich Ihre Ziele. Verwenden Sie einen Profiler, um Ihre Leistung zu analysieren und festzustellen, wo sich die Probleme befinden, und beheben Sie sie anschließend.

+0

Ich neige dazu, mit Ihnen zuzustimmen, und ich sorge mich nicht wirklich um Müll - ich möchte nur informiert werden! Sind Sie jedoch sicher, dass dies auf der xbox der Fall ist, wo der Kollektor nicht generationsübergreifend ist? – Martin

+0

Es ist immer noch Mark-N-Sweep, auch wenn es nicht generationsübergreifend ist. –

+2

Die Leistung der Xbox XNA GC ist relativ zur Anzahl der Live/Dead-Objekte, also versuchen Sie, die Gesamtzahl der Objekte niedrig zu halten. Und ja, verwenden Sie einen Speicher-Profiler, um herauszufinden, ob Sie wirklich ein Problem haben. –

1

Delegate Erstellung generiert Müll, wie bereits erwähnt.

In Ihrem Beispiel wird mit params Argument wahrscheinlich auch Müll erzeugt.

Erwägen Sie die Bereitstellung von Überladungen, ohne das Schlüsselwort params zu verwenden.

Das ist der Grund, warum Überlastungen mit einer unterschiedlichen Anzahl von Argumenten in der Regel in der Bibliothek Methoden existieren, zusammen mit dem man mit params Stichwort:

Siehe String.Format Method (String, Object[])

Format Method (String, Object) 
Format Method (String, Object[]) 
... 
Format Method (String, Object, Object) 
Format Method (String, Object, Object, Object) 
Verwandte Themen