Я пишу приложение в C#, который использует третью сторону COM DLL, этот dll создает много ресурсов (как битовые массивы, видео, структуры данных) в неуправляемой памяти. В то время как рытье вокруг я столкнулся со следующим призывом к Сборщику "мусора":
GC.AddMemoryPressure(long long bytesAllocated)
Это документируется в MSDN здесь:
http://msdn.microsoft.com/en-us/library/system.gc.addmemorypressure.aspx
Это походит на что-то, что я должен называть, так как этот внешний dll является createing много ресурсов, о которых не знает CLR.
Я предполагаю, что у меня есть два вопроса...
В любом смешанном собственном / управляемом процессе используется сочетание собственной / управляемой памяти. Если между ними нет связи, контролируемой сборщиком мусора, то в этом API не будет необходимости. Например, если есть определенные детерминированные изменения состояния в управляемом коде, которые вызывают выделение и освобождение собственной памяти, то ничто, что может сделать GC, никогда не заставит освободить внутреннюю память.
Однако очень часто есть собственная память, удерживаемая управляемыми объектами, у которых есть финализаторы. Таким образом, GC может уменьшить размер собственной кучи, просто запустив сбор и запустив те финализаторы.
Поэтому, если у вас много всего этого, вполне может возникнуть необходимость вызвать этот API (как сказано в документации).
Что касается того, сколько вы должны это сказать, это, вероятно, не то, на что вы можете придумать ответ с помощью чистого анализа, особенно с помощью сторонней библиотеки. Вам нужно запустить Performance Monitor, запустить тест, который выделяет множество сторонних объектов, и посмотреть на счетчики Native Bytes и CLR памяти, чтобы увидеть, как они соотносятся.
Поскольку вы используете COM-объект, вы можете детерминированно принудительно принудительно очистить экземпляры, когда знаете, что они вам больше не нужны, с помощью Marshal.ReleaseComObject . Обратите внимание, что вам нужно использовать тупой цикл, чтобы избавиться от объекта:
while (Marshal.ReleaseComObject(obj) != 0)
{
}
Самое важное, что вы можете сделать, - это вызвать метод Dispose () для этих сторонних классов DLL и относиться к нему с абсолютным фанатизмом. (Или, конечно, используя блоки using, поскольку они вызывают Dispose () автоматически при выходе из блока.)
Суть неуправляемых ресурсов заключается в том, что классы .NET, которые их обертывают или используют, должны иметь финализатор, поскольку а также реализация шаблона IDisposable (). Если вызывается Dispose (), он должен немедленно позаботиться о неуправляемых ресурсах, а также подавить финализатор. Если вы не вызываете Dispose (), то у вас настоящие проблемы с памятью, и добавление «давления» на сборщик мусора не исправит этого.
Основная логика сборщика мусора заключается в том, что любой класс, имеющий активный финализатор, не обрабатывается, пока не будут исчерпаны все другие возможности. Это означает, что очистка gen0, gen1 и gen2 уже произошла. Финализатор, который не был подавлен, почти так же плох, как утечка памяти.
Поэтому вызовите Dispose (). Убедитесь, что вы никогда не пропустите это.
РЕДАКТИРОВАТЬ: Только что заметил, что сторонняя DLL является COM-DLL. Лучше всего убедиться, что ваши .NET-оболочки полностью реализуют IDisposable () (а не просто предоставляют метод Dispose). Затем убедитесь, что вы всегда вызываете Dispose () после завершения работы с COM-объектами.
Допустим, у меня есть такой объект:
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 творится странные вещи, и, возможно, он хотел бы по-другому запланировать сбор данных.
Это не важно, если вы не замечаете проблем с памятью, которые, по вашему мнению, вызваны сборщиком мусора.