短命的物体

时间:2009-03-10 19:33:33

标签: c# .net memory-management garbage-collection

生成大量临时对象(即临时结果)的开销是什么“年轻”(在垃圾收集间隔期间从未升级到下一代)?我假设“新”操作非常便宜,因为它实际上只是一个指针增量。但是,处理这个临时“垃圾”的隐性成本是多少?

6 个答案:

答案 0 :(得分:13)

不是很多 - 垃圾收集器对于gen0非常快。它也会调整自己,调整gen0的大小,具体取决于它每次运行时收集的数量。 (如果它设法收集很多,它会减少gen0的大小,以便下次收集,反之亦然。)

最终的测试是您的应用程序的执行方式。 Perfmon在这里非常方便,显示了在GC上花了多少时间,每一代有多少集合等。

答案 1 :(得分:4)

正如你所说,分配本身非常便宜。生成大量短期对象的成本是更频繁的垃圾收集,因为它们在第0代预算耗尽时被触发。但是,第0代集合相当便宜,因此只要您的对象确实很短暂,开销很可能并不重要。

另一方面,在循环中连接大量字符串的常见示例显着地推动了垃圾收集器,因此这一切都取决于您创建的对象的数量。考虑分配并没有什么坏处。

垃圾收集的成本是在压缩过程中托管线程被挂起。

答案 2 :(得分:2)

一般来说,这不是你应该担心的事情,听起来它开始非常接近“微优化”。 GC的设计假设“调整良好的应用程序”将在Gen0中拥有所有的分配 - 这意味着它们都“年轻”。每次分配新对象时,它始终在Gen0中。在Gen0阈值通过且Gen0中没有足够的可用空间来保存下一个分配之前,不会发生集合。

“新”操作实际上是一堆东西:

  1. 分配内存
  2. 运行类型构造函数
  3. 返回指向内存的指针
  4. 递增下一个对象指针

答案 3 :(得分:1)

虽然新操作是有效设计和编写的,但它并不是免费的,并且需要时间来分配新内存。内存分配库需要跟踪哪些块可用于分配,并且新分配的内存为零。

创建许多年轻的对象也会更频繁地触发垃圾收集,并且操作可能很昂贵。特别是“停止世界”的垃圾收集者。

以下是MSDN上有关其工作原理的文章: http://msdn.microsoft.com/en-us/magazine/bb985011.aspx

注意:它描述了调用垃圾收集是如何昂贵的,因为它需要在开始垃圾收集之前构建对象图。

答案 4 :(得分:0)

如果这些对象永远不会从第0代升级,那么你会看到相当不错的表现。我能看到的唯一隐藏成本是,如果你超过你的第0代预算,你将强制GC压缩堆,但GC会自我调整,所以这不是一个问题。

答案 5 :(得分:0)

垃圾收集在.Net中是分代的。短命的物体将首先和经常收集。 Gen 0系列很便宜,但根据您创建的对象数量的大小,它可能会非常昂贵。我会运行一个分析器来查看它是否会影响性能。如果是,请考虑将它们切换为结构。这些不需要收集。