GC.AddMemoryPressure

Я пишу приложение в C#, который использует третью сторону COM DLL, этот dll создает много ресурсов (как битовые массивы, видео, структуры данных) в неуправляемой памяти. В то время как рытье вокруг я столкнулся со следующим призывом к Сборщику "мусора":

GC.AddMemoryPressure(long long bytesAllocated)

Это документируется в MSDN здесь:

http://msdn.microsoft.com/en-us/library/system.gc.addmemorypressure.aspx

Это походит на что-то, что я должен называть, так как этот внешний dll является createing много ресурсов, о которых не знает CLR.

Я предполагаю, что у меня есть два вопроса...

  1. Как я знаю, сколько давления памяти для добавления, когда dll является третьей стороной и для меня не возможно знать точно, сколько памяти этот dll выделяет.
  2. Как важный это должно сделать это?

6
задан John Saunders 11 April 2010 в 19:09
поделиться

4 ответа

В любом смешанном собственном / управляемом процессе используется сочетание собственной / управляемой памяти. Если между ними нет связи, контролируемой сборщиком мусора, то в этом API не будет необходимости. Например, если есть определенные детерминированные изменения состояния в управляемом коде, которые вызывают выделение и освобождение собственной памяти, то ничто, что может сделать GC, никогда не заставит освободить внутреннюю память.

Однако очень часто есть собственная память, удерживаемая управляемыми объектами, у которых есть финализаторы. Таким образом, GC может уменьшить размер собственной кучи, просто запустив сбор и запустив те финализаторы.

Поэтому, если у вас много всего этого, вполне может возникнуть необходимость вызвать этот API (как сказано в документации).

Что касается того, сколько вы должны это сказать, это, вероятно, не то, на что вы можете придумать ответ с помощью чистого анализа, особенно с помощью сторонней библиотеки. Вам нужно запустить Performance Monitor, запустить тест, который выделяет множество сторонних объектов, и посмотреть на счетчики Native Bytes и CLR памяти, чтобы увидеть, как они соотносятся.

Поскольку вы используете COM-объект, вы можете детерминированно принудительно принудительно очистить экземпляры, когда знаете, что они вам больше не нужны, с помощью Marshal.ReleaseComObject . Обратите внимание, что вам нужно использовать тупой цикл, чтобы избавиться от объекта:

while (Marshal.ReleaseComObject(obj) != 0) 
{
}
5
ответ дан 9 December 2019 в 22:31
поделиться

Самое важное, что вы можете сделать, - это вызвать метод Dispose () для этих сторонних классов DLL и относиться к нему с абсолютным фанатизмом. (Или, конечно, используя блоки using, поскольку они вызывают Dispose () автоматически при выходе из блока.)

Суть неуправляемых ресурсов заключается в том, что классы .NET, которые их обертывают или используют, должны иметь финализатор, поскольку а также реализация шаблона IDisposable (). Если вызывается Dispose (), он должен немедленно позаботиться о неуправляемых ресурсах, а также подавить финализатор. Если вы не вызываете Dispose (), то у вас настоящие проблемы с памятью, и добавление «давления» на сборщик мусора не исправит этого.

Основная логика сборщика мусора заключается в том, что любой класс, имеющий активный финализатор, не обрабатывается, пока не будут исчерпаны все другие возможности. Это означает, что очистка gen0, gen1 и gen2 уже произошла. Финализатор, который не был подавлен, почти так же плох, как утечка памяти.

Поэтому вызовите Dispose (). Убедитесь, что вы никогда не пропустите это.

РЕДАКТИРОВАТЬ: Только что заметил, что сторонняя DLL является COM-DLL. Лучше всего убедиться, что ваши .NET-оболочки полностью реализуют IDisposable () (а не просто предоставляют метод Dispose). Затем убедитесь, что вы всегда вызываете Dispose () после завершения работы с COM-объектами.

2
ответ дан 9 December 2019 в 22:31
поделиться

Допустим, у меня есть такой объект:

public class SomeImageType : IDisposable
{
    public int Width { get; private set; }
    public int Height { get; private set; }
    public PixelFormat PixelFormat { get; private set; }
    IntPtr ImageData { get; private set; }
    // implementation of constructor and IDisposable not shown
}

Сколько памяти для этого требуется? 20 байт + накладные расходы на объект? Когда приходит время для сбора, если у этого объекта нет ссылок, это вообще не имеет значения. Но нужны ли эти 20 байт? Нет, черт возьми, это изображение. Итак, возьмите эти 20 и умножьте на ширину, высоту и количество байтов на пиксель, и вы получите что-то, что занимает (возможно) мегабайты. Сообщая сборщику мусора о необходимости увеличения нагрузки на память, вы говорите, что там есть айсберг, поглощающий ресурсы. Когда вы избавляетесь от объекта, вы, конечно же, освобождаете эту память и приказываете сборщику мусора сбросить это давление. Эти два вызова позволяют нам намекнуть сборщику мусора, что с Circle K творится странные вещи, и, возможно, он хотел бы по-другому запланировать сбор данных.

3
ответ дан 9 December 2019 в 22:31
поделиться

Это не важно, если вы не замечаете проблем с памятью, которые, по вашему мнению, вызваны сборщиком мусора.

1
ответ дан 9 December 2019 в 22:31
поделиться
Другие вопросы по тегам:

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