.net - 有关如何避免客户端应用程序中 GC 延迟的建议

标签 .net garbage-collection

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

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 秒的延迟是 Not Acceptable 。

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

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

最佳答案

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

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

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

关于.net - 有关如何避免客户端应用程序中 GC 延迟的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14810257/

相关文章:

java - 垃圾回收问题

c# - N单位。索引 [0] 处的值不同

c# - 垃圾收集器无法为主要堆部分分配 16384 字节的内存

java - 垃圾收集器如何在引擎盖下工作以收集死对象?

java - 微服务中Kafka生产者引起的Big GC暂停

java - Java 中 GC 的成本

c# - .NET Flag Enum 从值中获取属性

c# - 如何解析人为输入的逻辑属性,例如这个和(那个或另一个)?

c# - NUnit DLL 版本不匹配

.net - System.IO.File.ReadAllText 不会因无效编码而抛出异常