我怎么知道在.NET中的大对象堆(LOH)中分配了一组结构?

时间:2010-05-06 00:26:32

标签: .net arrays large-object-heap

在使用CLR Profiler进行一些实验后,我发现:

Node[,] n = new Node[100,23]; //'84,028 bytes, is not placed in LOH
Node[,] n = new Node[100,24]; //'86,428 bytes, is 

    public struct Node {
        public int Value;
        public Point Point;
        public Color Color;
        public bool Handled;
        public Object Tag;
    }

在运行期间,我如何知道在大对象堆(LOH)中分配了一组结构(或任何数组)?

3 个答案:

答案 0 :(得分:2)

任何大于85,000字节的对象都将存储在LOH上。这是一篇关于.Net Memory Management的精彩博文。

答案 1 :(得分:1)

从您的评论中,我认为您实际上并不需要知道该对象是否会继续使用LOH。当你输入一个“太大”的值时,当你真正想做的就是向用户显示警告时,这是否是你应用程序减速的实际原因是无关紧要的。

所以我建议稍微简单一些:只需使用一些试错法来确定截止值。如果他们输入的尺寸超过了试错值,则显示警告。

至于你的实际性能问题,你可以简单地分配一堆“较小的”一维数组,而不是分配一个大的二维数组。而不是:

Node[,] n = new Node[100,100]; // this will go the LOH

你这样做:

Node[][] n = new Node[100][];
for(int i = 0; i < n.Length; i++) {
    n[i] = new Node[100];  // none of these will be on the LOH
}

你总共拥有相同数量的节点,但LOH上什么都没有。就个人而言,我认为你可能会发现性能实际上并没有那么大的不同,但是尝试一下也许是值得的。

答案 2 :(得分:1)

您可以在分配后立即找到。使用GC.GetGeneration(object)重载来获取对象所在的世代号。对于LOH,这将是2.

Node[,] n = new Node[100,23]; 
// GC.GetGeneration(n) should give 0
Node[,] n = new Node[100,24]; 
// GC.GetGeneration(n) should give 2

注意,这有一些限制,对于生产代码来说绝不是一种正确的方法,我假设:如果您稍后查询该数字,该对象可能已经从Gen 0移动到Gen 2。我不知道要区分Gen2(小对象)堆和LOH。此外,对于我测试的所有.NET版本,LOH上的对象返回的数字是2。但我在实际规范中找不到这个,所以它也可能是一个变化的问题。