2009-05-07 12 views
14

Ist es möglich, eine minimale Größe eines Generation 0 Heap in .NET festzulegen?. NET-Generation 0 Heap-Größe

Ich habe eine folgende sistuation. Ich habe eine Funktion, die ca. 20-30 MB 1KB-Objekte zuweist, etwas damit macht, und beendet, wobei alle zugewiesenen Objekte als GC-ed übrig bleiben. Jetzt kann ich im Systemmonitor sehen, dass die Größe des Heapspeichers der Generation 0 5-6 MB beträgt, was nicht ausreicht, um alle benötigten 20-30 MB Objekte zu akzeptieren. Wenn ich mit dem Zuweisen anfange, beginnt gen0 GC irgendwann zu laufen, und da alle Objekte benötigt werden, fördert es sie zu einem gen1. Beim nächsten Start von GC werden diese Objekte in gen2 hochgestuft. Letztendlich landen etwa 15MB meiner Objekte im Gen2-Heap. Dies sind nach meiner Logik temporäre Objekte, die auf keinen Fall im gen2-Heap enden sollten. Ich glaube, das Problem liegt in der Größe der gen0 Heap-Größe. Aber ich bin mir nicht sicher. Ich weiß, dass es in Java eine Möglichkeit gibt, eine minimale Größe der Generationenhaufen festzulegen. Gibt es so einen Weg in .NET?

Antwort

3

Sind Sie sicher, dass Sie nicht mehr auf diese Objekte verweisen? Die GC ist sehr gut sich auf die Bedürfnisse Ihrer Anwendung zu tun und würde Objekte der Generation 2 nicht fördern, es sei denn, Sie hatten Wurzeln für diese Objekte irgendwo.

Ich denke, wenn Sie herausfinden, wo diese Wurzeln sind und sicherstellen, dass Sie wirklich nicht mehr auf diese Objekte verweisen, dann wird der GC beginnen, den Speicher für diese Objekte zu befreien und sie nicht auf Generation 1, geschweige denn Generation 2 zu fördern Wenn Sie dies tun, erkennt der GC, dass Sie die Generation 0 benötigen, um größer zu sein, und erhöht die Größe des Heaps in Ihrem Namen.

+1

Objekte, die größer als 85K sind, können generell nicht erfasst werden, außer in Gen2. Wenn ein Verweis auf ein neues Objekt in einem Objekt gespeichert wird, das größer als 85K ist, wird das neue Objekt, bis die Referenz innerhalb des großen Objekts zerstört wird, auf Gen2 aufsteigen, bevor es für die Sammlung in Frage kommt, auch wenn das Objekt zuvor entwurzelt wird. – supercat

1

+1 zu Andrew. Der GC ist selbst-tuning es lernt über die App Speicher brauchen Muster im laufenden Betrieb.
In Ihrem Fall, wenn der GC eine Sammlung von Gen 0 durchführt und feststellt, dass viele Objekte überlebt haben/nicht viel Speicher zurückgewonnen wurde, wird der Garbage Collector das Gen 0 Budget/Quota automatisch erhöhen.

Wenn Sie GC Type members betrachten, scheint es keine Möglichkeit zu geben, die GC-Generierungsbudgets/-größe programmatisch zu konfigurieren.

8

Die Größe der verschiedenen Generationen ist ein Implementierungsdetail, und mir sind keine Möglichkeiten bekannt, es für .NET-Anwendungen abzustimmen. Wenn mein Gedächtnis mir richtig dient Generation 0 und 1 teilen ein einzelnes Segment, das ist 16 MB in Win32, wenn Sie also eine ganze Menge von Objekten erstellen, werden einige von ihnen zu höheren Generationen heraufgestuft, wenn sie noch referenziert werden (wie du beschreibst).

Ich denke, die Idee hinter der Begrenzung der Größe der Generation 0 ist, um sicherzustellen, dass eine G0-Sammlung billig ist. Wenn Generation 0 auf eine beliebige Größe wachsen könnte, würde Ihre Gesamtleistung höchstwahrscheinlich leiden.

EDIT: Ich glaube, Jeffrey Richters Buch hat einige Details dazu, also sollten Sie das überprüfen.

EDIT2: Richter stellt fest (S. 502-507), dass das anfängliche Budget der Generation 0 256 KB beträgt und das erste Budget der ersten Generation 2 MB beträgt. Dies ist jedoch nicht die Größe der Generation. Die Budgets werden nach Bedarf angepasst und wachsen und schrumpfen je nach Speicherbedarf der Anwendung.

Joe Duffys Professional .NET Framework 2.0 besagt jedoch, dass die ephermalen Generationen (d. H. Gen 0 und 1) ein einzelnes Segment teilen, das normalerweise 16 MB ist (S. 117). Nur Generation 2 darf nach Bedarf wachsen (ich gehe davon aus, dass LOH nach Bedarf wachsen darf, aber das ist mir aus dem Text nicht klar).

+1

Gen 0 war 256KB (entspricht dem L2 Cache der CPU) Gen1 2MB Gen2 10MB nach Richters zweitem Buch. Natürlich unterliegen diese Änderungen ... – Gishu

+0

Laut Richter sind dies die Budgets der Generation 0 bzw. 1. Bitte beachten Sie meine Bearbeitung für Details. –

3

Der Heap der Generation 0 ist anfänglich auf den Cache Ihrer CPU zugeschnitten.Dies ist so, dass kleine temporäre Objekte nicht einmal in den Hauptspeicher verschoben werden müssen.

+0

Ich überwache gerade eine Anwendung mit einer gen0 Heap-Größe von über 500 MB. Also Gen0 Heap-Größe! = CPU-Cache-Größe. – sisve

+0

Siehe auch http://blogs.msdn.com/b/johan/archive/2007/04/20/memory-management-in-the-net-framework.aspx. Ich sollte meine Antwort wahrscheinlich bearbeiten, um sie genauer zu machen. –

0

Ich glaube nicht, dass es eine Möglichkeit gibt, diese Werte in .NET GC festzulegen.

Auf den ersten Blick sieht aus wie diese besondere Situation die Notwendigkeit erweiterte Optionen haben, so rechtfertigt, aber wenn dies wäre eine statische Option sein, dass es die ganze Lebensdauer Sie Programm beeinflussen. Eine dynamische Option, die Sie zur Laufzeit einstellen könnten, wäre ideal.

Auch ich glaube nicht, dass dies die Leistung Ihres Programms enorm beeinflussen wird, obwohl, wenn Sie in der Lage waren, die gen (0) Größe zu erhöhen, könnten Sie etwas Speicher freigeben (und einige Leistung).

Da der GC selbsttätig ist, wird gen (0) automatisch die Größe erhöhen und die BIG Objekte werden früher oder später Müll gesammelt werden.

+0

die OP-Situation ist eine große Anzahl von kleinen Objekten, die zur gleichen Zeit erreichbar sein müssen ... – Gishu

3

Vielen Dank für Ihre Hilfe.

Whell, die Situation ist sehr interessant. Ich habe nie erwähnt, dass ich diese 30 MB Objekte in einem Array mit einer Größe von 100000 speichere. Ich ordne zuerst dieses Array zu und fülle es dann mit Objekten. Da dieses Array größer als 85 KB ist, wird dieses Array im Heap für große Objekte gespeichert. Es stellt sich heraus, dass für die Garbage-Collection zum Sammeln von Objekten in diesem Heap die gen2-Auflistung ausgeführt werden muss. Daher wird jedes Mal, wenn im Large Objects Heap nicht genügend Speicherplatz vorhanden ist, der gen2-Collector ausgeführt, wodurch die Performance zerstört wird. Hier ist das einfache Beispiel, das ständig gen2 Sammlung aufrufen wird. Sie müssen es im Debug-Modus ausführen (wegen Compiler-Optimierungen).

static void Main(string[] args) 
{ 
    while (true) 
    { 
     byte[] objects = new byte[100000]; 
    } 
} 

Bedeutet dies, dass, wenn ich ein temporäres Array, dessen Größe brauchen, ist größer als 85K, dass Array in der larget Heap-Objekte werden am Ende?

+0

Sie können seit dieser Frage weitergegangen sein, nur ein Gedanke von mir beim Lesen dieses. Wenn Sie anstelle von Klassen Strukturen verwenden könnten, würde dies den Druck des GC stark reduzieren, da es nur das gesamte Array als einen zusammenhängenden Speicherblock reservieren und es als einen Block löschen müsste, es würde nur ein Verweis auf dieses Array sein Elemente selbst sind Werte, keine Objekte. Danach kann 'stackalloc' (anstelle von 'neu') Ihnen helfen, es schneller zuzuordnen und wieder freizugeben, obwohl Sie dies wirklich tun müssen, da es unsicher ist. – gjvdkamp

2

Bei der ersten Generation0 kann erhöhen und verringern, aber das sind in der Zukunft. Wenn der Prozess ausgeführt wird, hat der initialisierte verwaltete Heap eine feste Größe in der Generation0 256 KB (was Richter bedeutet), weil moderne Computer 256 und mehr Speicher für das Cash der CPU der zweiten Ebene haben. Sekunde. Andrew, du hast Recht. Wenn ein Objekt so groß ist, geht es sofort zu gen2. Ich nehme an, Sie wollten die gen0-Größe verringern, um häufiger GC zu provozieren, um ungenutzten Speicherplatz zu löschen und Ihre App leichter zu halten. Ich habe dasselbe Problem in einer SilverLight-Website und suche eine Lösung. Ich denke, was ist, wenn Code viele Objekte mit Wurzeln erzeugt und wenn gen0 voll ist, ruft CLR GC an, die sie zu gen1 bewegen, und wenn Objekte wachsen, bewegen sie sie dann zu gen2. Sagen wir, alle 3 Generationen sind fast voll. Dann rief zum Beispiel GC an. Was es tun wird. Einfach löschen generation0? Wie mit 1. und 2.. Ich denke, Lösung, um Speicherlicht zu halten, ist das Folgende. Erstellen Sie zuerst kleine und viele Objekte anstatt groß und weniger in der Anzahl. Die interne Referenzierung der zweiten Objekte muss in einer Richtung und nicht in einer chaotischen Beziehung zueinander stehen. Statische Objekte, die nicht dynamisch erzeugt werden, z. B. in Übereinstimmung mit Datensätzen aus der Datenbank, müssen in globalen Variablen gespeichert werden und nicht erneut erstellt werden, wenn der Code sie caliert.

Verwandte Themen