Wie kann nicht verwendeter Speicher aus dem großen Objekthaufen LOH von mehreren verwalteten Apps zurückgewonnen werden?

Während eines Gesprächs mit einem Kollegen über eine bestimmte Gruppe von Apps, die beim Start fast 1,5 GB Speicher verbrauchen, verwies er mich auf einen sehr guten Link zu.NET-Produktions-Debugging

Der Teil, der mich verwirrt hat, ist ...

Wenn Sie beispielsweise einem einzelnen Block 1 MB Speicher zuweisen, wird der Heapspeicher für große Objekte auf 1 MB erweitert. Wenn Sie dieses Objekt freigeben, wird der virtuelle Speicher durch den Heapspeicher für große Objekte nicht freigegeben, sodass die Größe des Heapspeichers 1 MB beträgt. Wenn Sie später einen weiteren 500-KB-Block zuweisen, wird der neue Block innerhalb des 1-MB-Speicherblocks zugewiesen, der zum Heap für große Objekte gehört. Während der Prozesslebensdauer wird der Heap für große Objekte immer größer, um alle derzeit referenzierten Zuordnungen für große Blöcke aufzunehmen, verkleinert sich jedoch nie, wenn Objekte freigegeben werden, selbst wenn eine Garbage Collection auftritt. Abbildung 2.4 auf der nächsten Seite zeigt ein Beispiel für einen großen Objekthaufen.

Nehmen wir an, wir haben eine fiktive App, die eine Flut von großen Objekten (> 85 KB) erzeugt, sodass der Haufen großer Objekte auf 200 Meg wächst. Nehmen wir nun an, wir haben 10 solcher App-Instanzen in Betrieb, so dass 2000 Megabyte zugewiesen werden. Jetzt wird dieser Speicher erst wieder an das Betriebssystem zurückgegeben, wenn der Prozess beendet ist ... (habe ich verstanden)

Gibt es Lücken in meinem Verständnis? Wie erhalten wir nicht verwendeten Speicher in den verschiedenen LOHeaps zurück? erstellen wir nicht den perfekten Sturm von OutOfMemoryExceptions?

Aktualisieren: Aus Marc 'Antwort wollte ich klarstellen, dass die LOH-Objekte nicht referenziert werden - die großen Objekte sind use-n-throw - jedoch schrumpft der Heap nicht, obwohl der Heap nach dem ersten Anstieg relativ leer ist.

Update Nr. 2: Einschließlich eines Code-Snippets (übertrieben, aber ich denke, das ist ein klarer Punkt). Ich sehe eine OutOfMemoryException, wenn der virtuelle Speicher auf meinem Computer die 1,5-G-Marke erreicht (auf einem anderen 1,7-G)Eric L.'s Blog Post, 'Prozessspeicher kann als massive Datei auf der Festplatte dargestellt werden.' - Dieses Ergebnis ist daher unerwartet. Die Computer in diesem Fall verfügten über GB freien Speicherplatz auf der Festplatte. Verursacht die PageFile.sys-Betriebssystemdatei (oder verwandte Einstellungen) Einschränkungen?

<code>        static float _megaBytes;
        static readonly int BYTES_IN_MB = 1024*1024;

        static void BigBite()
        {
           try
           {
              var list = new List<byte[]>();
              int i = 1;

              for (int x = 0; x < 1500; x++)
              {
                 var memory = new byte[BYTES_IN_MB + i];
                 _megaBytes += memory.Length / BYTES_IN_MB;
                 list.Add(memory);
                 Console.WriteLine("Allocation #{0} : {1}MB now", i++, _megaBytes);
              }
           }
           catch (Exception e)
           {  Console.WriteLine("Boom! {0}", e); // I put a breakpoint here to check the console
              throw;
           }
        }
       static void Main(string[] args)
        {
            BigBite();
            Console.WriteLine("Check VM now!"); Console.ReadLine();
            _megaBytes = 0;

            ThreadPool.QueueUserWorkItem(delegate { BigBite(); });
            ThreadPool.QueueUserWorkItem(delegate { BigBite(); });
            Console.ReadLine();   // will blow before it reaches here
        }
</code>

Antworten auf die Frage(3)

Ihre Antwort auf die Frage