2

让我们想象一下这个简单的测试程序:

static void Main(string[] args)
{
    var length = 30000000;
    var c = new List<object>();
    for (int i = 0; i < length; i++)
    {
        c.Add(new object());
    }
    var start = DateTime.Now;
    GC.Collect();
    GC.WaitForFullGCComplete();
    Console.WriteLine("GC took " + (DateTime.Now - start).TotalMilliseconds + " ms");
    Console.ReadKey();
}

在我的计算机(Framework 4.0,x64)上,输出约为 1.4 秒,而样本消耗了 ~1GB 的 RAM。

问题:有什么方法可以加速垃圾收集?有什么最佳做法吗?客户端应用程序中约 1GB 的内存消耗很多,但仍然相当合理。但是在我的情况下,延迟超过 1 秒是不可接受的。

只是可能不会得到支持但可以帮助我的想法:

  • 我可以告诉 GC 忽略某些对象吗?
  • 我可以将堆分成多个部分,以便让 GC 在部分堆上运行。(我宁愿十倍 100 毫秒的延迟。)
4

2 回答 2

4

在某些情况下,当处理在相当长的时间内无法收集的大量数据,GC 可能会很烦人 - 会有很多引用,甚至更糟糕的是:GC 实际上不太可能收集很多,所以浪费时间!这里的一种选择是考虑使用值类型的数组等。这里的意义在于,一个包含 200 万个值类型的数组只是一个引用;200 万个对收藏没有任何影响。但是,子引用仍然会产生影响,例如string每行的 s。但它可以提供帮助

既然我提到string了 s,另一件要考虑的事情是你是否有多个相同底层字符组合的实例;例如,通过从数据库或文件加载数据。您可能会考虑在那里应用一些手动字符串实习(使用string.Intern- 而是使用每个加载字典或类似的)。这将再次减少string正在收集的 s 的数量。

作为最后的想法;如果您的数据需要集合,这可能会很棘手 - 例如,列表通常涉及额外的 2 个对象:列表和底层数组。将其乘以几百万,事情就会开始变得棘手。在我们的例子中,我们通过使用固定缓冲区来解决这个问题,但这是一个有点高级的话题,并且仅适用于您对列表中的项目数量有一个可预测的小“上限”。

于 2013-02-11T10:41:53.917 回答
0

您的测试完全是人为的 - 实际上您不会在应用程序中明确等待 GC 完成。

但是,如果您有某些对时间要求严格的代码部分,那么您可以暂时禁用 GC

于 2013-02-11T10:34:16.270 回答