Dav*_*vre 37 .net c# caching garbage-collection
我正在使用.Net 4中的新MemoryCache,最大缓存大小限制为MB(我测试它设置在10到200MB之间,系统内存介于1.75和8GB之间).我没有在对象上设置任何基于时间的过期,因为我将缓存简单地用作高性能驱动器,并且只要有空间,我希望它被使用. 令我惊讶的是,缓存拒绝驱逐任何对象,以至于我会得到SystemOutOfMemory例外.
我启动了perfmon,将我的应用程序连接到.Net CLR Memory\#Bytes In All Heaps,.Net Memory Cache 4.0并且Process\Private Bytes- 实际上,内存消耗已经失控,并且没有注册缓存修剪.
做了一些google搜索和stackoverflowing,下载并附着在CLRProfiler,和威猛:驱逐无处不在!根据我设置的内存大小限制,内存保持在合理的范围内.再次调试模式,没有驱逐.CLRProfiler再次驱逐.
我终于注意到,探查器强制应用程序在没有并发垃圾收集的情况下运行(另请参阅有用的SO并发垃圾收集问题).我在我的app.config中将其关闭了,果然,驱逐!
这似乎充满了令人遗憾的缺乏文档而不说:这只适用于非并发垃圾收集 - 虽然我从ASP.NET移植后映像,但他们可能不必担心并发垃圾收集.
那么有其他人看过这个吗?我希望得到一些其他经验,也许还有一些更有教育意义的见解.
更新1
我在一个方法中重现了这个问题:似乎必须并行写入缓存,以便缓存驱逐不被触发(在并发垃圾收集模式下).如果有兴趣,我会将测试代码上传到公共回购.我肯定会走向CLR/GC/MemoryCache池的深层,我想我忘了我的漂浮物......
更新2
我在CodePlex上发布了测试代码以重现该问题.此外,可能感兴趣的是,原始生产代码在Azure中作为工作者角色运行.有趣的是,在角色的app.config中更改GC并发设置无效.Azure可能会像ASP.NET一样覆盖GC设置吗?此外,在WPF和控制台应用程序下运行测试代码将产生略微不同的驱逐结果.
您可以在有问题的方法之后立即"强制"垃圾收集,并查看问题是否重现执行:
System.Threading.Thread.Sleep(200);
GC.Collect();
GC.WaitForPendingFinalizers();
Run Code Online (Sandbox Code Playgroud)
就在方法的最后(确保你释放任何句柄来引用对象并将它们清空).如果这可以防止内存泄漏,然后是,则可能存在运行时错误.
| 归档时间: |
|
| 查看次数: |
9904 次 |
| 最近记录: |