我试图在我们的旧网站中调试高CPU使用率的原因,并且通过查看DebugDiag中的一些分析,我怀疑LOH上的对象数量以及随后的GC集合可能是原因。在一个.dbg文件中,我们在LOH上有大约3.5gb,其中大部分是对象。
我知道对于LOH上的对象,它们必须超过85000字节。
我不确定的是,这是否指的是,例如,单个阵列。或者它可以引用一个大对象图?
我的意思是,如果我有对象Foo,它包含n个其他对象,每个对象本身包含n个对象。如果这些对象中的每一个都包含字符串,并且Foo(和所有子对象)的总大小大于85000字节,那么Foo会被放置在LOH上吗?或者,如果Foo对象图中的某个地方有一个大于85000字节的单个数组,那么它就是放在LOH上的那个数组吗?
感谢。
答案 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字节的限制,但它仍然可以被破坏。