Java 为什么这个特殊的次要GC如此缓慢

Java 为什么这个特殊的次要GC如此缓慢,java,garbage-collection,jvm,Java,Garbage Collection,Jvm,我们在tomcat 6.0.35和JDK 7u60上运行了一个Jira 6.3.10应用程序。操作系统是Centos 6.2,内核为2.6.32-220.7.1.el6.x86_64。 我们有时会注意到应用程序中的暂停。我们发现了与GC的相关性 内存的启动选项是:-Xms16384m-Xmx16384m-XX:NewSize=6144m-XX:MaxPermSize=512m-XX:+UseCodeCacheFlushing-XX:+UseConcMarkSweepGC-XX:+CMSClass

我们在tomcat 6.0.35和JDK 7u60上运行了一个Jira 6.3.10应用程序。操作系统是Centos 6.2,内核为2.6.32-220.7.1.el6.x86_64。 我们有时会注意到应用程序中的暂停。我们发现了与GC的相关性

内存的启动选项是:
-Xms16384m-Xmx16384m-XX:NewSize=6144m-XX:MaxPermSize=512m-XX:+UseCodeCacheFlushing-XX:+UseConcMarkSweepGC-XX:+CMSClassUnloadingEnabled-XX:ReservedCodeCacheSize=512m-XX:+DisableExplicitGC

问题是,我无法解释为什么一个特定的小GC需要将近7秒。请访问以下网址查看收藏:
2015-09-17T14:59:42.485+0000
。用户注意到一分钟多一点的停顿

从我当时读到的资料来看,我认为是Tcard_扫描决定了这一缓慢的收集,但我不确定,也无法解释为什么会发生这种情况

2015-09-17T14:57:03.824+0000: 3160725.220: [GC2015-09-17T14:57:03.824+0000: 3160725.220: [ParNew: 5112700K->77061K(5662336K), 0.0999740 secs] 10048034K->5017436K(16148096K), 0.1002730 secs] [Times: user=1.01 sys=0.02, real=0.10 secs]
2015-09-17T14:57:36.631+0000: 3160758.027: [GC2015-09-17T14:57:36.631+0000: 3160758.027: [ParNew: 5110277K->127181K(5662336K), 0.0841060 secs] 10050652K->5075489K(16148096K), 0.0843680 secs] [Times: user=0.87 sys=0.02, real=0.09 secs]
2015-09-17T14:57:59.494+0000: 3160780.890: [GC2015-09-17T14:57:59.494+0000: 3160780.890: [ParNew: 5160397K->104929K(5662336K), 0.1033160 secs] 10108705K->5056258K(16148096K), 0.1036150 secs] [Times: user=0.62 sys=0.00, real=0.11 secs]
2015-09-17T14:58:27.069+0000: 3160808.464: [GC2015-09-17T14:58:27.069+0000: 3160808.465: [ParNew: 5138145K->86797K(5662336K), 0.0844890 secs] 10089474K->5039063K(16148096K), 0.0847790 secs] [Times: user=0.68 sys=0.01, real=0.09 secs]
2015-09-17T14:58:43.489+0000: 3160824.885: [GC2015-09-17T14:58:43.489+0000: 3160824.885: [ParNew: 5120013K->91000K(5662336K), 0.0588270 secs] 10072279K->5045124K(16148096K), 0.0590680 secs] [Times: user=0.53 sys=0.01, real=0.06 secs]
2015-09-17T14:59:03.831+0000: 3160845.227: [GC2015-09-17T14:59:03.832+0000: 3160845.227: [ParNew: 5124216K->89921K(5662336K), 0.1018980 secs] 10078340K->5047918K(16148096K), 0.1021850 secs] [Times: user=0.56 sys=0.01, real=0.10 secs]
2015-09-17T14:59:42.485+0000: 3160883.880: [GC2015-09-17T14:59:42.485+0000: 3160883.880: [ParNew: 5123137K->98539K(5662336K), 6.9674580 secs] 10081134K->5061766K(16148096K), 6.9677100 secs] [Times: user=102.14 sys=0.05, real=6.97 secs]
2015-09-17T15:00:17.679+0000: 3160919.075: [GC2015-09-17T15:00:17.680+0000: 3160919.075: [ParNew: 5131755K->141258K(5662336K), 0.1189970 secs] 10094982K->5107030K(16148096K), 0.1194650 secs] [Times: user=0.80 sys=0.00, real=0.12 secs]
2015-09-17T15:01:20.149+0000: 3160981.545: [GC2015-09-17T15:01:20.149+0000: 3160981.545: [ParNew: 5174474K->118871K(5662336K), 0.1251710 secs] 10140246K->5089067K(16148096K), 0.1255370 secs] [Times: user=0.63 sys=0.00, real=0.12 secs]
2015-09-17T15:03:07.323+0000: 3161088.718: [GC2015-09-17T15:03:07.323+0000: 3161088.719: [ParNew: 5152087K->80387K(5662336K), 0.0782410 secs] 10122283K->5055601K(16148096K), 0.0785610 secs] [Times: user=0.57 sys=0.01, real=0.07 secs]
2015-09-17T15:03:26.396+0000: 3161107.791: [GC2015-09-17T15:03:26.396+0000: 3161107.791: [ParNew: 5113538K->66134K(5662336K), 0.0697170 secs] 10088753K->5044322K(16148096K), 0.0699990 secs] [Times: user=0.48 sys=0.01, real=0.07 secs]
2015-09-17T15:03:47.185+0000: 3161128.580: [GC2015-09-17T15:03:47.185+0000: 3161128.581: [ParNew: 5099350K->62874K(5662336K), 0.0692700 secs] 10077538K->5043879K(16148096K), 0.0695140 secs] [Times: user=0.61 sys=0.02, real=0.07 secs]
2015-09-17T15:04:04.503+0000: 3161145.899: [GC2015-09-17T15:04:04.503+0000: 3161145.899: [ParNew: 5096090K->63684K(5662336K), 0.0709490 secs] 10077095K->5047678K(16148096K), 0.0712390 secs] [Times: user=0.54 sys=0.01, real=0.07 secs]
2015-09-17T15:04:48.013+0000: 3161189.409: [GC2015-09-17T15:04:48.013+0000: 3161189.409: [ParNew: 5096900K->74854K(5662336K), 0.1530160 secs] 10080894K->5061766K(16148096K), 0.1533520 secs] [Times: user=0.76 sys=0.00, real=0.15 secs] 
我们有198GB内存。服务器未处于主动交换状态。这个特定的Jira实例具有相当高的使用率。有一些自动工具一直在戳这个实例。 服务器上的内存状态:

$ cat /proc/meminfo
MemTotal:       198333224 kB
MemFree:        13194296 kB
Buffers:           93948 kB
Cached:         10236288 kB
SwapCached:      1722248 kB
Active:         168906584 kB
Inactive:       10675040 kB
Active(anon):   163755088 kB
Inactive(anon):  5508552 kB
Active(file):    5151496 kB
Inactive(file):  5166488 kB
Unevictable:        4960 kB
Mlocked:            4960 kB
SwapTotal:       6193136 kB
SwapFree:             12 kB
Dirty:             14040 kB
Writeback:             0 kB
AnonPages:      167534556 kB
Mapped:          1341076 kB
Shmem:              9196 kB
Slab:            2117816 kB
SReclaimable:    1258104 kB
SUnreclaim:       859712 kB
KernelStack:       51048 kB
PageTables:       431780 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    105359748 kB
Committed_AS:   187566824 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      680016 kB
VmallocChunk:   34255555544 kB
HardwareCorrupted:     0 kB
AnonHugePages:  79947776 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:        5604 kB
DirectMap2M:     2078720 kB
DirectMap1G:    199229440 kB

在同一台机器上运行的其他Jira实例不受影响。我们正在这台机器上运行30个Jira实例。

一般情况下

这可能是另一个占用资源(或交换增加的开销)的进程:

有时操作系统的活动,如交换空间或网络 在GC发生时发生的活动可以使GC 停顿的时间要长得多。这些暂停可以是几次 几秒钟到几分钟

如果系统配置为使用交换空间,则操作系统可能会 将JVM进程的非活动内存页移动到交换空间,以 为当前活动进程释放内存,该进程可能相同 进程或系统上的其他进程。交换非常重要 昂贵,因为它需要的磁盘访问速度比 与物理内存访问相比。所以,如果在垃圾桶里 收集系统需要执行交换时,GC似乎 跑很长时间

资料来源:

本文还提供了一些可能感兴趣的通用指针


具体地说

然而,在这种情况下,我认为问题更可能是服务器上运行的JVM的数量

30*不同的堆,加上JVM开销,可能会导致大量内存使用。如果总堆分配超过物理内存的75%,则可能会遇到上述问题(交换活动将揭示这一点)

更重要的是,线程CPU争用可能是这里真正的杀手。根据经验,我的JVM数量不会超过逻辑CPU的数量(如果实例将同时使用)

此外,我尝试确保GC线程的数量不超过可用虚拟CPU内核数量的4倍

在30*18(根据您的评论),这可能是540个GC线程。我假设你的系统没有135个逻辑核

如果我对响应性的要求较低,我可能会达到8:1的比例。但这就是我在单个系统上所能做到的——独立的JVM相互竞争资源


建议

减少并行线程的数量,以使总数低于4倍阈值。我发现这不实用,将低优先级JVM设置为低值(2)并适当地设置为高优先级JVM(4或8)


另外,我不确定设置
congcthreads=0
的含义,因为我假设没有任何工作线程就不能有CMS。。。?如果未设置该值,则JVM会根据系统自行决定。我希望这也是0设置的行为——在共享系统上,这可能是一个过高的值。尝试显式设置。

服务器有多少物理内存可用?是否有其他应用程序或繁重的进程正在运行?我们有189 GB的物理内存。12GB可用空间和9GB文件系统缓存空间。应用程序使用166GB。所有30个Jira实例是否都在自己的JVM中运行,配置了16个GiB堆?另外,配置了多少个GC线程?对于堆,它们中的大多数都在2-4GB的范围内。我们使用的默认值是:
congcthreads=0
parallegcthreads=18
,正如
/usr/java/jdk1.7/bin/java-XX:+UnlockDiagnosticVMOptions-XX:+UnlockExperimentalVMOptions-XX:+PrintFlagsFinal-version | grep-i gcthreads
congcthreads
在启用CMS时默认为5。至少以下报告是这样的:
java-XX:+UnlockDiagnosticVMOptions-XX:+UnlockExperimentalVMOptions-XX:+PrintFlagsFinal-XX:+UseConcMarkSweepGC-Version2>/dev/null | grep ConcGCThreads
非常好,但事实并非如此。请看我编辑的问题。事实上,有时当一些实例开始被更多地使用并且同时运行GC时,这是一个问题。但对于这个特定的问题,当只有一个实例出现性能问题时,情况并非如此。我的感觉是,这不是由系统问题引起的,而是由特定的使用模式引起的。让我困惑的是,小规模的收集时间似乎并不比之前和之后的其他小规模GCs有什么特别之处。一些实例是空闲的,只有内部调度程序和监控在其中运行一些东西。由于大多数对象都未被触摸,因此由于最近内核中的预期分页机制,它们的一些页面被复制到页面文件中。请参阅:为小实例设置
ParallelGCThreads
lower是一个好主意。非常感谢。我不认为它能解决这个问题,但它肯定会有助于优化环境。只需添加一个注释:
congcthreads
在使用CMS时默认为5。