.Net 4 内存缓存与并发垃圾回收泄露情况
.Net 4 内存缓存与并发垃圾回收泄露情况
我在.Net 4中使用新的MemoryCache,设置了最大缓存大小限制(我在内存为1.75GB至8GB的系统上测试了10至200MB之间的设置)。我没有设置任何基于时间的对象过期,因为我只是将缓存用作高性能驱动器,只要有空间,我就希望使用它。令我惊讶的是,缓存拒绝清除任何对象,以至于我会收到SystemOutOfMemory异常。
我启动了perfmon,将我的应用程序连接到.Net CLR Memory\#Bytes In All Heaps、.Net Memory Cache 4.0和Process\Private Bytes,确实,内存消耗失控,并且没有注册任何缓存修剪。
我进行了一些谷歌搜索和stackoverflow,下载并连接了CLRProfiler,然后:到处都是驱逐!内存保持在我设置的合理范围内。再次以调试模式运行,没有驱逐。再次运行CLRProfiler,有驱逐。
我最后注意到,分析器强制应用程序在没有并发垃圾回收的情况下运行(也可以参见有用的SO Concurrent Garbage Collection问题)。我在我的app.config中关闭了它,果然,有驱逐!
这似乎是至少缺乏文档的荒谬之处,没有说:这只适用于非并发垃圾回收 - 虽然我认为由于它是从ASP.NET移植过来,他们可能不必担心并发垃圾回收。
那么,还有其他人遇到过这个问题吗?我很想了解其他人的经验,也许还有一些更有见地的见解。
更新1
我在一个方法中复现了这个问题:似乎只有在并发垃圾回收模式下,缓存必须并行写入才不会触发缓存驱逐。如果有兴趣,我会将测试代码上传到公共仓库。我肯定是在深入研究CLR/GC/MemoryCache领域,我想我忘记带上我的浮板了...
更新2
我在CodePlex上发布了测试代码来复现这个问题。此外,可能有趣的是,原始的生产代码在Azure中作为Worker Role运行。有趣的是,在角色的app.config中更改GC并发设置没有效果。可能Azure会像ASP.NET一样覆盖GC设置?此外,将测试代码运行在WPF和控制台应用程序下会产生稍微不同的驱逐结果。