我有一个在静态字段中保存/缓存许多对象的应用程序。当在应用程序的生命周期中保存了大量对象时,会抛出内存不足异常,因为缓存变得太大了。
是否有任何类或对象通知我内存快用完了,并且很快就会抛出一个outofmemoryexception,这样我就可以知道我需要通过删除一些缓存对象来释放一些内存?我正在寻找应用程序中存在内存压力的迹象,以便在抛出内存异常之前,在应用程序运行期间采取预防措施。
发布于 2013-06-16 02:08:43
我还有一个应用程序,它尽可能多地使用ram。根据您的特定场景,您有几个选择(都有缺点)。
最简单的方法之一是预先分配一个类(或字节)的循环缓冲区,缓存这些类(或字节)以预先消耗所有ram。这通常是不可取的,因为当你不需要的时候消耗一个机器上的所有内存是非常粗鲁的。
处理大型缓存(或避免抛出内存异常)的另一种方法是在分配之前首先检查我需要的内存是否存在。这样做的缺点是需要序列化内存分配。否则,检查可用内存和分配内存之间的时间可能会耗尽内存。
下面是我在.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.此外,一旦我进入while循环,我就会通知需要释放一些内存(取决于您的应用程序)。注意:我试图通过使用休眠语句来简化代码,但如果可能的话,最终您会希望使用某种类型的非轮询操作。
我不确定你的应用程序的细节,但如果你是多线程的,或者运行许多不同的可执行文件,那么当分配内存到缓存时,序列化这个内存检查可能会更好。如果是这种情况,我使用信号量来确保只有一个线程和/或进程可以根据需要分配RAM。如下所示:
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类)。这样做的好处是,当你在写的时候,可以检查内存压力和清理,然后向缓存中添加更多,但仍然有多个线程处理数据。缺点当然是将数据放入缓存的瓶颈来自单个固定点。
发布于 2013-06-16 00:33:25
如果缓存的数据太多,导致内存不足,则表明缓存方法存在严重问题。即使作为32位进程,您也有2 GB的地址空间。
您应该考虑使用有限的高速缓存,其中用户可以设置首选的高速缓存大小,当达到此大小时,您可以自动删除对象。您可以实现特定的缓存策略来挑选要从缓存中删除的对象:最旧的对象、最不常用的对象或这些对象的组合。
您还可以尝试将某些缓存映射到磁盘,并仅将最常用的对象保留在内存中。当需要一个不在内存中的对象时,可以从磁盘中反序列化它,并将其放回内存中。如果某个对象在一段时间内未使用,则可以将其交换到磁盘。
https://stackoverflow.com/questions/17125438
复制相似问题