以编程方式确定大对象堆的限制

Posted

技术标签:

【中文标题】以编程方式确定大对象堆的限制【英文标题】:Determine limit for large object heap programmatically 【发布时间】:2011-01-27 09:11:17 【问题描述】:

既然建议对大对象使用 IDisposal 模式,我想知道,为什么似乎没有可靠的方法来确定一个对象被认为是“大”的限制?

在内部存在这样的区别:在 LOH 上分配的对象的下限。每当它以 85k 的形式公开传达时,就会同时阻止一个人依赖该数字。

特别是对于处理大量“更大”数组的应用程序,为了实现正确的内存管理和防止 LOH 碎片,必须需要该限制。另一方面,对于“较小”的数组,从内存消耗的角度来看,IDisposal 没有意义。在这里,compacting GC 做得更好。

为什么没有

GC.GetLOHLimit() 

甚至更好:

bool GC.ArrayTargetForManualDisposal(Type type, int length); 

编辑:我知道,IDisposable 模式只是建议正确处理特殊对象(例如“大”或非托管对象)。我的问题不是假设,运行时会对这些对象进行任何特殊处理。我宁愿要求对模式的实现者(也可能是其他人)提供运行时支持,以了解对象何时应该遵循特殊的内存管理。

【问题讨论】:

@user492238 关于您的编辑:同样,IDisposable 与托管内存管理无关。您能否提供一个推荐使用IDisposable 来管理托管内存的参考。 IDisposable 是确保 确保 对象将在许多资源推荐的池中释放的最佳方法。但这个问题并不依赖于 IDisposable。而是问,如果一个对象完全需要特殊处理,为什么没有办法在运行时获得提示。是否会在 IDisposable 内部完成这一点在这里不太重要。 双精度数组的限制不同 对。我们必须向查询函数提供数组的类型。 @user492238 如果您想回复其他用户的cmets,请附上他们的@username,否则他们将不会收到通知。 【参考方案1】:

IDisposable 与托管内存管理无关。对象的处理是一种用户约定\模式,它不被运行时内部使用,并且对内存管理没有影响。运行时不知道IDisposableIDisposable 的唯一特殊处理\识别是与 using 关键字一起使用时,但编译器(至少 C# 编译器)可以识别,而不是运行时。

对于 LOH,LOH 算法没有公开保证 - 这就是为什么首先没有 API 可以获取最大对象大小等参数。在未来版本的 CLR 中,考虑 LOH 的对象大小确实可以是动态的,这是完全可行的。 CLR 设计者不希望用户将自己与内存管理的内部细节联系起来,因为这会使他们更难或不可能在不破坏大量现有程序的情况下对其进行更改。

如果您关心 CLR 内存管理,我首先建议您了解 IDisposable 不参与其中的事实。

【讨论】:

“在未来版本的 CLR 中,考虑 LOH 的对象大小确实可以是动态的” - 因为,我会假设运行时会提供任何关于它。 @user492238 你知道一些关于 LOH 管理的事情,但是这些都没有被 API 冒泡,这只是 CLR 设计者不希望用户直接依赖特定的实现细节的产物。这在实践中是一个很好的软件设计,因为它们封装了一个非常关于优化的设计方面。如果他们允许你将自己与它的各个方面结合起来,就会阻止他们完全改变它。 @user492238 否决票不会赢得您的任何尊重。恕我直言,我正在回复您的 cmets 和问题。 @chibacity:我同意。如果它是完美的设计,用户将不需要了解任何内部结构。事实上,设计师们自己也建议对特殊情况进行特殊处理(没有给出具体细节)。 GC.GetGeneration、GC.Collect 只是有关内存管理的一些示例。从某种角度来看,托管堆是艺术。因为它(当然)不能处理所有情况,所以实现者必须有时跟踪特殊情况——其中之一是内存碎片。 @user492238 但是你确实知道内部的事情,他们只是没有通过将它们冒泡到 API 来给你任何关于它们的保证。他们不想在这个领域进行耦合。【参考方案2】:

正如 chibacity 所说,IDisposable 与 LOH 管理无关。这是一篇关于 LOH 的好文章:Large Object Heap Uncovered。

话虽如此,据我所知,没有任何公共 API 可以确定 LOH 大小。您可以在 SSCLI "rotor" 中找到对 85000 字节限制的引用(来源:Shared Source Common Language Infrastructure 2.0 Release Download):

在 clr/src/vm/gc.h:

#define LARGE_OBJECT_SIZE   85000

虽然这个源是 CLR 2.0 等效源,而不是 CLR 4,但我认为他们没有改变这一点,因为它肯定会对现有代码产生深远的影响。

所以如果你想用这个值做一些聪明的事情,你可能可以把它安全地放在一个常量中,或者让它可配置,但它肯定不会在运行过程中动态改变。

【讨论】:

@Simon LOH 算法没有公开保证 - 这就是为什么首先没有 API 可以获取最大对象大小等参数。在未来版本的 CLR 中,考虑 LOH 的对象大小确实可以是动态的,这是完全可行的。 @chibacity - 我不认为我说了什么不同的东西。 LOH也有可能消失。谁能预测未来? 因为没有全面的保证,所以用户应该有机会找出运行时的当前值,对吧? @Simon 我完全同意 - CLR 版本之间肯定会发生变化。 LOH 可能会完全消失。 OP 对IDisposable 有一些误解,但在我们谈到 LOH 之类的事情之前。 “IDisposable 与 LOH 管理无关”这不是真的。即使您链接的文章也建议对大型对象进行池化。可池对象最自然的实现是:IDisposable。

以上是关于以编程方式确定大对象堆的限制的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式确定 YouTube 视频是不是有年龄限制?

以编程方式填充分配给对象的属性集定义中的数据

在 Objective-C Xcode 5 中以编程方式创建视图

webpack究竟是什么

以编程方式确定 SQL Server Compact sdf 文件的大小

如何以编程方式确定从主功能区创建的 Outlook 新项目 --> 新项目