gpt4 book ai didi

.net - 在 .NET 中,您可以设置对象的 GC 生成,或者以其他方式指示它即将超出范围吗?

转载 作者:行者123 更新时间:2023-12-01 01:46:30 24 4
gpt4 key购买 nike

.NET 的垃圾收集器是分代垃圾收集器,基于大多数分配的对象都是短暂的这一理念。因此,对象从“第 0 代”开始,在那里它们可以很容易地被收集(而且通常是),并且生命周期更长的对象被提升到“第 1 代”和“第 2 代”,在那里它们被更全面的扫描所触及。当方法分配一个对象作为其状态的一部分时,通常会创建第 0 代对象,然后在退出时让该对象超出范围。

但是,有时那些将对象分配为状态的方法会运行很长时间。也许它们会阻塞 I/O 调用,或者使用一堆线程来托管合并排序或数据库查询。在此期间发生的垃圾收集会在方法执行期间将这些状态对象提升到第 1 代和第 2 代。虽然这很适合让它们远离快速垃圾收集扫描,但一旦这个长时间运行的方法结束,我就不再需要这些状态对象,并且不再有任何被调用者持有对它们的任何引用。

在这一点上,能够将此告诉垃圾收集器会很好。这么说吧,是的,这个对象已经存在了很长时间,但是很快就可以被丢弃,垃圾收集器可以通过将对象移动到 gen 0 堆来响应。然后,下次需要执行垃圾收集时(例如下次调用此长时间运行的方法时),可以通过更快的 gen 0 扫描而不是完整的阻塞扫描来回收必要的内存,从而减少垃圾收集器对性能影响的不可预测性。

一些其他信息:

  • 现在,我的团队通过将这些“本地状态”对象存储在通过 refin 参数传递的巨型可变结构中来缓解不可预测的性能问题。据我了解,.NET 框架对于超出一些字节数的任何结构(官方消息来源说 16,虽然我听说过 24)以及可变结构的优化很差,但我不能否认这样一个事实这些结构具有自 Action 用域,并且在方法返回时肯定会被释放——当然,除非我们可以向 GC 发出一个类即将退出的信号。
  • 如果这是建议 API 而不是命令,我会非常高兴,因为最终 GC 必须做它必须做的事情。也许如果事实证明对象在某处仍然有引用,最终会出现某种性能损失。
  • 我也乐于回答有关 .NET 以外的垃圾收集框架中存在的此工具的问题。

最佳答案

您的问题的简单答案是 - 不,没有这样的 API。大多数现代 GC 的设计都考虑了大多数对象早逝或长寿的“世代假设”。您所描述的通常被称为“中年危机” - 对象的生命周期足以提升到最老一代,但很快就不再需要了。对于当前的 GC,这显然不是最佳选择。避免它的一种常见方法是:减少分配(更少的晋升机会,因此我们经常停留在“英年早逝”部分)或重用对象(因此我们落入“长寿”部分)。

通过大量重用结构和引用,您已经采用了第一种方法。你也可以考虑通过池来重用对象,比如 ArrayPool<T>或其他人。

关于问题,您提出 API 用于:

"the garbage collector can respond by moving the object to the gen 0 heap"

虽然涉及到很多可能的实现细节,但要高效实现,难度可想而知。许多 GC,包括 .NET GC,都尽量不复制/移动内存。世代只是逻辑内存区域,边界来回移动。因此,“将对象移动到 gen0”将需要复制它(可能还需要复制它的所有保留图,以使其变得合理),这将带来比潜在 yield 大得多的开销。更糟糕的是,目前它只能在 GC 期间完成,因为我们没有实现并发压缩(通常,在使用对象时移动它们)。

"As I understand it, the .NET framework is poorly optimized for any structs beyond some small number of bytes (official sources say 16, though I've heard 24) as well as mutable structs"

好像有点假。 .NET 运行时对结构的使用进行了很大的优化,如果你通过 ref 传递它们,这是我能想到的最有效的方法之一。只知道 defensive-copying pitfall使用 in 时可能遇到的问题参数。

关于.net - 在 .NET 中,您可以设置对象的 GC 生成,或者以其他方式指示它即将超出范围吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54954287/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com