添加到大对象堆的对象

时间:2014-12-09 06:31:21

标签: c# large-object-heap

我试图在我们的旧网站中调试高CPU使用率的原因,并且通过查看DebugDiag中的一些分析,我怀疑LOH上的对象数量以及随后的GC集合可能是原因。在一个.dbg文件中,我们在LOH上有大约3.5gb,其中大部分是对象。

我知道对于LOH上的对象,它们必须超过85000字节。

我不确定的是,这是否指的是,例如,单个阵列。或者它可以引用一个大对象图?

我的意思是,如果我有对象Foo,它包含n个其他对象,每个对象本身包含n个对象。如果这些对象中的每一个都包含字符串,并且Foo(和所有子对象)的总大小大于85000字节,那么Foo会被放置在LOH上吗?或者,如果Foo对象图中的某个地方有一个大于85000字节的单个数组,那么它就是放在LOH上的那个数组吗?

感谢。

3 个答案:

答案 0 :(得分:4)

你是对的,如果数组大于85000,那么它将被视为LOH而不是整个对象。为了解释这个,我创建了一个例子。

   class Program
    {
        static void Main(string[] args)
        {
            Obj o = new Obj();
            o.Allocate(85000);
            Console.WriteLine(System.GC.GetGeneration(o));
            Console.WriteLine(System.GC.GetGeneration(o.items));
            Console.WriteLine(System.GC.GetGeneration(o.items2));
            Console.WriteLine(System.GC.GetGeneration(o.Data));
            Console.ReadLine();           
        }

        class Obj
        {
            public byte[] items = null;

            public byte[] items2 = null;

            public string Data = string.Empty;

            public void Allocate(int i)
            {
                items = new byte[i];
                items2 = new byte[10];
                Data = System.Text.Encoding.UTF8.GetString(items);
            }
        }
    }

此处如果您注意到字符串数据。它也被认为是LOH,因为字符串是字符数组。 Items2不是LOH,Items是LOH,但实际对象o不是LOH。

答案 1 :(得分:1)

只有大于85,000字节的单个对象进入LOH。只要没有单个对象超过限制,对象图可以总数多于但不在LOH中。字节数组和字符串是最典型的罪魁祸首。

答案 2 :(得分:0)

我同意@daspek和@dotnetstep。

例如在@ dotnetstep的例子中,o在32位机器上的大小应为12bytes,在64位机器上的大小应为24bytes。

Obj类中定义的所有字段都是引用类型,因此所有Obj存储都是指向其子元素(在本例中为数组)的堆位置的指针。

现在这些对象中的每一个都是数组(字符串是char []数组),因此如果它们超过85000字节的限制,它们就可以放在LOH上。

常规对象每次创建时都可以放置在LOH上的唯一方法是,如果所有字段都是,则32位计算机上有21251个或更多字段,64位计算机上有10626个或更多字段 REFERENCE 类型。对于所有意图和目的,这通常不是一种实用的类创建;碰到这样一个班级是非常罕见的。

在包含的字段是结构的实例中,它们被认为是类定义的一部分。因此,结构的内容不是保存4字节堆地址,而是类的布局的一部分 - 大量结构的字段可能不会很快达到85000字节的限制,但它仍然可以被破坏。