我有一个应用程序使用了很多演员:准确地说是 25,000。它使用Scala 2.7.7 并在jdk6_u18上运行。它基本上是监听和处理市场数据,状态很少。
它每天早上 8 点 2 点开始,一个小时内就崩溃了OutOfMemoryError
。“啊哈”你说,“你有内存泄漏!” 除了当我重新启动它时,它永远不会在一天的剩余时间内再次崩溃!尽管美国市场在下午 2.30 开放时,GC 和 CPU 开销都增加了。
一些轶事发现:
- 它在 Solaris 上运行。当我过去在 Linux 上运行它时,它从来没有崩溃过。
- 我试过搞乱代堆大小,分配更多内存等。我认为这没什么区别
- 当我
verbose:gc
打开时,收集器的行为似乎有所不同
提出了几个问题:
- 为什么这个程序的行为在 Linux 和 Solaris 之间会有所不同?
- 为什么从 8.02 开始和从 8.42 开始的行为会有所不同?
- 我听说演员库有一些内存泄漏问题。它们是什么,什么时候修复的,我如何发现这里是否发生了“类似”的事情?(在jhat等中寻找的东西)
- 有谁知道可能会发生什么?
我现在正试图G1
看看这是否有什么不同。我明天会更新这个问题!
G1 的一些输出,带有 verbose:gc on
我想我只是在行动中抓住了它:
600.290:[完全 GC 255M->144M(256M),1.5772616 秒]
602.084:[GC 暂停(年轻)227M->145M(256M),0.0556769 秒]
602.418:[完全 GC 254M->1441526 秒,1. ]
604.279:[GC 暂停(年轻)227M->145M(256M),0.0415157 秒]
604.602:[完全 GC 255M->145M(256M),1.6041762 秒]
606.422:[GC 暂停(年轻)227M->145M(256 ), 0.0237441 秒]
606.710: [完整 GC 254M->145M(256M), 1.6022185 秒]
然后稍晚一点(你可以看到完整的 GC 花费了更长的时间并且回收的更少)
849.084: [完全 GC 254M->176M(256M), 1.9658754 秒]
851.191: [GC 暂停 (年轻) 228M->176M(256M), 0.0218611 秒]
851.414: [完全 GC 254M->1765257 秒, 1. ]
853.492:[GC 暂停(年轻)228M->176M(256M),0.0224688 秒]
853.716:[完全 GC 254M->176M(256M),1.9339705 秒]
855.793:[GC 暂停(年轻)228M->176M(256 ), 0.0215707 秒]
856.009: [完全 GC 254M->176M(256M), 1.9805797 秒]
858.137: [GC 暂停 (年轻) 228M->176M(256M), 0.0223224 秒]
G1 的一些输出,详细信息:gc 关闭
又好了!*叹*
303.656:[GC 暂停(年轻)225M->93M(256M),0.1680767 秒]
308.060:[GC 暂停(年轻)226M->94M(256M),0.1793724 秒]
312.746:[GC 暂停(年轻)227M->93M (256M), 0.1674851 secs]
316.162: [GC pause (young) 227M->95M(256M), 0.1826145 secs]
320.147: [GC pause (young) 226M->94M(256M), 0.1656664 secs]
325.978: [GC pause (年轻) 226M->93M(256M), 0.1475760 秒]
330.176: [GC 暂停 (年轻) 226M->94M(256M), 0.1727795 秒]
很久很久以后它仍然可以!
25882.894:[GC 暂停(年轻)224M->125M(256M),0.2126515 秒]
25884.880:[GC 暂停(年轻)224M->126M(256M),0.2059802 秒]
25887.027:[GC 暂停(年轻)224M->12 (256M), 0.1851359 秒]
25889.940: [GC 暂停 (年轻) 223M->126M(256M), 0.2046496 秒]
25891.567: [GC 暂停 (年轻) 224M->126M(256M), 0.1600574 秒]
再后来,一个完整的 GC
37180.191: [GC pause (young) 225M->154M(256M), 0.1716404 secs]
37182.163: [GC pause (young) (initial-mark) 225M->153M(256M)37182.326: [GC concurrent-mark-start], 0.1622246 secs]
37183.089: [GC concurrent-mark-end, 0.7635219 sec]
37183.090: [GC remark, 0.0032547 secs]
37183.093: [GC concurrent-count-start]
37183.297: [GC concurrent-count-end, 0.20433307]
3.2043307 ] GC 清理 198M->198M(256M), 0.0068127 秒]
37183.400: [GC concurrent-cleanup-start]
37183.400: [GC concurrent-cleanup-end, 0.0000393]
37183.648: [GC pause (young) 222M->153M(256M) , 0.1483041 秒]
37184.235: [GC 暂停 (部分) 171M->91M(256M), 0.2520714 秒]
37187.223:[GC 暂停(年轻)221M->92M(256M),0.1721220 秒]
更新
好吧,自从在 jdk1.6.0_18 上切换到 G1 垃圾收集器后,应用程序已经连续三天表现良好。我怀疑 Erik 对 VM在高吞吐量情况下将自己陷入死亡螺旋的情况的分析是正确的,因为它已经将对象提升到了终身代。