简体   繁体   English

将对象添加到大对象堆中

[英]Objects added to the Large Object Heap

I'm trying to debug the reason for high CPU usage in our legacy website, and from looking at some analysis in DebugDiag, I suspect that the amount of objects on the LOH, and subsequent GC collections, could be a reason. 我正在尝试调试旧版网站中CPU使用率高的原因,并且从DebugDiag中的一些分析来看,我怀疑LOH上的对象数量以及随后的GC收集可能是原因。 In one .dbg file we have ~3.5gb on the LOH with the majority of those objects being strings. 在一个.dbg文件中,LOH上有〜3.5gb,其中大多数对象是字符串。

I'm aware that for objects to go on the LOH, they must be over 85000 bytes. 我知道要使对象在LOH上运行,它们必须超过85000个字节。

What I'm not sure of is if this refers to, for example, a single array. 我不确定的是例如是否指向单个数组。 Or can it refer to a large object graph? 还是可以引用大型对象图?

What I mean by that is if I have object Foo, that contains n other objects, each containing n objects themselves. 我的意思是,如果我有对象Foo,它包含n个其他对象,每个对象本身包含n个对象。 With each of these objects containing strings, and the total size of Foo (and all child objects) being greater than 85000 bytes would Foo be placed on the LOH? 如果这些对象中的每个对象都包含字符串,并且Foo(以及所有子对象)的总大小大于85000字节,那么Foo会放在LOH上吗? Or, if somewhere in the Foo object graph there was a single array greater than 85000 bytes would it just be that array that got placed on the LOH? 或者,如果在Foo对象图中某处有一个大于85000字节的数组,那仅仅是放在LOH上的那个数组吗?

Thanks. 谢谢。

You are right that if array is larger than 85000 then it will be consider as LOH not entire object. 没错,如果数组大于85000,那么它将被视为LOH而不是整个对象。 To explain this here I created example. 为了解释这一点,我创建了示例。

   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);
            }
        }
    }

Here if you notice that string data. 在这里,如果您注意到该字符串数据。 It is also consider as LOH because string is character array. 由于字符串是字符数组,因此也被视为LOH。 Items2 is not LOH and Items is LOH but actual object o is not LOH. Items2不是LOH,Items是LOH,但实际对象o不是LOH。

Only individual objects greater than 85,000 bytes go into the LOH. 仅大于85,000字节的单个对象进入LOH。 An object graph can total more than that but not be in the LOH so long as no individual object crosses the limit. 只要没有单个对象超过限制,一个对象图的总数就可以超过该总数,但不能在LOH中。 Byte arrays and strings are the most typical culprits. 字节数组和字符串是最典型的元凶。

I agree with @daspek and @dotnetstep. 我同意@daspek和@dotnetstep。

For instance in @dotnetstep's example, o should have a size of 12bytes on a 32bit machine and 24bytes on a 64bit machine. 例如,在@dotnetstep的示例中,o在32位计算机上的大小应为12字节,在64位计算机上的大小应为24字节。

All the fields defined in the Obj class are reference types and so all Obj stores are pointers to the heap locations where its child elements (in this case arrays) are created. Obj类中定义的所有字段都是引用类型,因此所有Obj存储都是指向创建其子元素(在本例中为数组)的堆位置的指针。

Now each of these objects are arrays (string being an array of char[]) so they can get placed on the LOH if they exceed the limit of 85000bytes. 现在,每个对象都是数组(字符串是char []的数组),因此如果它们超过85000bytes的限制,则可以将它们放在LOH中。

The only way a regular object can get placed on the LOH everytime it is created is if it has 21251 or more fields on a 32 bit machine and 10626 or more fields on a 64 bit machine if all the fields are REFERENCE types. 常规对象每次创建时都只能放在LOH上的唯一方法是,如果所有字段都是REFERENCE类型,则它在32位计算机上具有21251个或更多字段,而在64位计算机上具有10626个或更多字段。 For all intents and purposes, that is not usually a practical kind of class create; 出于所有目的和目的,通常不是一种实用的类创建方法。 it will be extremely rare to come across such a class. 碰到这样的一类人将非常罕见。

In an instance where the contained fields are structs, they are considered to be part of the class's definition. 在其中包含的字段是结构的实例中,它们被视为类定义的一部分。 So rather than hold a 4byte heap address, the contents of the struct are part of the class's layout - a good number of fields with large structs may not quickly get one to the limit of 85000bytes but it can still be breached. 因此,结构的内容不是保留4字节的堆地址,而是类的布局的一部分-大量具有大结构的字段可能不会很快就达到85000字节的限制,但仍然可以被破坏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM