Делаем фоновое приложение с большим объемом памяти "дружественным" - PullRequest
4 голосов
/ 25 октября 2009

У меня есть приложение, которое периодически должно обрабатывать большие блоки данных с помощью вычислительно тривиального алгоритма. Оказывается, я также могу предотвратить замедление системы от доступа к жесткому диску, храня блоки данных в кеше памяти. Приложение является приложением с низким приоритетом, поэтому я работаю над тем, чтобы минимизировать его влияние на систему по всем направлениям, что означает использование дополнительной памяти (при наличии) для снижения нагрузки на процессор и жесткие диски. Кэшированные данные занимают всего 64 МБ блоков байтов, и чем больше у меня в памяти, тем меньше накладных расходов у программы на дисках.

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

Меня особенно интересует, как это можно сделать в приложении .NET.

Ответы [ 3 ]

2 голосов
/ 25 октября 2009

Один из вариантов - использовать ASP.NET Cache, который очищает элементы в ответ на нехватку памяти. Хотя Microsoft придает большое предупреждение о том, что он тестируется только в приложении ASP.NET, ничто не мешает вам получить доступ к HttpRuntime.Cache в любом приложении, и на практике это сработало, когда я это сделал.

Если это кажется грязным и неправильным (или просто не делает то, что вам нужно), мы можем по крайней мере черпать вдохновение из того, что ASP.NET знает, как очистить кэш. Он периодически вызывает ядро ​​ GlobalMemoryStatusEx , чтобы выяснить доступную память. В частности, свойство dwMemoryLoad возвращенной структуры является процентом общего объема используемой памяти. По умолчанию ASP.NET считает, что память заканчивается, когда она достигает 90%.

Вот пример кода, который можно назвать самим здесь .

1 голос
/ 25 октября 2009

Вы можете запустить P / Invoke до Win32 CreateMemoryResourceNotification API с опцией LowMemoryResourceNotification. Это возвращает объект уведомления, который вы можете либо опрашивать (используя QueryMemoryResourceNotification), либо ждать (в фоновом потоке; вам потребуется использовать один из методов ожидания Win32, а не метод ожидания .NET, или, возможно, получить собственный класс из WaitHandle для инкапсуляции объекта Win32). Вы бы ответили, отбросив блоки из вашего кеша и форсировав сборку мусора; вам нужно проверить, достаточно ли это «быстро, чтобы пользователь никогда не чувствовал замедление работы системы».

Кроме того, при просмотре документов пороговое значение для уведомления о недостаточном объеме памяти составляет реально мало памяти (32 МБ в системе 4 ГБ!). Я подозреваю, что к тому времени пользователь, возможно, уже почувствовал замедление, и подкачка вашего приложения в память для выгрузки его блоков может вызвать ощутимый доступ к диску. Опять же, вы можете оценить это с помощью тестирования.

0 голосов
/ 25 октября 2009

Вы можете использовать класс WeakReference, чтобы иметь слабые ссылки на блоки памяти. Это позволяет сборщику мусора удалять объекты при необходимости.

Ваши объекты будут в куче больших объектов, так как они больше 85 КБ. Наиболее распространенная сборка мусора смотрит только на кучу первого поколения, поэтому она не будет собирать ваши объекты. Если система уведомляет систему .NET о нехватке памяти, сборщик мусора выполнит более тщательный сбор, удалив ваши объекты в куче больших объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...