调整 JVM 堆大小后解释 jstat 输出

发布于 2025-01-03 17:06:14 字数 2940 浏览 0 评论 0原文

最近尝试增加堆空间和新旧代大小的比率,我看到 jstat -gccapacity 的结果令人困惑,它显示的容量比我预期的要小得多。

JVM (1.5.0_16) 使用 -server -Xms2048m -Xmx2048m -XX:NewRatio=2 启动。它在 Solaris 5.10 amd64 主机上运行。大约有 10GB 的可用内存。因此,根据我的阅读,JVM 应该能够充分利用 2GB 的堆空间。

通过观察jstat -gcutil,我观察到所有代都多次填充,导致垃圾收集。例如:

Timestamp         S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
        66150.4   0.00  51.09  56.95  90.33  54.85   6291   58.922     7   22.826   81.748

我本以为这会导致 JVM 将所有代扩展到其完整大小。然而,jstat -gccapacity 产生:

 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC
700416.0 700416.0  86016.0 1408.0 1408.0  39104.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6338     7

后续运行显示 NGC/S0C/S1C/EC 值的变化:

 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC
700416.0 700416.0  86016.0 1472.0 1472.0  39104.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6380     7
700416.0 700416.0 106496.0 1792.0 1856.0  97024.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6433     7
700416.0 700416.0 106496.0 1792.0 1792.0  96064.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6436     7

据我了解,容量数字是发电的总大小,利用率数字显示内的分配一代人。因此,上面的结果告诉我,新代的最小和最大容量组合均为 (NGCMN/MGCMX) 684MB,而旧代的最小和最大容量为 1,366MB (OGCMN/OGCMX)。让我困惑的是新一代的能力。所以我的问题是:

  1. 为什么 EC + S0C + S1C == NGC 不? (41,920 != 86016)
  2. 为什么 NGC 明显小于 NGCMN/MGCMX?
    • 这是因为达到了最大堆大小(NGC+OGC+PGC 的大小为 1,488MB),如果是这样,什么会导致下限?我能找到的所有文档都说 Solaris 64 位 JVM 应该能够使用 4GB。
  3. 如果达到最大堆大小,为什么新一代的容量会发生变化(全部增加或全部减少),而老一代则没有改变来补偿)。

其他可能有用的 jstat 结果:

$ jstat -gcnew 20167
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
1536.0 1600.0 1300.3    0.0 13  15 1600.0  82880.0  30892.6   6482   60.540

$ jstat -gcnewcapacity 20167
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
  700416.0   700416.0   106496.0   1472.0 233472.0 233472.0   1408.0   700288.0    81088.0  6489     7

$ jstat -gcold 20167
   PC       PU        OC          OU       YGC    FGC    FGCT     GCT
 38912.0  21426.5   1398784.0   1375651.6   6503     7   22.826   83.627

$ jstat -gcoldcapacity 20167
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
  1398784.0   1398784.0   1398784.0   1398784.0  6517     7   22.826   83.779

$ jstat -gcpermcapacity 20167
  PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT
   16384.0    65536.0    38912.0    38912.0  6531     7   22.826   83.925

Having recently attempted to increase the heap space and ratio of new to old gen size I'm seeing confusing results from jstat -gccapacity which is showing much smaller capacities than I would expect.

The JVM (1.5.0_16) is started with -server -Xms2048m -Xmx2048m -XX:NewRatio=2. It's running on a Solaris 5.10 amd64 host. With about 10GB of free memory. So from what I've read the JVM should be able to make use of the full 2GB of heap space.

Watching jstat -gcutil I've observed all of the generations filling up several times causing garbage collections. E.g.:

Timestamp         S0     S1     E      O      P     YGC     YGCT    FGC    FGCT     GCT
        66150.4   0.00  51.09  56.95  90.33  54.85   6291   58.922     7   22.826   81.748

Which I would have thought would cause the JVM to expand all the generations to their full size. However, jstat -gccapacity produces:

 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC
700416.0 700416.0  86016.0 1408.0 1408.0  39104.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6338     7

Subsequent runs show NGC/S0C/S1C/EC change in value:

 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC      PGCMN    PGCMX     PGC       PC     YGC    FGC
700416.0 700416.0  86016.0 1472.0 1472.0  39104.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6380     7
700416.0 700416.0 106496.0 1792.0 1856.0  97024.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6433     7
700416.0 700416.0 106496.0 1792.0 1792.0  96064.0  1398784.0  1398784.0  1398784.0  1398784.0  16384.0  65536.0  38912.0  38912.0   6436     7

From what I understand, the capacity figures are the total size of the generation and the utilisation figures show allocations within the generation. So the above result is telling me that the combined new gen min and max capacities are both (NGCMN/MGCMX) 684MB and the old gen min and max are 1,366MB (OGCMN/OGCMX). What's confusing me is the capacities of the new generations. So my questions:

  1. Why doesn't EC + S0C + S1C == NGC? (41,920 != 86016)
  2. Why is NGC significantly smaller than NGCMN/MGCMX?
    • Is this because the max heap size is being hit (which would put it at 1,488MB, from NGC+OGC+PGC), if so what would cause the lower limit? All the documentation I can find says a Solaris 64 bit JVM should be able to use 4GB.
  3. If the max heap size is being hit why do the new generations change in capacity (either all increasing or all decreasing) without the older generation changing to compensate).

Other potentially useful jstat results:

$ jstat -gcnew 20167
 S0C    S1C    S0U    S1U   TT MTT  DSS      EC       EU     YGC     YGCT
1536.0 1600.0 1300.3    0.0 13  15 1600.0  82880.0  30892.6   6482   60.540

$ jstat -gcnewcapacity 20167
  NGCMN      NGCMX       NGC      S0CMX     S0C     S1CMX     S1C       ECMX        EC      YGC   FGC
  700416.0   700416.0   106496.0   1472.0 233472.0 233472.0   1408.0   700288.0    81088.0  6489     7

$ jstat -gcold 20167
   PC       PU        OC          OU       YGC    FGC    FGCT     GCT
 38912.0  21426.5   1398784.0   1375651.6   6503     7   22.826   83.627

$ jstat -gcoldcapacity 20167
   OGCMN       OGCMX        OGC         OC       YGC   FGC    FGCT     GCT
  1398784.0   1398784.0   1398784.0   1398784.0  6517     7   22.826   83.779

$ jstat -gcpermcapacity 20167
  PGCMN      PGCMX       PGC         PC      YGC   FGC    FGCT     GCT
   16384.0    65536.0    38912.0    38912.0  6531     7   22.826   83.925

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

朮生 2025-01-10 17:06:14

事实证明,这是吞吐量收集器的故意行为:

使用 5.0 Java[tm] 虚拟机调整垃圾收集 > 5.2.2.2 调整生成大小

收集器保存的统计信息(例如,平均暂停时间)是
在集合结束时更新。测试以确定是否
然后对已实现的目标进行任何必要的调整
一代人的规模已经形成。

观察 JVM 处于峰值负载时的 GC 容量确实显示组合的年轻代当前容量等于最小/最大容量值。

It turns out that this is intentional behaviour by the throughput collector:

Tuning Garbage Collection with the 5.0 Java[tm] Virtual Machine > 5.2.2.2 Adjusting Generation Sizes

The statistics (e.g., average pause time) kept by the collector are
updated at the end of a collection. The tests to determine if the
goals have been met are then made and any needed adjustments to the
size of a generation is made.

Observing the GC capacities while the JVM is under peak load does show the combined young gen current capacities to be equal to the min/max capacity values.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文