2013-06-15 2 views
1

У меня есть приложение, которое сохраняет/кэширует множество объектов в статическом поле. Когда есть много объектов, сохраненных в течение всего жизненного цикла приложения, исключается исключение из памяти, потому что кеш становится настолько большим.Информер давления/счетчик/статистика

Есть ли какой-либо класс или объект, который сообщает мне, что память заканчивается, и скоро будет запущен outofmemoryexception, чтобы я мог знать, что мне нужно освободить память, удалив некоторые из этих кешированных объектов? Я ищу признак того, что в приложении присутствует давление памяти, поэтому я могу принять меры предосторожности во время выполнения приложения до того, как будет выброшено исключение памяти.

+0

проверить этот ответ: http://stackoverflow.com/a/1248141/941243 – Chris

ответ

0

У меня также есть приложение, которое использует как можно больше бара. У вас есть пара вариантов в зависимости от вашего конкретного сценария (у всех есть недостатки).

Одним из простейших является предварительное распределение кругового буфера классов (или байтов), которые вы кешируете, чтобы потреблять все фронты фронтов. Обычно это не является предпочтительным, потому что потребление всей ОЗУ на ящике, когда вам не нужно, является просто грубым.

Другой способ обработки больших кешей (или избежать исключений из памяти) заключается в том, чтобы сначала проверить, что память, которая мне нужна, существует до выделения. Это имеет недостаток в необходимости сериализации распределения памяти. В противном случае время между доступной оперативной памятью и выделением из ОЗУ может закончиться.

Вот образец наилучшим образом я нашел, чтобы сделать это в .NET:

//Wait for enough memory 
var temp = new System.Diagnostics.PerformanceCounter("Memory", "Available MBytes"); 
long freeMemory = Convert.ToInt64(temp.NextValue()) * (long)1000000; 
long neededMemory = (long)bytesToAllocate; 
int attempts=1200; //two minutes 

while (freeMemory < neededMemory) 
{ 
    //Signal that memory needs to be freed 
    Console.WriteLine("Waiting for enough free memory:. Free Memory:" + freeMemory + " Needed Memory(MB):" + neededMemory); 
    System.Threading.Thread.Sleep(100); 
    freeMemory = Convert.ToInt64(temp.NextValue()) * (long)1000000; 
    --attempts; 

    if (0 == attempts) 
      throw new OutOfMemoryException("Could not get enough free memory. File:" + Path.GetFileName(wavFileURL)); 
} 

//Try and allocate the memory we need. 

Кроме того, как только я нахожусь внутри цикла в то время как я сигнализировать, что некоторый объем памяти должен быть освобожден (в зависимости от вашего заявление). ПРИМЕЧАНИЕ. Я попытался упростить код, используя оператор Sleep, но в конечном итоге вам понадобится какой-то тип операции без опроса, если это возможно.

Я не уверен в специфике вашего приложения, но если вы многопоточны или запускаете много разных исполняемых файлов, то может быть лучше сериализовать эту проверку памяти при выделенной памяти в кеш. Если это так, я использую Семафор, чтобы убедиться, что только один поток и/или процесс могут выделять ОЗУ по мере необходимости. Подобно этому:

Semaphore namedSemaphore = new Semaphore(1, 1, "MemoryAllocationSemaphore"); //named semaphores are cross process 
    if (bytesToAllocate > 2000000) //if we need less than 2MB then dont bother locking. 
    { 
      if (!namedSemaphore.WaitOne((int)TimeSpan.FromMinutes(15).TotalMilliseconds)) 
      { 
       throw new TimeoutException("Waited over 15 minutes for aquiring memory allocation semaphore"); 
      } 
    } 

Затем немного позже по вызову это:

namedSemaphore.Release(); 

в финальном блоке, чтобы освободить семафор.

Другой вариант заключается в использовании блокировки с одним считывателем нескольких считывателей.Чтобы несколько потоков вытягивали данные из кеша (например, класс ReaderWriterLock). Это имеет то преимущество, что, когда вы пишете, чтобы проверить давление и очистку памяти, добавьте еще больше в кеш, но все еще имеете несколько потоков обработки данных. Недостатком, конечно же, является то, что шейка бутылки для получения данных в кеш поступает из одной фиксированной точки.

0

Если у вас столько кэшированных данных, что у вас заканчивается память, что указывает на что-то серьезно неправильное в вашем подходе к кешированию. Даже в 32-разрядном режиме у вас есть адресное пространство 2 ГБ.

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

Вы также можете попытаться отобразить часть своего кеша на диск и сохранить только наиболее часто используемые объекты в памяти. Когда нужен объект, который отсутствует в памяти, вы можете дезацинировать его с диска и вернуть его обратно в память. Если объект не используется в течение определенного периода времени, вы можете поменять его на диск.

Смежные вопросы