gpt4 book ai didi

c# - MemoryCache OutOfMemoryException

转载 作者:行者123 更新时间:2023-12-03 14:51:04 30 4
gpt4 key购买 nike

我试图弄清楚应该如何使用 MemoryCache 以避免出现内存不足异常。我来自 ASP.Net 背景,缓存管理它自己的内存使用,所以我希望 MemoryCache 会做同样的事情。正如我制作的波纹管测试程序所示,情况似乎并非如此:

class Program
{
static void Main(string[] args)
{
var cache = new MemoryCache("Cache");

for (int i = 0; i < 100000; i++)
{
AddToCache(cache, i);
}


Console.ReadLine();
}

private static void AddToCache(MemoryCache cache, int i)
{
var key = "File:" + i;
var contents = System.IO.File.ReadAllBytes("File.txt");
var policy = new CacheItemPolicy
{
SlidingExpiration = TimeSpan.FromHours(12)
};

policy.ChangeMonitors.Add(
new HostFileChangeMonitor(
new[] { Path.GetFullPath("File.txt") }
.ToList()));

cache.Add(key, contents, policy);
Console.Clear();
Console.Write(i);
}
}

在大约达到 2GB 的内存使用量(任何 CPU)或消耗我机器的所有物理内存(x64)(16GB)之后,上述内容会引发内存不足异常。

如果我删除 cache.Add 位,程序不会抛出任何异常。如果我在每次添加缓存后都调用 cache.Trim(5),我会看到它释放了一些内存,并且在任何给定时间(来自 cache.GetCount())在缓存中保留了大约 150 个对象。

调用 cache.Trim 是我的程序的责任吗?如果是这样,什么时候应该调用它(比如我的程序如何知道内存已满)?你如何计算百分比参数?

注意:我计划在长时间运行的 Windows 服务中使用 MemoryCache,因此对其进行适当的内存管理至关重要。

最佳答案

MemoryCache 有一个后台线程,它会定期估计进程使用了​​多少内存以及缓存中有多少键。当它认为您正在接近 cachememorylimit 时,它将修剪缓存。每次此后台线程运行时,它都会检查您与限制的接近程度,并且会在内存压力下增加轮询频率。

如果您非常快速地添加项目,后台线程将没有机会运行,并且您可能会在缓存可以修剪和 GC 运行之前耗尽内存(在 x64 进程中,这可能导致大量堆大小和多分钟GC 暂停)。修剪过程/内存估计也已知具有 bugs under some conditions .

如果您的程序由于快速加载过多的对象而容易出现内存不足的情况,那么像 LRU 缓存这样具有有限大小的东西是一个更好的策略。 LRU 通常使用基于项目计数的策略来驱逐最近最少使用的项目。

我编写了 TLRU(一种时间感知最近最少使用策略)的线程安全实现,您可以轻松地将其用作 ConcurrentDictionary 的替代品。

它可以在 Github 上找到:https://github.com/bitfaster/BitFaster.Caching

Install-Package BitFaster.Caching

对您的程序使用它看起来像这样,并且它不会耗尽内存(取决于您的文件有多大):
 class Program
{
static void Main(string[] args)
{
int capacity = 80;
TimeSpan timeToLive = TimeSpan.FromMinutes(5);
var lru = new ConcurrentTLru<int, byte[]>(capacity, timeToLive);

for (int i = 0; i < 100000; i++)
{
var value = lru.GetOrAdd(1, (k) => System.IO.File.ReadAllBytes("File.txt"));
}


Console.ReadLine();
}
}

如果你真的想避免内存不足,你还应该考虑将文件读入 RecyclableMemoryStream ,并使用 BitFaster 中的 Scoped 类使缓存值线程安全并避免处理时发生竞争。

关于c# - MemoryCache OutOfMemoryException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23969334/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com