oxb*_*kes 9 garbage-collection jvm scala out-of-memory actor
我有一个使用相当多的演员的应用程序:准确地说是25,000.它使用Scala 2.7.7并在jdk6_u18上运行.它基本上监听和处理市场数据,并且几乎没有状态.
它从每天上午8点02分开始,并在一小时内崩溃了OutOfMemoryError."啊哈"你说,"你有内存泄漏!" 除了当我重新启动它说,它从来没有,永远再次崩溃的一天的休息!尽管美国市场在下午2:30开放,但GC和CPU开销都有所上升.
一些轶事发现:
verbose:gc打开时,收集器的行为似乎有所不同一些问题出现了:
我现在正试图G1看看这是否有所不同.我明天会更新这个问题!
我想我刚刚抓住了这个行为:
600.290:[全GC 255M-> 144M(256M),1.5772616秒]
602.084:[GC暂停(年轻)227M-> 145M(256M),0.0556769秒]
602.418:[全GC 254M-> 144M(256M),1.6415216秒]
604.279:[GC暂停(年轻)227M-> 145M(256M),0.0415157秒]
604.602:[全GC 255M-> 145M(256M),1.6041762秒]
606.422:[GC暂停(年轻)227M-> 145M(256M) ),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-> 176M(256M),1.9352357秒]
853.492:[GC暂停(年轻)228M-> 176M(256M),0.0224688秒]
853.716:[全GC 254M-> 176M(256M),1.9339705秒]
855.793:[GC暂停(年轻)228M-> 176M(256M) ),0.0215707秒]
856.009:[全GC 254M-> 176M(256M),1.9805797秒]
858.137:[GC暂停(年轻)228M-> 176M(256M),0.0223224秒]
再好了!*叹*
303.656:[GC暂停(年轻)225M-> 93M(256M),0.1680767秒]
308.060:[GC暂停(年轻)226M-> 94M(256M),0.1793724秒]
312.746:[GC暂停(年轻)227M-> 93M (256M),0.1674851秒]
316.162:[GC暂停(年轻)227M-> 95M(256M),0.1826145秒]
320.147:[GC暂停(年轻)226M-> 94M(256M),0.1656664秒]
325.978:[GC暂停(年轻)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-> 125M (256M),0.1851359秒]
25889.940:[GC暂停(年轻)223M-> 126M(256M),0.2046496秒]
25891.567:[GC暂停(年轻)224M-> 126M(256M),0.1600574秒]
然后,还有一个完整的GC
37180.191:[GC暂停(年轻)225M-> 154M(256M),0.1716404秒]
37182.163:[GC暂停(年轻)(初始标记)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.2043307]
37183.393:[ GC净化198M-> 198M(256M),0.0068127秒]
37183.400:[GC concurrent-cleanup-start]
37183.400:[GC concurrent-cleanup-end,0.0000393]
37183.648:[GC暂停(年轻)222M-> 153M(256M) ,0.1483041秒]
37184.235:[GC暂停(部分)171M-> 91M(256M),0.2520714秒]
37187.223:[GC暂停(年轻)221M-> 92M(256M),0.1721220秒]
那么,既然切换到G1垃圾收集器上jdk1.6.0_18应用已经表现本身上3个连续天.我怀疑Erik对于虚拟机在高吞吐量情况下陷入死亡螺旋的情况的分析是正确的,在这种情况下,它将对象推广到终身代.
您是否有理由期望堆的大小会缓慢增长?两条痕迹看起来都在增长。我在很多情况下做过的一件事就是减少堆,试图让问题变得更糟。然而,256M 大约是 Scala 的下限。
我之前注意到的一件事是,如果你有一些短命的对象,由于太大的压力而从伊甸园生成出来,它会逐渐杀死你。当有大量活动(也许您早上有大量活动?)并且您的伊甸园空间不够大时,就会发生这种情况。一般而言,Scala,尤其是演员,大量使用短暂的小物体,似乎有一个神奇的门槛,一旦你跨过,一切都会走下坡路。因此,一次运行会很好,但下一次就会崩溃并烧毁。
我之前注意到的另一件事是,在 OSX/x86 上运行良好的 GC 设置通常在 Sparc/Solaris 上运行不佳,反之亦然。如果您使用 CoolThreads,我建议您将 GC 配置为调度程序/池中的每个线程都有一个 GC 线程。
这就带来了另一件事——确保调度程序不会随意创建新线程。有时它会这样做。我想说你几乎应该总是手动设置线程的上限。我不知道它有多相关,但是关于 Actor 默认使用的 fork-join 调度程序的一个有趣的事实是,它适用于短期的、CPU 密集型任务。在它管理的线程中进行 IO 会破坏它的假设。当然它应该仍然有效,但是......
祝你好运!我已经因为这些问题而失去了很多很多日子。
看看这里的一些选项:http://java.sun.com/performance/reference/whitepapers/tuning.html
看起来您正在使用并发标记清除收集器。尝试设置:
-XX:+UseParallelGC
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1117 次 |
| 最近记录: |