java - 使用 UseConcMarkSweepGC 减少 JVM 暂停时间 > 1 秒

标签 java performance garbage-collection jvm jvm-arguments

我在一台有 16Gb 内存、8 核处理器和 Java 1.6 的机器上运行一个内存密集型应用程序,所有这些都运行在 CentOS 5.2 版(最终版)上。确切的 JVM 详细信息是:

java version "1.6.0_10"
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) 64-Bit Server VM (build 11.0-b15, mixed mode)

我正在使用以下命令行选项启动应用程序:

java -XX:+UseConcMarkSweepGC -verbose:gc -server -Xmx10g -Xms10g ...

我的应用程序公开了一个 JSON-RPC API,我的目标是在 25 毫秒内响应请求。不幸的是,我看到延迟高达或超过 1 秒,这似乎是由垃圾收集引起的。以下是一些较长的示例:

[GC 4592788K->4462162K(10468736K), 1.3606660 secs]
[GC 5881547K->5768559K(10468736K), 1.2559860 secs]
[GC 6045823K->5914115K(10468736K), 1.3250050 secs]

这些垃圾收集事件中的每一个都伴随着延迟的 API 响应,其持续时间与显示的垃圾收集长度非常相似(在几毫秒内)。

这里有一些典型的例子(这些都是在几秒钟内产生的):

[GC 3373764K->3336654K(10468736K), 0.6677560 secs]
[GC 3472974K->3427592K(10468736K), 0.5059650 secs]
[GC 3563912K->3517273K(10468736K), 0.6844440 secs]
[GC 3622292K->3589011K(10468736K), 0.4528480 secs]

问题是我认为 UseConcMarkSweepGC 会避免这种情况,或者至少使这种情况极为罕见。相反,超过 100 毫秒的延迟几乎每分钟发生一次或更多(尽管超过 1 秒的延迟相当罕见,可能每 10 或 15 分钟一次)。

另一件事是,我认为只有 FULL GC 会导致线程暂停,但这些似乎不是 Full GC。

可能需要注意的是,大部分内存都被使用软引用的 LRU 内存缓存占用。

如有任何帮助或建议,我们将不胜感激。

最佳答案

首先,查看 Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning文档,如果您还没有这样做的话。该文档说:

the concurrent collector does most of its tracing and sweeping work with the application threads still running, so only brief pauses are seen by the application threads. However, if the concurrent collector is unable to finish reclaiming the unreachable objects before the tenured generation fills up, or if an allocation cannot be satisfied with the available free space blocks in the tenured generation, then the application is paused and the collection is completed with all the application threads stopped. The inability to complete a collection concurrently is referred to as concurrent mode failure and indicates the need to adjust the concurrent collector parameters.

稍后……

The concurrent collector pauses an application twice during a concurrent collection cycle.

我注意到那些 GC 似乎并没有释放太多内存。也许您的许多对象都是长寿的?您可能希望调整生成大小和其他 GC 参数。按照许多标准,10 Gig 是一个巨大 堆,我会天真地期望 GC 在如此巨大的堆上花费更长的时间。尽管如此,1 秒仍然是一个非常长的暂停时间,表明有问题(您的程序正在生成大量不需要的对象或正在生成难以回收的对象,或其他原因)或者您只需要调整 GC。

通常,我会告诉别人,如果他们必须调整 GC,那么他们还有其他问题需要先解决。但是对于这种规模的应用程序,我认为您会陷入“比普通程序员更需要了解 GC”的境界。

正如其他人所说,您需要分析您的应用程序以查看瓶颈在哪里。您的 PermGen 是否对于分配给它的空间来说太大了?你在创建不必要的对象吗? jconsole 至少可以显示有关 VM 的最少信息。这是一个起点。然而,正如其他人所指出的,您很可能需要比这更高级的工具。

祝你好运。

关于java - 使用 UseConcMarkSweepGC 减少 JVM 暂停时间 > 1 秒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/574021/

相关文章:

javascript - V8 GC何时触发其第一个次要GC周期(清理)?

Java volatile 变量多线程行为

java - 如果数据已经存在,如何验证 jTextField?

mysql - BIG 查询 VS 本地查询和搜索 VS 对数据库的多个查询

c++ - 生成 m 和 n 之间的素数

compiler-construction - 如何避免 LLVM 的代码生成器执行不需要的常量折叠?

java - 鼓励 Java 中的主要 GC(但不是 STW GC)

java - 错误 : sun. awt.image.ToolkitImage 无法转换为 java.awt.image.BufferedImage

java - 如何使包含 FlowLayout 的 JPanel 居中?

performance - XPath 性能——哪一个更好?