CLR GC 与 JVM 上最新的 ZGC 和 Shenandoah GC 相比如何?

Mar*_*ol4 8 .net c# clr garbage-collection jvm

近年来,C#(.NET 世界第一)添加了很多功能来减轻 GC 压力。毫无疑问,所有这些功能使我们能够构建更好、更高效的应用程序。但无论语言和 VM(CLR、JVM)功能如何随着时间的推移而添加,高性能和非阻塞 GC 都是托管应用程序的关键性能因素。

最近,在 JVM 世界中出现了两种新的 GC,它们似乎提供了出色的指标。有一些来源(包括作者)提供了有关这些 GC 的基准和技术见解。我们可以了解到,最大 STW(停止世界)间隔“承诺”不再超过 10 毫秒,并且无论堆大小如何,平均通常会波动到低于 1 毫秒。还有测试表明,新的 GC 开销得到了很好的平衡,不会对应用程序吞吐量产生负面影响,同时大幅减少(10 倍或更多)STW 暂停。

另一方面,有关 CLR GC 的信息非常少。是否有任何最新来源可以了解 CLR GC(4.8、Core 3.1、.NET 5)与最新 JVM 成就的比较?我可以找到一些讨论 CLR GC 与 G1 的旧资料。但如今,G1 无法与 ZGC/Shenandoah 匹敌,而且旧的资料也没有显示出今天的现实。考虑到没有更新的来源,我们可以得出结论,自那时以来,CLR GC 指标并没有显着改善。但这对于 2020 年的 .NET 平台来说似乎是一个真正的问题,因为与平均 1 毫秒和最大 10 毫秒相比,平均 STW 约为 20-30 毫秒,偶尔会跳到 300 毫秒以上,看起来非常糟糕(正如 GC 制造商声称和测试的那样)确认)在 JVM 上暂停。

我必须说这让我有点担心,因为在很多应用程序中 GC 暂停非常重要。事实上,它们是决定特定技术(例如 .NET、JVM、本机等)是否应被视为对某项任务或目的可行的关键因素之一。看起来 JVM 上的最新 GC 为 Java 和其他 JVM 语言/技术开辟了新领域。我们不允许应用程序停止 500 毫秒左右的可能性,因为 GC 必须完成其工作,而最大约 10 毫秒,平均约 1 毫秒就足够了。

今天的真相是什么?CLR GC 与最新的 JVM GC 相比如何?关于 CLR 上的 STW 暂停是否有任何保证(看起来 JVM 正在朝这个方向发展)?

Kev*_*sse 9

这是一个很大的话题,但如果我必须总结一下的话:

  • shenandoah、zgc 等是低延迟垃圾收集器:它们牺牲吞吐量来确保非常短的暂停时间。它们适合某些类型的应用程序(基本上,任何具有低延迟限制的应用程序),但不适用于其他类型的应用程序(举一个极端的例子,对于批处理,您根本不关心延迟并希望最大化吞吐量,这使得这些 GC 是一个糟糕的选择)
  • 迄今为止,.NET 还没有低延迟 GC。我听说有一些长期计划来实施,但我怀疑我们至少在两年后才能看到任何结果
  • .NET GC 的方法与 Java GC 非常不同。Java GC 可以进行非常精细的调整,但代价是复杂性较高。.NET GC 的目标是“只是工作”,设置很少,但很容易理解和利用。这越来越不真实,因为 .NET Core 添加了一堆配置旋钮,例如调整第 0 代预算。

我们不允许应用程序停止 500 毫秒左右的可能性,因为 GC 必须完成其工作,而最大约 10 毫秒,平均约 1 毫秒就足够了。

根据我的非代表性经验,使用 .NET 时,每个第 0 代收集可能会有 5 到 15 毫秒的 GC 暂停时间。如果您的目标是 ~1ms,您可能需要完全禁用 GC。我知道有些公司正在 .NET 中进行高频交易,因此这表明这是可能的。但这仅仅是因为他们有能力在市场时间之外重新启动服务器。如果您需要持续约 1 毫秒的暂停时间,那么 .NET 还没有做好准备。