在实时系统中控制Java垃圾收集

时间:2016-10-26 20:39:21

标签: java garbage-collection real-time heap-memory

我们正在用Java运行RT系统。它通常使用相对较大的堆(100 + GB)并处理来自消息队列的请求。必须快速处理每个请求(<100ms)以满足SLA。

我们遇到了严重的GC相关问题,因为GC经常会在请求期间(200 + ms)导致世界停止收集,从而导致失败。

我们的一位具有合理GC知识的开发人员花了很长时间来调整GC参数并尝试不同的GC。几天之后,他想出了一些我们开玩笑地称之为“遗传算法”的参数化#34;。它可以降低GC暂停时间,但仍远未达到SLA要求。

我正在寻找的解决方案是保护代码的一些关键部分,并在请求完成后,让GC执行所需的工作,下一个请求。在请求之外偶尔暂停可能没问题,因为我们有几个工人,而垃圾收集工作人员暂时不会要求请求。

我有一些愚蠢,丑陋,很可能不起作用的想法,但希望他们说明问题:

  • 偶尔在接收线程中调用>> Sass Compilation Failed: resources/assets/sass/compass/_support.scss Error: Undefined operation: "prefix-usage(browser-prefixes(browsers()), css-transitions, (full-support: true), (partial-support: true)) gt 0.1". on line 324 of resources/assets/sass/compass/_support.scss >> @if $usage > $threshold { ------^ ,同时祈求GC做一些工作,
  • 在请求之间调用Thread.sleep()System.gc(),再次无可救药地祈求它提供帮助,
  • 完全使用像https://stackoverflow.com/a/6915221/1137187这样的hacky模式来编写代码。

最后一个重要的注意事项是,我们是一个低预算的初创公司,Zing®等商业解决方案不适合我们,我们正在寻找非商业解决方案。

有什么想法吗?我们将代码完全重写为C ++(我们并不知道GC可能是一个问题而不是开头的解决方案),但代码库已经太大了。

1 个答案:

答案 0 :(得分:2)

  

有什么想法吗?

使用其他JVM? Azul声称能够处理此类案件。 Redhat和Oracle分别为openjdk贡献了shenandoah和zgc,并考虑了类似的目标,所以如果你不想要商业解决方案,也许可以试用实验版本。

还有其他JVM专注于实时应用程序,但据我所知,它们专注于较小系统上更难的实时要求,您的听起来更像是软实时要求。

您可以尝试的另一件事是通过使用预先分配的对象或适用的更紧凑的数据表示来显着减少对象分配(配置应用程序!)。在保持新的大小相同的同时降低分配压力意味着每个收集的死亡率增加,这将加速年轻收藏。

选择硬件以最大化内存带宽也可能有所帮助。

  

在请求之间调用System.gc()或Runtime.gc(),再次无可救药地祈求它帮助,

这个可能-XX:+ExplicitGCInvokesConcurrent结合使用,否则会触发带有CMS或G1的单线程STW集合(我假设你正在使用其中一个)。但这种方法似乎很脆弱,需要大量的调整和监控。

相关问题