java - Linux 使用运行 Java GC 的系统/内核 CPU

标签 java linux garbage-collection jvm

一些背景信息;

服务器;

具有 130 GB Ram 的新 SLES 12 服务器旨在为大型数据库(150G + 数据)运行 MySQL。

服务器还将托管一些 Java 应用程序。

Java 版本(默认来自 Oracle)- Java(TM) SE 运行时环境(build 1.7.0-b147)- Java HotSpot(TM) 64 位服务器 VM(build 21.0-b17,混合模式)

我们遇到了以下问题;

运行一些特定的 java 应用程序会使内核/系统 cpu 峰值减慢/暂停应用程序一段时间。我通过制作一个 Java 应用程序重现了它,该应用程序只是随着时间的推移消耗内存并使用一些 cpu。

调查显示,在经济放缓期间出现大量中断 (10000-25000)。

每次减速后,Java 都会获得更多内存。将 Java 设置为从固定内存开始似乎也可以减少问题(将 -Xmx 和 -Xms 设置为相同的值)。详细的垃圾收集还表明 GC 正在启动并且可能是触发器。

GC 和内存分配由于某种原因非常昂贵,我们不确定从这里看哪里。来自 GC 的详细信息:

[GC^C 1024064K->259230K(3925376K), 87,3591890 secs]

在低端 linux 服务器上运行 GC 的相同程序(运行 SLES,来自 SUN 的 Java 1.6.0_11);

[GC 1092288K->253266K(3959488K), 3.0125460 secs]    

减速期间的 TOP:

top - 11:23:33 up 87 days, 19:55,  5 users,  load average: 14.27, 4.50, 10.17
Tasks: 250 total,  39 running, 211 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us, 71.8%sy,  0.0%ni, 28.2%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    129033M total,   128576M used,      457M free,     1388M buffers
Swap:    32765M total,       13M used,    32752M free,   113732M cached

减速期间的 vmstat(从第 3 行开始);

procs -----------memory---------- ---swap-- -----io---- -system-- -----cpu------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0  13552 1714328 1422268 116462260    0    0    10     9    0    0  0  0 100  0  0
 1  0  13552 1241780 1422268 116462292    0    0     0     0  240  353  1  0 99  0  0
 1  0  13552 695616 1422268 116462292    0    0     0    17  419  431  3  0 97  0  0
55  0  13552 486384 1422268 116462292    0    0     0     2 20228  458  1 57 43  0  0
75  0  13552 476172 1422268 116462300    0    0     0     8 12782  684  0 70 30  0  0
65  0  13552 470304 1422268 116462304    0    0     0     0 13108  792  0 72 28  0  0

为什么 GC 在高端服务器上与低端服务器相比如此昂贵?有什么想法可以在哪里寻找线索吗?

更新 - 调用参数 2012-11-26 调用参数;

java -Xmx4g -Xms4g -verbose:gc -server -cp "./dest/" UseMemoryMain

给予

[GC^C 1024064K->259230K(3925376K), 87,3591890 secs]

改为;

java -Xmx4g -Xms4g -XX:+UseParallelGC -verbose:gc -cp "./dest/" UseMemoryMain

给予

[GC 1048640K->265430K(4019584K), 0,0902660 secs]

改为;

java -Xmx4g -Xms4g -XX:+UseConcMarkSweepGC -verbose:gc -cp "./dest/" UseMemoryMain

给予

[GC 1092288K->272230K(3959488K), 0,1791320 secs]

真正有趣的是,今天 重新运行而没有告诉使用哪种 GC 方法给出了这个;

java -Xmx4g -Xms4g -verbose:gc -server -cp "./dest/" UseMemoryMain

给予

[GC 1024064K->259238K(3925376K), 0,0839190 secs]

Java 以某种方式改变了默认 GC 的策略...

最佳答案

垃圾收集确实是一个棘手的话题。 为了给出最佳答案,您应该发布用于调用 java 的完整命令行。

正如您所说,搁浅 GC 开关会有所帮助。原因是,不幸的是,对于当今使用的许多应用程序而言,默认设置并不是最佳设置。对于许多需要快速响应的应用程序,因为它们是交互式的,参数

-XX:+UseConcMarkSweepGC

会有很大的不同。

值得注意的是,使用您提到的 JVM,使用更大的堆(比方说更大的 10GB)总是需要一些调整。获取您拥有的 GC 日志,观察当您使用 GC 选项时行为如何变化。我建议尝试不同的收集器策略(如 CMS 或 G1),并尝试 Eden Space 的配置(如 Xmn)。

最后但并非最不重要的一点是,您可以使用探查器调查应用程序对内存执行的操作。也许可以改进代码,从而避免大量 GC。

关于java - Linux 使用运行 Java GC 的系统/内核 CPU,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13541099/

相关文章:

java - java 中的 std::wstring sFile

c# - .NET 中 GC 如何收集静态成员中的资源?

java - Android Views 的 WeakReference 安全吗?

linux - 如何在 bash 的终端界面中隐藏\n?

c - linux读取系统调用没有得到EOF

c# - 我可以 "prime"CLR GC 期望挥霍内存使用吗?

java - 如果刷新 token 被撤销,则从应用程序中注销用户

java - 使用父键对象化过滤器实体

java - JVM 中老年代空间利用率

linux - "command -v lftp >/dev/null 2>&1"是什么意思?