Вопрос по .net, c# – Как вернуть неиспользованную память из кучи больших объектов LOH из нескольких управляемых приложений?

8

Во время разговора с коллегой о конкретной группе приложений, использующих почти 1,5 ГБ памяти при запуске ... он указал мне на очень хорошую ссылку на.NET отладка продукции

То, что меня озадачило, это ...

For example, if you allocate 1 MB of memory to a single block, the large object heap expands to 1 MB in size. When you free this object, the large object heap does not decommit the virtual memory, so the heap stays at 1 MB in size. If you allocate another 500-KB block later, the new block is allocated within the 1 MB block of memory belonging to the large object heap. During the process lifetime, the large object heap always grows to hold all the large block allocations currently referenced, but never shrinks when objects are released, even if a garbage collection occurs. Figure 2.4 on the next page shows an example of a large object heap.

Теперь предположим, что у нас есть вымышленное приложение, которое создает поток больших объектов (& gt; 85 КБ), так что куча больших объектов увеличивается, скажем, до 200 Мег. Теперь допустим, что у нас запущено 10 таких экземпляров приложения, так что выделено 2000 мегабайт. Теперь эта память никогда не возвращается в ОС, пока процесс не остановится ... (это то, что я понял)

Есть ли пробелы в моем понимании? Как нам вернуть неиспользованную память в различных LOHeaps; мы не создаем идеальный шторм исключений OutOfMemory?

Update: Из ответа Марка я хотел уточнить, что на объекты LOH не ссылаются - большие объекты используют use-n-throw - однако куча не уменьшается, даже несмотря на то, что куча относительно пуста после первоначального всплеска.

Update#2: Просто включаю фрагмент кода (преувеличено, но я думаю, что это понятно) .. Я вижу исключение OutOfMemoryException примерно в то время, когда виртуальная память достигает отметки 1,5G на моей машине (1,7G на другой)Сообщение Эрика Л. в блоге, «память процесса может быть визуализирована как массивный файл на диске». - этот результат, таким образом, неожиданный. У машин в этом случае было ГБ свободного места на жестком диске. Налагает ли файл ОС PageFile.sys (или связанные с ним настройки) какие-либо ограничения?

<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>
(ответил на комментарий) Marc Gravell♦

Ваш Ответ

3   ответа
3

это зависит от LOH - однако, не забывайте, чтоOutOfMemoryException это процесс, так как на самом деле жесткий диск является ограничивающим фактором для виртуальной памяти. Эрик Липпертнаписал об этом в блоге относительно недавно. Конечно, это не предотвращает снижение производительности при всех вызовах ...

Спасибо за ссылку .. прикрепил фрагмент кода, который смущает меня еще больше, но похож на проблему, которая запустила эту тему. Ваши мысли как всегда очень ценятся. Спасибо за работу, которую вы делаете на этом форуме ... Gishu
Я не уверен, что редактирование что-либо меняет. Смысл, который я пытался сделать, состоит в том, что наличие шарика и цепи размером 200 МБ не являетсяnecessarily проблема. Большая часть этого, вероятно, выйдет из основной памяти из-за неактивности ...
Обновим вопрос: сами объекты LOH в этом случае используют use-n-throw ... как только они достигли своей цели, объекты LOH были освобождены, но куча не уменьшается. Рассмотрим компонент, который выполняет некоторую сериализацию объектов перед отправкой по конвейеру: в этом случае вы выделяете, скажем, 200 Мегабайт в виде байтовых массивов, которые являются мусором после передачи данных. Gishu
2

если у вас действительно есть такой шаблон распределения, вы можете переместить свои большие объекты в другой домен приложения - когда вы решите освободить все большие объекты, освободите домен приложения, и куча для этого домена приложения будет освобождена.

LOH не в Appdomain.
5

- Если вы используете приложение как 32-битное приложение, пространство виртуальной машины, доступное для вашего процесса, составляет всего 2 ГБ, 3 ГБ, если вы включили переключатель большого адресного пространства, поэтому даже если у вас есть ОГРОМНЫЙ файл подкачки, это не имеет значения, если вы 32-битный процесс, имеет значение, если вы запускаете 64-битную, где у вас есть огромное адресное пространство.

Object with size > 85000 bytes are allocated on LOH, note it is 85000 bytes not 85K, it is also implementation details that could change. Now, back to your question. The GC will un-commit the LOH segments that are not used in 2 situations 1- When the memory pressure on the machine is high ( ~95-98% ) 2- When it fails to satisfy new allocation requests, it will decommit the unused pages in the LOH

так что вы вернете память в одном из этих случаев. Тот факт, что вы нажимаете OOM до того, как достигнете предела в 2 ГБ, может означать, что у вас есть фрагментация VA, фрагментация VA происходит, когда у вас нет непрерывного адресного пространства VA для удовлетворения нового выделения, например, вы запрашиваете сегмент размером 8 КБ, и вы не делаете; в вашем VA должно быть 2 последовательных страницы (при условии, что размер страницы равен 4 КБ)

Вы можете использовать расширение! vamap отладчик в инструментах отладки для окон, чтобы проверить это.

Надеюсь это поможет Спасибо

Похожие вопросы