C# 添加到大型对象堆的对象

C# 添加到大型对象堆的对象,c#,large-object-heap,C#,Large Object Heap,我正在尝试调试旧式网站中CPU使用率高的原因,通过查看DebugDiag中的一些分析,我怀疑LOH上的对象数量以及后续GC集合可能是一个原因。在一个.dbg文件中,我们在LOH上有~3.5gb,其中大多数对象是字符串 我知道对于LOH上的对象,它们必须超过85000字节 我不确定的是,这是否指一个数组。或者它可以引用大型对象图 我的意思是,如果我有对象Foo,它包含n个其他对象,每个对象本身包含n个对象。如果这些对象中的每一个都包含字符串,并且Foo(和所有子对象)的总大小大于85000字节,那

我正在尝试调试旧式网站中CPU使用率高的原因,通过查看DebugDiag中的一些分析,我怀疑LOH上的对象数量以及后续GC集合可能是一个原因。在一个.dbg文件中,我们在LOH上有~3.5gb,其中大多数对象是字符串

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

我不确定的是,这是否指一个数组。或者它可以引用大型对象图

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


谢谢。

如果数组大于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,因为字符串是字符数组。ItSs2不是LOH,项目是LOH,但实际对象O不是LOH。

< P>您是正确的,如果数组大于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。

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

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

我同意@daspek和@dotnetstep

例如,在@dotnetstep的示例中,o在32位机器上的大小应为12字节,在64位机器上的大小应为24字节

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

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

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


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

我同意@daspek和@dotnetstep

例如,在@dotnetstep的示例中,o在32位机器上的大小应为12字节,在64位机器上的大小应为24字节

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

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

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


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

回答得很好。谢谢现在来看看为什么我在LOH上有超过1gb的字符串!调试不是很有趣吗:)回答得很好。谢谢现在来看看为什么我在LOH上有超过1gb的字符串!调试不是一件乐事吗:)只是一个猜测:如果网站通过串接字符串动态生成页面/html,那么切换到StringBuilder或适当的控件/数据绑定可能值得一试。WinDbg可以帮助您找出这些字符串来自何处只是一个猜测:如果网站正在通过连接字符串动态生成页面/html,那么可能值得尝试切换到StringBuilder或适当的控件/数据绑定。WinDbg可以帮助您找出这些字符串的来源