Jak odzyskać nieużywaną pamięć z dużej sterty obiektów LOH z wielu zarządzanych aplikacji?

Podczas rozmowy z kolegą o konkretnej grupie aplikacji wykorzystujących prawie 1,5 GB pamięci podczas uruchamiania ... wskazał mi bardzo dobry linkDebugowanie produkcji .NET

Część, która mnie zaintrygowała, to ...

Na przykład, jeśli przydzielisz 1 MB pamięci do pojedynczego bloku, sterta dużego obiektu rozszerzy się do rozmiaru 1 MB. Gdy zwolnisz ten obiekt, sterta dużego obiektu nie anuluje pamięci wirtualnej, więc sterta ma rozmiar 1 MB. Jeśli później przydzielisz kolejny blok o rozmiarze 500 KB, nowy blok zostanie przydzielony w bloku pamięci o wielkości 1 MB należącym do stosu dużych obiektów. W czasie trwania procesu sterta dużych obiektów zawsze rośnie, aby pomieścić wszystkie przydziały dużych bloków, do których obecnie się odwołuje, ale nigdy nie zmniejsza się, gdy obiekty są zwalniane, nawet jeśli wystąpi zbieranie śmieci. Rysunek 2.4 na następnej stronie pokazuje przykład sterty dużych obiektów.

Teraz załóżmy, że mamy fikcyjną aplikację, która tworzy lawinę dużych obiektów (> 85 KB), więc duża sterta obiektu rośnie, powiedzmy do 200 Meg. Teraz powiedzmy, że mamy 10 takich instancji aplikacji działających tak, że przydzielono 2000 Megs. Teraz ta pamięć nigdy nie jest zwracana do systemu operacyjnego, dopóki proces się nie zamknie ... (co zrozumiałem)

Czy są jakieś luki w moim rozumieniu? Jak odzyskać nieużywaną pamięć w różnych LOHeapach; nie tworzymy idealnej burzy wyjątków OutOfMemory?

Aktualizacja: Z odpowiedzi Marca chciałem wyjaśnić, że obiekty LOH nie są przywoływane - duże obiekty są używane -n-throw - jednak sterta nie kurczy się, nawet jeśli sterty są stosunkowo puste po początkowym przepływie.

Aktualizacja # 2: Po prostu dołączenie fragmentu kodu (przesadzonego, ale myślę o wszystkim). Widzę OutOfMemoryException w czasie, gdy pamięć wirtualna trafia na znak 1.5G na moim komputerze (1.7G na innym).Wpis na blogu Erica L., „pamięć procesu może być wizualizowana jako ogromny plik na dysku…” - wynik ten jest więc nieoczekiwany. Maszyny w tym przypadku miały GB wolnego miejsca na dysku twardym. Czy plik OS PageFile.sys (lub powiązane ustawienia) nakłada jakiekolwiek ograniczenia?

<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>

questionAnswers(3)

yourAnswerToTheQuestion