.NET:典型的垃圾收集器开销是多少?

11

执行时间中有5%花费在垃圾回收上?10%?25%?

谢谢。


10
我不懂.NET,但我确定答案是:取决于情况! :) - sfussenegger
1
如果您担心 .net 性能,那么垃圾回收器不应该是您最担心的问题。如果您编写算法代码(信号处理、压缩),当将 C++ 算法移植到 .net 时,您可以预计会出现显着的减速。在我所见过的示例中,它很容易比原来慢两倍以上。如果您不是这种情况,所有 .net 开销与您等待磁盘访问或在非托管库中花费的时间相比都微不足道。 - user180326
6个回答

3

这完全取决于应用程序。垃圾回收是按需执行的,因此您分配大量内存并且这些内存后来变成垃圾的次数越多,它就必须运行得越频繁。

如果您预先分配了所有内容并且从未分配任何新对象,甚至可以降至0%。

在典型的应用程序中,我认为花费在垃圾回收器上的时间非常接近0%。


我知道这很大程度上取决于内存使用情况,但也许有一些典型的开销期望吗? - Vladimir Doloto
5
一个典型的期望是根本不需要关心。 - sfussenegger

3

这篇博客文章对此领域进行了有趣的调查。

那么,作者的结论是什么呢?他的例子中开销微不足道。

因此,在真正的程序中,即使在紧密循环中,GC堆的速度也是如此之快,以至于您可以毫不犹豫地使用闭包和委托(甚至不需要思考几个纳秒)。与往常一样,先从一个干净、安全的设计开始工作,然后通过剖析找出开销所在。


他的结论非常清晰。他最后的建议是编写干净、安全的代码,然后进行分析以找出问题,这可能是最好的建议。要了解实际开销,请添加一些测试和内存分析。然后你就会确定。 - Tim C
我认为这篇博客文章有点误导人。作者正在运行单线程测试,并使用简单的开始和结束时间差来“测量”GC开销。实际上,他正在测量lambda的开销,而GC将在不同的线程中运行。(至少我希望它是这样做的。有人能确认或反驳吗?) - sfussenegger
@sfussenegger,就我所记得的,我在一个虚拟机上运行了测试,该虚拟机配置为使用物理机器的单个核心。无论如何,如果在多个核心上表现得更好,那么这是支持GC优于手动内存管理的又一个论据。 - Daniel Earwicker

2
开销差异很大。将问题域缩小为“典型场景”并不实际,因为GC(和相关功能,例如终结)的开销取决于几个因素:
  • 应用程序使用的GC方式(影响GC期间线程可能被阻塞的方式)。
  • 您的分配情况,包括分配频率(当分配请求需要更多内存时,GC会自动触发)和对象的生命周期分布(代0收集最快,代2收集较慢,如果您引导了很多代2收集,则开销会增加)。
  • 可终结对象的生命周期分布,因为它们必须在其终结器完成后才能成为可回收对象。
各个轴对每个相关领域的影响可以进行分析(我可能没有从头脑中回想出所有相关领域) - 因此问题实际上是“如何将这些相关性轴缩减为一个‘常见情况’?”
基本上,正如其他人所说,这取决于情况。或者说,“低到足以让您不必担心,直到它出现在分析器报告中。”

1
在本地的C/C++中,有时会存在分配内存的巨大成本,因为需要找到一个正确大小的空闲内存块,释放内存也有一定的成本,因为必须将释放的内存链接到正确的块列表中,并将小块合并成大块。
在.NET中,分配新对象非常快,但是当垃圾回收器运行时,您需要付出代价。然而,对于短生命周期对象来说,垃圾回收的成本几乎可以忽略不计。
我始终认为,如果垃圾回收的成本对您造成了问题,那么您可能会在软件设计方面遇到更大的问题。如果您没有足够的物理内存,分页可能是任何GC的重大问题,因此您可能无法将所有数据都放入RAM中,并依赖于操作系统根据需要提供虚拟内存。

0

是的,垃圾回收器会在所有应用程序中平均花费一定比例的时间进行垃圾收集。但这并不一定意味着这些时间是额外开销。

对于额外开销,你只能计算在非托管平台上释放相同数量内存后剩余的时间。

考虑到这一点,实际的额外开销是负数的,因为垃圾回收器会以批量释放多个内存块的方式来节省时间。这意味着较少的上下文切换和整体效率的提升。

此外,从.NET 4开始,垃圾回收器会在一个不太打断当前运行代码的不同线程上进行大部分工作。随着我们越来越多地使用多核机器,其中某个核心可能会偶尔空闲,这是一个重要的改进。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接