Hadoop与jvm gc策略

我最近我新上了几台hadoop机器,kernel用的比较新,是3.x的。然后发现负载常常在30-100左右,程序总是在gc,实际效率很低,这让我很苦恼。其实按常规的来说,把堆加大,加到不需要频繁gc即可。可是我后来发现不是堆大小的问题。

post一个gc.log:

1.069: [GC 31872K->5284K(122304K), 0.0088550 secs]
6.494: [GC 31690K->4514K(122304K), 0.0099710 secs]
6.508: [GC 33335K->32774K(122304K), 0.0100570 secs]
6.593: [GC 64647K->59923K(154176K), 0.0108310 secs]
6.604: [Full GC 59923K->59653K(200640K), 0.0508330 secs]
6.987: [GC 132863K->107292K(200640K), 0.0085310 secs]
6.995: [Full GC 107292K->106832K(267392K), 0.0401220 secs]
7.183: [GC 170576K->107056K(307264K), 0.0082470 secs]
7.533: [GC 215728K->135600K(322944K), 0.0074970 secs]
12.723: [GC 253360K->173598K(385024K), 0.0124620 secs]
12.735: [Full GC 173598K->173123K(465856K), 0.0724350 secs]
18.332: [GC 352903K->239422K(465728K), 0.0249970 secs]
18.357: [Full GC 239422K->238927K(557312K), 0.1160660 secs]
18.822: [GC 418706K->267380K(621440K), 0.0175090 secs]
19.325: [GC 511412K->267452K(621312K), 0.0022710 secs]
19.780: [GC 511484K->267452K(685248K), 0.0038650 secs]
20.925: [GC 581756K->277025K(693760K), 0.0060070 secs]
21.539: [GC 593825K->276897K(760576K), 0.0061160 secs]
22.371: [GC 665889K->276897K(765504K), 0.0170160 secs]
23.118: [GC 665889K->276833K(838528K), 0.0065460 secs]
24.315: [GC 744417K->333391K(847360K), 33.3970180 secs]
57.712: [Full GC 333391K->332946K(953024K), 152.6022870 secs]
282.438: [GC 804242K->409063K(1035200K), 1.1653870 secs]
283.604: [Full GC 409063K->408521K(1140416K), 0.2474490 secs]
284.887: [GC 966601K->512612K(1213952K), 0.0281880 secs]
284.916: [Full GC 512612K->512210K(1353408K), 0.0457780 secs]
285.999: [GC 1139794K->605350K(1388416K), 2.6966760 secs]
288.696: [Full GC 605350K->604823K(1510144K), 7.9970150 secs]
323.197: [GC 1265222K->684810K(1509824K), 0.1777950 secs]
324.630: [GC 1347658K->745021K(1537280K), 0.0598840 secs]
324.690: [Full GC 745021K->744535K(1696832K), 0.0986400 secs]
326.005: [GC 1432391K->791759K(1696640K), 0.0425280 secs]
327.321: [GC 1482319K->828234K(1697408K), 0.0117510 secs]
328.509: [GC 1519882K->837344K(1697280K), 0.0079260 secs]
329.688: [GC 1528992K->845678K(1697920K), 0.0112400 secs]
330.895: [GC 1538222K->870867K(1697856K), 0.0117370 secs]
332.226: [GC 1563412K->891232K(1698240K), 0.0237550 secs]
333.605: [GC 1584484K->895999K(1698176K), 0.0314060 secs]
334.904: [GC 1589250K->910487K(1698688K), 0.0579970 secs]
334.962: [Full GC 910487K->910073K(1857472K), 0.1606510 secs]
341.566: [GC 1604025K->911406K(1857408K), 0.0074860 secs]
355.581: [GC 1605358K->943545K(1833856K), 0.1045370 secs]
359.845: [GC 1613881K->950785K(1841088K), 0.0991790 secs]
363.841: [GC 1621121K->961049K(1835648K), 0.1762470 secs]

总的堆大小也只有1G,为什么做一次gc需要将近3分钟?当时系统的负载极高。我后来想了一下,是这样:每个机器上,可能有多个mapreduce child进程,每个都是一个单独的jvm。这个进程数我是按照CPU的数量除以2设置的。如果按默认的gc方式,他们都采用的是并行gc。那么需要多少CPU呢?running 队列过大的时候,操作系统会花费大量的时间在上下文切换上,于是让本已很卡的程序变得更卡。

于是我就把gc算法换成串行化的(-XX:+UseSerialGC),然后监测load状况。发现确实没有再超过10的了。

这个是否可推而广之,所有采用多进程方式运行的服务不宜采用并行化GC?

此博客中的热门博文

少写代码,多读别人写的代码

在windows下使用llvm+clang

tensorflow distributed runtime初窥