【问题标题】:.NET object creation and generations.NET 对象创建和生成
【发布时间】:2010-04-19 08:51:20
【问题描述】:

有没有办法告诉 .NET 在第 2 代堆中分配一个新对象。我有一个问题,我需要分配大约 200 MB 的对象,对它们做一些事情,然后把它们扔掉。这里发生的情况是所有数据都被复制了两次(从 gen0 到 gen1,然后从 gen1 到 gen2)。

【问题讨论】:

    标签: .net garbage-collection instantiation


    【解决方案1】:

    没有办法直接在第 2 代进行分配。所有分配都发生在第 0 代和 LOH 上的大对象。

    但是,当对象移动到新一代时,通常不会复制数据。相反,不同堆的起点被移动。由于堆的压缩,对象可能会被移动,但这是另一回事。

    如果在第 2 代中存储对象很重要,您可以重用这些实例。 IE。在类型上创建一些 init 方法并调用它而不是创建新实例。

    【讨论】:

    • 如果我理解正确,所有新创建的对象都分配在 gen0 堆中。当 gen0 堆满时,所有对象(仍然需要的)都被移动到 gen1,而 gen0 变为空。当 gen1 的 GC 运行时,gen1 也会发生同样的情况。据我所知,没有将指针移动到不同堆的事情。也许您可以提供指向 MSDN 或其他地方的链接,因为我正在经历大量的复制(可以通过性能监视器看到)。
    • @nimoraca:移动指针部分是 CLR 所做的。如果不是这样,您将不得不为所有收集移动对象,这将是非常低效的。有关详细信息,请查看《通过 C# 的 CLR》一书。这篇文章有一些相同点msdn.microsoft.com/en-us/magazine/bb985010.aspx
    • @nimoraca:如果您对细节感兴趣,您还可以使用 WinDbg 和 SOS(或 PSSCOR2)检查不同的堆等。
    • 由于 LOH 对象是大于 85k(或类似的)的对象,我做了一个简单的测试。首先,我创建了大小为 50kb 的 1000 字节数组。由于这些对象没有在 LOH 中分配,因此我创建了大小为 100kb 的 500 字节数组。第二次测试几乎比第一次快三倍,这清楚地说明了代际移动物体的问题。这是我的应用程序中的主要性能问题,因为它往往会经常分配很多小对象。我将尝试重用对象(如您所建议的那样),但我希望有一个更简单的解决方案。
    • 其实LOH并没有被compacted,所以在LOH的GC过程中没有移动对象。没有细节就很难评论你的测量结果。
    【解决方案2】:

    Framework 处理大对象的方式与处理普通对象的方式不同。简而言之,它将大对象放入生成中,并且在重新分配堆时不要移动它。

    【讨论】:

      【解决方案3】:

      如果您想修复对象以使框架无法移动它们,您可以尝试使用GCHandle 固定对象。这通常用于 P/Invoke,但会给出您正在寻找的结果。我怀疑您是否会看到由于代际压缩导致的减速,但我不能说没有看到您的分析数据。

      http://msdn.microsoft.com/en-us/library/khk3k17t%28v=VS.71%29.aspx

      例子:

      var q = new MyObject();
      var handle = GCHandle.Alloc(q, GCHandleType.Pinned);
      
      // use object
      
      handle.Free();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-01
        • 2020-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-16
        • 2016-07-23
        • 2023-02-04
        相关资源
        最近更新 更多