我知道很多关于应该从 gc.logs 中感知什么的事情,比如
- 您应该检查“Full GC”运行的频率,如果它运行频繁则说明有问题
- 您还应该检查“Full GC”在完成时能够回收多少内存,如果它不多,那么它又是问题的迹象,因为它会强制“Full GC”再次运行
- 如果“Full GC”频繁运行,您应该重新检查分配给 java 进程的堆空间。
这些是我正在研究的一些要点,我很想知道在查看 gc 日志时还应该注意什么。
仅供引用,我已经完成了以下线程....
最佳答案
首先你需要知道 GC 会对你的程序造成什么错误。根据您使用的收集器类型,GC 日志的 tenured 和 old gen 内容可能会有所不同。但总的来说,我们需要从 gc 日志中得出的基线推断主要集中在以下方面:
- 小集合需要多长时间?
- 主要收款需要多长时间?
- 次要回收的频率是多少?
- 主要收集的频率是多少?
- 小集合回收了多少?
- 主要馆藏回收了多少?
- 上述的组合
大多数程序都有一个非常频繁的次要回收,它占用大约 90-95% 的堆并将其余部分传递给 Survivor 空间。随后的收集再次清理了大约 80% 的幸存者,实际上只有 2% 到 4% 的实际次要收集使其进入旧世代,无论您使用哪个收集器,这个循环都会继续进行。
现在的痛点是当每个应用程序请求或线程有数百个小型次要集合时,当它们加起来时会占用相当大的时间,大部分时间都在两位数秒内。由于在现代 Collection 家中,次要的传球和横扫并没有阻止世界的情况,所以这是可以忍受的。对于 Old gen,当收集器运行但不回收任何主要内容时,问题就来了。例如:通常收集器会在老一代大约 80-85% 满时运行。这可能是一个停止世界的插曲,因为除非堆有更多空间,否则新数据不能保存在堆上,这可能就是这种情况。因此暂停应用程序线程,让 GC 线程先清理空间。但是一旦收集器完成,堆填充率就不会像它应该的那样下降。一个好的大小应该一次性减少 40% 以上的堆。如果不是,则意味着您需要更多堆来保存长期存在的对象。
所以本质上 GC 分析不是“根据一组预定义的步骤来做”的事情。它更像是一个 hti 和试验分析。它更像是一个实验,您设置初始大小和设置,然后记录或监视 GC Activity 并记录结果。然后在运行 8-10 次之后,您比较笔记并查看哪些适用于您的应用程序,哪些不适用于您的应用程序。这确实是一项有趣的艰苦工作。
关于java - gc.logs 应该检查什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27340974/