我已阅读 why is it bad practice to call System.gc() ,以及许多其他的,例如this one描述了对 System.gc() 的一次真正灾难性的滥用。然而,在某些情况下,GC takes too long并避免长时间停顿,例如 avoiding garbage这并不完全是微不足道的,并且使代码更难维护。
恕我直言,在以下常见场景中手动调用 GC 是可以的:
- 有多个可互换的网络服务器,它们前面有故障转移。
- 每台服务器都使用几 GB 的堆,STW 暂停时间比平均请求长得多。
- 故障转移不知道 GC 何时发生。
- 故障转移可以根据需要免除服务器的责任。
该算法似乎很简单:定期选择一个服务器,不再向其发送任何请求,让它完成正在运行的请求,让它执行 GC,然后重新激活该服务器。
我想知道我是否遗漏了什么?1,2
有哪些替代方案?
长时间运行的请求可能是一个问题,但我们假设没有问题。或者简单地将等待时间限制为与 GC 所需时间相当的时间。发出更慢的请求听起来还不错。
像
-XX:+DisableExplicitGC
这样的选项可能会使算法变得无用,但不要使用它(我的用例包括我负责的专用服务器)。
最佳答案
对于低延迟交易系统,我以非典型方式使用 GC。
您希望避免在交易日期间发生任何收款,即使是轻微的收款。实现此目的的一种方法是每秒创建少于 300 KB 的垃圾。这大约是每小时 1 GB,或每天最多 24 GB。当您使用 24 GB Eden 空间时,这意味着没有次要/主要 GC。然而,为了确保 GC 在计划且可接受的时间发生,System.gc()
比如每天早上 5 点接到电话,第二天您就有一个干净的伊甸园空间。
有时,您创建的垃圾比预期多,例如无法重新连接到数据源,并且您可能会获得少量的次要集合。然而,只有当出现问题时才会发生这种情况。
了解更多详情http://vanillajava.blogspot.co.uk/2011/06/how-to-avoid-garbage-collection.html
by avoiding garbage is not exactly trivial and makes the code harder to maintain.
完全避免垃圾几乎是不可能的。然而 300 KB/s 对于 JVM 来说并不是那么困难。 (如今,您可以在一台具有 24 GB Eden 空间的机器上拥有多个 JVM)
请注意,如果您能够将垃圾速度保持在 50 KB/s 以下,您就可以在没有 GC 的情况下运行一整周。
Periodically select a server, let no more requests be send to it, let it finished its running requests, let it do its GC, and re-activate the server.
您可以将 GC 视为未能满足 SLA 条件。在这种情况下,当您确定集群即将发生这种情况时,您可以删除服务器,对其进行 Full GC 并将其返回到集群。
关于java - 手动 GC 调用的用例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36962630/