解释在JBoss Server上观察JVM垃圾收集

jba*_*ndi 3 java performance jboss garbage-collection jvm

使用VisualVM,我观察JBoss服务器上的以下堆使用情况:

VisualVm堆使用的屏幕截图

使用以下(相关)JVM选项启动服务器:

-Xrs -Xms3072m -Xmx3072m -XX:MaxPermSize=512m -XX:+UseParallelOldGC -Dsun.rmi.dgc.client.gcInterval=3600000 -Dsun.rmi.dgc.server.gcInterval=3600000
Run Code Online (Sandbox Code Playgroud)

我们目前还启用了GC日志记录:

-XX:+PrintGC -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -Xloggc:log\gc.log
Run Code Online (Sandbox Code Playgroud)

基本上我对观察到的模式很满意,因为看起来我们没有任何内存泄漏(模式在几天内重复).

不过我想知道是否有优化空间?

首先,我不明白为什么当堆使用量达到2GB左右时垃圾收集已经开始了?它看起来像是因为它可以提供3GB,因为它可以在以后启动?

更多我会对有关观察到的堆使用模式和使用的JVM选项的提示感兴趣:

  • 观察到的模式是否允许我得出有关使用的GC策略(UseParallelOldGC)的结论?我认为这个策略是正确的,或者考虑到观察到的堆使用情况,我应该尝试使用另一个策略吗?

  • 我可以优化GC过程,以便使用完整的堆大小(3GB)吗?

  • 现在它似乎从未使用过3GB的全部,我应该将Xms/Xmx降低到2.5GB吗?

  • 我缺少任何明显的GC优化吗?像调整-XX:NewSize或-XX:NewRatio?

  • 想到的任何其他提示?

谢谢!

Mic*_*ael 6

我会说你的屏幕截图中的GC行为看起来很"正常".

您通常希望在堆空间过满之前触发主要集合,或者根据许多场景很容易遇到OutOfMemoryError.

另外,您是否意识到Java的堆空间被划分为新的(eden),当前(幸存者)和旧(tenured)对象的不同区域?

这个答案提供了一些关于这个主题的优秀信息,所以我在此不再重复:

java内存池是如何划分的?

基本上,堆的每个区域都会触发自己的集合.伊甸园空间通常经常被收集,并且"快速"收集幸存者和终身空间通常更大并且需要更长时间来收集.

你可以根据上面的图表减少堆大小吗?

是.但是,您的当前配置允许您的应用程序有一些喘息空间,如果它可能遇到更繁忙的时期或负载峰值.

你能优化GC吗?

是的,但没有神奇的设置.第一个问题是你真的需要吗?如果您的应用程序只是一个非交互式"处理器",我真的不会打扰.如果您真的需要低暂停应用程序,那么可以进行一些调整.权衡通常是您需要更多资源才能获得相同的结果.

我的经验是,当负载增加时,低暂停JVM配置具有非常明显的下降点.如果您的应用程序通常处于空闲状态,但是在调用它时您希望得到"快速"响应,那么低暂停可能是合适的.在繁忙的系统中,流量/负载达到峰值,您可能更喜欢更传统的方法.

摘要

在任何情况下,不要试图进行任意更改以"改进"您的配置.对您的方法保持科学和专业.

如果您没有可用的生产指标,请考虑使用Apache JMeter等工具构建负载测试场景,以模拟应用程序的典型活动负载,增加负载(例如,10%,20%或50%等)和间歇性高峰负荷.

使用GC和应用程序的指标,至少测量:

  • 平均吞吐量.
  • 峰值吞吐量.
  • 平均负载(CPU和内存).
  • 高峰负荷.
  • 应用程序暂停时间(总暂停和个别暂停).
  • 花在执行收藏上的时间
  • 可靠性(OOME等).

一旦您对使用当前配置记录了应用程序性能的准确基准测试感到高兴,那么您才应该开始进行任何更改.

显然,记录您的配置及其指标.记录任何更改,然后执行相同的基准测试.然后,您将能够看到任何可能适用的性能增益(或损失)和任何权衡.

以下是关于该主题的Oracle的进一步阅读,以帮助您入门:

Java SE 6虚拟机垃圾收集调整