Gen2集合并不总是收集死对象?

 烦恼的天伦之乐_456 发布于 2023-02-11 20:16

通过CLR #Bytes in all Heaps在过去几天监视全新.NET 4.5服务器应用程序的性能计数器,我可以注意到一种模式让我认为Gen2集合并不总是收集死对象,但我无法理解究竟发生了什么.

服务器应用程序使用Server GC/Background.NET Framework 4.5.1中运行.

这是一个托管为Windows服务的控制台应用程序(在Topshelf框架的帮助下)

服务器应用程序正在处理消息,并且吞吐量在某种程度上是不变的.

我可以看到的图表CLR #Bytes in all Heaps是内存开始大约为18MB,然后在大约20-24小时内增长到35MB(在此时间范围内有20-30个Gen2集合),然后突然回到名义价值为18MB,然后在20-24小时内再次增长到~35MB,然后又回落到18MB,等等(我可以看到应用程序现在正在运行的过去6天重复的模式)...内存不是线性的,大约需要5个小时才能增长10MB,然后剩下的10 MB大约需要15-17个小时.

事情就是我可以通过查看perfmon计数器看到#Gen0/#Gen1/#Gen2 collections一堆Gen2集合在20-24小时内(可能是30周年)正在进行,并且没有一个使内存回落到标称18MB.然而,奇怪的是通过使用外部工具强制GC(在我的情况下为Perfview),然后我可以看到#Induced GC上升1(GC.Collect被调用,所以这是正常的)并且内存立即回到标称值18MB.

这让我想到#Gen2系列的perfmon计数器不对,只有一个Gen2系列在20-22小时后发生(meeehhh我真的不这么认为)或者Gen2系列并不总是收集死亡对象(看起来似乎更合理)......但在这种情况下,为什么会通过GC.Collect强制GC执行操作,在应用程序的生命周期中明确调用GC.Collect与自动触发的集合之间的区别是什么.

我确信有一个非常好的解释但是从我发现的关于GC的文档的不同来源很少:( - Gen2集合在任何情况下都会收集死对象.所以也许文档不是最新的或者我读错了...欢迎任何解释.谢谢!

编辑:#Bytes in all heaps在4天内查看该图表的屏幕截图

(点击查看大图)
图形

这比试图描绘你头脑中的东西更容易.您在图表上看到的就是我上面所说的...内存增加超过20-24小时(以及在此时间范围内20-30 Gen2集合),直到达到~35MB然后突然下降.您将在图表的末尾注意到,通过外部工具触发的诱导GC I会立即将内存降回到标称值.

编辑#2:我在代码中做了很多清理,主要是关于终结器.我有很多关于一次性类型的类,所以我必须IDisposable在这些类型上实现.然而,在任何情况下,我都被一些文章误导为使用Finalizer实现Diposable模式.在阅读了一些MSDN文档之后,我开始明白只有当类型本身拥有本机资源时才需要终结器(在这种情况下,使用SafeHandle可以避免这种情况).所以我从所有这些类型中删除了所有终结器.代码中还有一些其他的修改,但主要是业务逻辑,没有".NET框架"相关.现在图表非常不同,这是一个平坦的线路,现在已经持续了20天......正是我期待看到的!所以这个问题现在已经解决了,但是我仍然不知道是什么问题导致......似乎它可能与终结器有关,但仍然无法解释我注意到的内容,即使我们没有调用Dispose (true) - 压缩终结器 - 终结器线程应该在收集之间启动而不是每20-24小时?考虑到我们现在已经摆脱了问题,需要时间回到"越野车"版本并再次重现它.我可能会尝试做一段时间,然后深究它.

编辑:添加了Gen2集合图(点击查看大图)

图形

撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有