【发布时间】:2018-02-26 13:18:52
【问题描述】:
情况
我正在为 Java 竞赛开发一个客户端,每当我收到请求时,我都有两秒钟的时间做出响应。响应后到下一个请求的时间未知。
有时,找到正确的响应需要将近 2 秒,有时只需几毫秒。问题是当垃圾回收发生在一个较长的计算(也分配了很多对象)中,就在两秒快结束时,因此响应发送得太晚,我被取消资格。
使用详细的 gc 输出,我发现 gc 通常需要大约 0.6 秒,即使我试图将其限制得更低。我还尝试在较短的计算中调用System.gc()(因为我确信我有大约 1.8 秒的时间不需要做任何事情),但它需要 1-3 秒,这也不安全。
我的程序只有很少的长寿命对象,大多数寿命短于一秒。
规格
我知道程序将始终在具有这些可用资源的同一台机器上运行:
- 64 位 Ubuntu
- openjdk:8u151-jre
- Intel® Xeon® Prozessor E5-2620 v4 的一个核心
- 1.5 GB 内存
我当前的jvm参数:
java -Dfile.encoding=UTF-8 \
-XX:MaxGCPauseMillis=200 \
-XX:GCPauseIntervalMillis=2050 \
-XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled \
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 \
-XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark \
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
想法
- 我能否以某种方式告诉 gc 它现在应该收集一些垃圾,但只收集大约 1.5 秒?
- 是否有一个
System.gc()等效项仅适用于年轻对象并且不检查终身代? - 能否优化 jvm 参数以获得更好的效果?
【问题讨论】:
-
据我所知,你不能真正限制垃圾收集。您只能尝试在计算时保留对所有变量的引用,因为这样 GC 肯定不会运行(因为所有内容仍然被引用,因此无法释放)。然后在计算之后取消引用所有内容,以便 gc 可以运行(并删除 System.gc() 以希望您的垃圾收集得到提示)
-
与其尝试优化 Java 垃圾收集(这类似于说您想对哥斯拉进行化妆),不如尝试专注于更大的问题。为什么每次收到请求时,Java 都需要执行 GC? GC 确实发生了很多,但如果你找到了一个模式,那么它就是你的程序导致它发生。你可能想好好看看它背后的原因。
-
您是否尝试过使用 G1 垃圾回收,它有更频繁的微循环,几乎无法察觉。 System.gc() 只是一个建议,在现代收集器中并没有做任何明显的事情。将上面所有的 GC 参数替换为:--XX:+UseG1GC
-
一种不好的方法是调用 GC,我的朋友也有同样的问题,即对象管理不善,调用 GC 或 GC 做了很多工作。所以他每次都用这个参数运行 GC:
- java -Dsun.rmi.dgc.client.gcInterval=3600000但我认为这也是一个不好的方法。看看你的程序或阅读这个GC approach -
学习c++的时间
标签: java garbage-collection jvm