网络上有很多文档,我也抄记很多内容到有道去笔记,可是那些东西都是别人的,
只通过消化测试总结才算是自己的内容,所以我也抄袭一下吧.
先上传一张图, 主要是对JVM GC收集器的对比说明,根据链接内容,做出自己的理解.
http://hllvm.group.iteye.com/group/topic/37095此链接的内容对我很我帮助.
# cat gccheck.sh #!/bin/bash #没有注释 20150916 filename="/data/resin/log/jvm-app-a.log" thistime=0.0 lasttime=0.0 tail -100 $filename | awk '/\[GC/' | while read line do echo $line | egrep -q 'CMS-initial-mark|YG occupancy' if [ $? -eq 0 ];then echo $line | awk '/CMS-initial-mark/{printf "%d %s %s, ",$1/60,$1,$(NF-1)};/YG occupancy/{print $1,$(NF-1)}' continue fi midline=$(echo $line | sed 's#\[##g;s#\]##g;s#:##g;s#(# #g;s#)##g;s#,##g;s#K##g;s#-># #g;') rate=$(echo $midline | awk '{printf "%.0f\n",($10-$7)/($12-$7)*100}') ygk=$(echo $midline | awk '{printf "%d\n",$5-$6}') heapk=$(echo $midline | awk '{printf "%d\n",$10-$11}') thistime=$(echo $midline | awk '{print $3}') interval=$(echo "$thistime-$lasttime"|bc) usedtime=$(echo $midline | awk '{printf "%d\n",$8*1000}') let total=ygk-heapk if [ $total -gt 0 ];then echo -e "YG减少的数据量 $ygk HEAP堆减少量 $heapk \033[31m间隔时间为 $interval 持续时间为 $usedtime 转移内容到OG为+$total KB \033[0m当前OG占有率 $rate%" else echo -e "YG减少的数据量 $ygk HEAP堆减少量 $heapk \033[31m间隔时间为 $interval 持续时间为 $usedtime 转移内容到OG为-$total KB\033[0m当前OG占有率 $rate%" fi lasttime=$thistime sleep 0.05 done
也是抄别人的,自己改了一下,主要是对GC回收过去进行查看.
13449.991: [GC 13449.991: [ParNew: 344566K->17482K(368640K), 0.0272580 secs] 734079K->407266K(1495040K), 0.0274010 secs] [Times: user=0.10 sys=0.01, real=0.03 secs]
13488.107: [GC 13488.107: [ParNew: 345162K->17620K(368640K), 0.0378120 secs] 734946K->410438K(1495040K), 0.0379860 secs] [Times: user=0.13 sys=0.00, real=0.03 secs]
13516.941: [GC 13516.941: [ParNew: 345300K->12992K(368640K), 0.0198980 secs] 738118K->406392K(1495040K), 0.0200320 secs] [Times: user=0.07 sys=0.00, real=0.02 secs]
简单脚本分析,通过打印日志了解JVM回收健康情况,抄抄改改.
可以了解到每次YGC的垃圾回收和对象实例转移情况, 我认为间隔35秒,YGC持续25秒左右的
哎呀,这个脚本还有修改一下.
执行 bash gccheck.sh会产生以下可视化内容.
YG减少的数据量 327084 HEAP堆减少量 326813 间隔时间为 36.019 持续时间为 27 转移内容到OG为+271 KB 当前OG占有率 32%
YG减少的数据量 327542 HEAP堆减少量 324508 间隔时间为 38.116 持续时间为 37 转移内容到OG为+3034 KB 当前OG占有率 33%
YG减少的数据量 332308 HEAP堆减少量 331726 间隔时间为 28.834 持续时间为 19 转移内容到OG为+582 KB 当前OG占有率 33%
############################################################
经过对网上内容的抄袭,终于得出这样的配置内容.
<jvm-arg>-Xms1500m</jvm-arg>
<jvm-arg>-Xmx1500m</jvm-arg>
<jvm-arg>-Xmn400m</jvm-arg>
<jvm-arg>-XX:SurvivorRatio=8</jvm-arg>
<jvm-arg>-XX:+UseConcMarkSweepGC</jvm-arg>
<jvm-arg>-XX:+CMSParallelRemarkEnabled</jvm-arg>
<jvm-arg>-XX:+UseCMSCompactAtFullCollection</jvm-arg>
<jvm-arg>-XX:CMSInitiatingOccupancyFraction=80</jvm-arg>
<jvm-arg>-XX:+UseCMSInitiatingOccupancyOnly</jvm-arg>
<jvm-arg>-XX:MaxDirectMemorySize=1024m</jvm-arg>
<jvm-arg>-XX:MaxPermSize=256m</jvm-arg>
<jvm-arg>-XX:PermSize=128m</jvm-arg>
<jvm-arg>-XX:+PrintGCTimeStamps</jvm-arg>
<jvm-arg>-XX:+PrintGCDetails</jvm-arg>
<jvm-arg>-Xss512k</jvm-arg>
<jvm-arg>-Xms1500m</jvm-arg> #heap堆设置为1.5G,OG就可以剩下1.1G, 通过调用CMS提高收集速率,当到达(OG的80%容量)
<jvm-arg>-Xmx1500m</jvm-arg> #880M的时候,就可以进行FGC处理,可以达到70秒左右(初始标记+并行扫描压缩)
<jvm-arg>-Xmn400m</jvm-arg> #刚开始设置512M,后来调整400MB,使其每隔35秒进行一次YG,单次YG时间为20秒左右
<jvm-arg>-XX:SurvivorRatio=8</jvm-arg> #有时会观察到survivor比例不一致,显示设置为8
<jvm-arg>-XX:+UseConcMarkSweepGC</jvm-arg> #使用CMS进行OG内存回收,对应会使用ParNew进行YG回收
<jvm-arg>-XX:+CMSParallelRemarkEnabled</jvm-arg> #第三阶段remark使用并行标记,减少停工时间 注意并发和并行
<jvm-arg>-XX:+UseCMSCompactAtFullCollection</jvm-arg> #CMS默认没有压缩,此处调用避免碎片,CMS-concurrent-sweep阶段
<jvm-arg>-XX:CMSInitiatingOccupancyFraction=80</jvm-arg> #等到OG使用率达到80%的时候开始收集
<jvm-arg>-XX:+UseCMSInitiatingOccupancyOnly</jvm-arg> #OG必须达到80%才调用CMS进行FGC收集
<jvm-arg>-XX:MaxDirectMemorySize=1024m</jvm-arg> #应用会调用NIO进行内容分配,我会强制限定使用1G
<jvm-arg>-XX:MaxPermSize=256m</jvm-arg> #PG最大空间,最大扩展范围
<jvm-arg>-XX:PermSize=128m</jvm-arg> #静态对象 变量存在空间,此处为128M,一般让其维持在50%使用
<jvm-arg>-XX:+PrintGCTimeStamps</jvm-arg> #必须打印出日志进行分析
<jvm-arg>-XX:+PrintGCDetails</jvm-arg> #必须打印出日志进行分析
<jvm-arg>-Xss512k</jvm-arg> #线程实例由之前1M调整为512K, 降低单支成本,提高产量
命令查看jvm信息,jmap jstat
#以下是jstat打印GC回收情况,那个FGCT为2是刚启动应用时出现些问题,稳定一天左右就会回归到70ms左右.
#另外那个YGC大约维持25ms左右,我觉得已经很赞,我的水平就是这样.
# /usr/java/jdk/bin/jstat -gcutil -h30 8828 1s
S0 S1 E O P YGC YGCT FGC FGCT GCT
0.00 35.76 85.10 36.73 50.36 421 10.026 2 1.654 11.680
0.00 35.76 90.37 36.73 50.36 421 10.026 2 1.654 11.680
0.00 35.76 92.28 36.73 50.36 421 10.026 2 1.654 11.680
35.39 0.00 0.34 36.78 50.36 422 10.050 2 1.654 11.704
35.39 0.00 2.51 36.78 50.36 422 10.050 2 1.654 11.704
35.39 0.00 4.96 36.78 50.36 422 10.050 2 1.654 11.704
----------------------------------------------------------------------------------------------
# /usr/java/jdk/bin/jmap -heap 8828
Attaching to process ID 8828, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 20.7-b02
using parallel threads in the new generation.
using thread-local object allocation.
Concurrent Mark-Sweep GC
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 1572864000 (1500.0MB)
NewSize = 419430400 (400.0MB)
MaxNewSize = 419430400 (400.0MB)
OldSize = 5439488 (5.1875MB)
NewRatio = 2
SurvivorRatio = 8
PermSize = 134217728 (128.0MB)
MaxPermSize = 268435456 (256.0MB)
#一将功成万骨枯,java程序内存资源很宝贵......
Heap Usage:
New Generation (Eden + 1 Survivor Space): #一个eden区和两个S区(两者只能存在一个),实际可用NG为360MB
capacity = 377487360 (360.0MB)
used = 140504056 (133.99510955810547MB)
free = 236983304 (226.00489044189453MB)
37.22086376614041% used
Eden Space: #E区使用情况
capacity = 335544320 (320.0MB)
used = 125658376 (119.83716583251953MB)
free = 209885944 (200.16283416748047MB)
37.44911432266235% used
From Space: #此处S区from空间分配为1:1:8,实际为10%(400MB),最后是40MB,可是有时不会得到这个值.
capacity = 41943040 (40.0MB)
used = 14845680 (14.157943725585938MB)
free = 27097360 (25.842056274414062MB)
35.394859313964844% used
To Space: #同上
capacity = 41943040 (40.0MB)
used = 0 (0.0MB)
free = 41943040 (40.0MB)
0.0% used
concurrent mark-sweep generation: #以前调整的时候,总会遇到内存碎片,这次终于正常了,呵呵.
capacity = 1153433600 (1100.0MB)
used = 424188544 (404.5377197265625MB)
free = 729245056 (695.4622802734375MB)
36.77615633877841% used
Perm Generation: #根据上面的配置,PG一般会维持在50%左右,我这次分配128MB
capacity = 134217728 (128.0MB)
used = 67596336 (64.46488952636719MB)
free = 66621392 (63.53511047363281MB)
50.363194942474365% used
----------------------------------------------------------------------------------------------
优化结果和跟进
----------------------------------------------------------------------------------------------
说明64位VM机器和JDK,内存4G
1.resin jvm1.5G(400+1100),mc缓存分配1G,为提高信息读写速度使用NIO技术,
使用bytebuffer. allocate分配内在,此处DirectMemorySize也最大设置为1G.
2. 通过free -m了解到SWAP还是有731M在使用,实际想不到是哪个进程在使用.
ps aux结果为以下内容
java区RES1.2G为heap堆部分,swap部分应该为nio bytebuffer使用的1G加速空间.
mc区分配1G空间,数据跳出率很高,此处swap 468M应该是MC的影响.
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ SWAP DATA COMMAND
8828 xxx 15 0 2282m 1.2g 12m S 6.7 31.4 37:31.03 1.0g 2.1g java
4128 yyy 15 0 1307m 839m 560 S 2.3 21.2 5445:57 468m 1.3g memcached
3.MC的状态信息 主要还是觉得有必要优化一下MC,学学学
curr_items 399754 现在的条目只有40万条
total_items 418833290 总共活跃条目4.1亿次
evictions 148384635 数据跳出率1.4亿次
RunDays 140 days
Items 399754
MaxMem 1024 MByte
Usage 57.20 %
HitRate 86.23 %
以下为MC的资源池分配情况,group 29 30占用过多资源,导致group 8 9次没有资源使用,结果消耗系统swap资源.
# xmemcached.pl localhost:11211
# Item_Size Max_age 1MB_pages Count Full?
8 480 B 15067 s 27 58853 yes
9 600 B 29830 s 33 57651 yes
10 752 B 8255 s 28 39032 yes
29 51.7 kB 29275 s 742 8263 yes
30 64.7 kB 3095 s 138 857 yes
标记:优化其应用,通过控制jvm大小和算法来优化,当然找到内存泄漏代码并解决问题才是最重要.
可是目前只会这样,通过此文希望能再接再励吧.
感觉以下链接内容:
http://www.iteye.com/topic/212967
http://www.iteye.com/topic/212967
http://www.iteye.com/topic/473874
http://blog.csdn.net/fenglibing/article/details/6321453
http://hllvm.group.iteye.com/group/topic/27945