java - 长FIFO队列应用的GC暂停调优

标签 java performance garbage-collection

我有一个应用程序将一些数据放入一个长链表中,该链表几乎占据了 JVM 中的所有 JVM 内存。当插入一个新元素时,最后一个元素将被删除,因此列表的大小始终是一个常量。当我将 JVM 内存大小设置为 6GB 时,我开始定期暂停 GC:3.4 秒,大约每 10 秒发生一次。

我在具有 4 个内核和 16GB RAM 的 Linux 上使用 Hotspot Java 1.7.0,64 位。传递了以下 JVM 参数: -Xmx6g -XX:+PrintGC -XX:+UseConcMarkSweepGC -XX:+UseParNewGC

您能否建议一些更好的选择来将 GC 暂停时间最小化到大约 100 毫秒左右?我自己也尝试过寻找这样的选择,但没有成功。

来源如下:

    LinkedList<long[]> list = new LinkedList<long[]>();

    // initial fill in
    for(int i = 0; i < 16L*1024*1024; i ++) {
        list.add(new long[16]);
    }

    System.out.printf("total: %5.1f free: %5.1f\n",((float)Runtime.getRuntime().totalMemory())/(1024*1024*1024), ((float)Runtime.getRuntime().freeMemory())/(1024*1024*1024));

    // the main stuff
    for(;;) {
        list.removeFirst();
        list.add(new long[16]);
    }

更新: 在下面的讨论中,我意识到人们正试图建议对代码进行一些更改。所以我需要对问题的背景做更多的解释。源示例是一个合成的虚幻代码。它很好地说明了很多老一代对象的问题。我在尝试实现具有某种插入和逐出策略的高负载缓存解决方案时遇到了这个问题。这通常会导致老一代垃圾的问题。我的目标是使用 JVM 选项找到最佳解决方案。这里我不想考虑代码改进。我想如果有一种神奇的 GC 参数组合可以使我的示例在低于 100 毫秒的暂停下工作,它也可能解决更一般的问题或至少为类似情况提供一些提示。

最佳答案

我会尝试用 ArrayDequeue 替换这个巨大的链表,特别是因为队列大小是恒定的。

极长的链表容易导致递归实现标记的垃圾收集器出现性能问题。收集器可能更喜欢可以迭代标记的大数组。

更新

有一个模糊的 GC 调优参数可能会有所帮助:

如果你使这个参数大得多,它可能足以阻止 CMS 收集器在标记是深度递归的情况下翻转到非增量模式(因为它可能是一个巨大的链接-列表。)

但是,这样做会增加 JVM 的整体内存使用量。我的“粗略”想法是,您需要一个至少 192 MB 左右的标记堆栈来标记具有 16M 元素的链表。这需要乘以执行标记的 GC 线程数。


The goal of my question is not to change Java code. Just imagine you have a correct java program which does not cause OutOfMemoryError. You have to find the right JVM parameters without changing the code. Actually I have understanding about the causes of such pauses, just I have no idea how to tune JVM to make the pauses less than 100ms.

恐怕在那种情况下您的目标可能无法实现(尽管有上述情况)。如果应用程序对 GC 非常不友好,您将获得糟糕的 GC 性能。

无论如何,您更大的目标是(应该)通过任何必要的方式解决性能问题。修复程序。在这种情况下,修复可能还有其他好处;例如减少内存使用量。

关于java - 长FIFO队列应用的GC暂停调优,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17654964/

相关文章:

java - 共享库 JNI 上 undefined reference

java - 使用 servlet 上的 doGet() 方法处理繁重的操作

php - 在高负载站点中使用 PHP 的策略

mysql连接查询问题

java - 传递零大小的数组,保存分配?

android - 位图被垃圾收集后是否可以使用?

java - 在 Java 中使用 Class<T> 作为注释的属性

java - 在Java中分割字符串,

java - 使您的应用程序随服务器更新的最佳方式是什么?

cocoa - 应用程序似乎正在泄漏内存