BlackHole開發好久了,目前穩定性、性能都還能夠了,可是做爲一個Java程序,內存開銷一直是硬傷,動不動100M內存下去了,對於單機用戶實在是不太友好。java
怎麼辦?優化先從分析開始!web
獲取內存信息通常使用jmap。數組
jmap -histo pid
這種方式獲取到得比較簡略,咱們能夠先把內存dump下來,再進行離線分析。jhat是一個離線內存分析工具,會開啓一個web服務以供展現。jvm
jmap -dump:file=dumpfile pid jhat -J-Xmx512m dumpfile
訪問 http://127.0.0.1:7000 便可。默認是Class列表,翻到頁面底部能夠查看其餘功能。工具
參考資料:oop
http://www.lhelper.org/newblog/?tag=jhat性能
http://blog.csdn.net/gtuu0123/article/details/6039474測試
如下分析僅針對JDK 7 HotSpot虛擬機。jmap -histo的結果:優化
num #instances #bytes class name ---------------------------------------------- 1: 28490 4057072 <constMethodKlass> 2: 28490 3882464 <methodKlass> 3: 2630 2820064 <constantPoolKlass> 4: 46350 2412600 <symbolKlass> 5: 32778 2372824 [C 6: 2630 1990744 <instanceKlassKlass> 7: 3418 1955208 [I 8: 15491 1911568 [B 9: 2347 1845400 <constantPoolCacheKlass> 10: 19246 615872 java.lang.String 11: 256 561152 [Lnet.sf.ehcache.store.chm.SelectableConcurrentHashMap$HashEntry; 12: 2930 304720 java.lang.Class 13: 3740 247280 [S 14: 4321 221520 [[I
其中[開頭表示數組,[C [I [B 分別是char[] int[] byte[]。.net
constMethodKlass、都實現自sun.jvm.hotspot.oops.Klass,用於在永久代裏保存類的信息。
換到JDK6以後,發現永久代的消耗下去了。
num #instances #bytes class name ---------------------------------------------- 1: 10823 3072312 [B 2: 16605 2318720 <constMethodKlass> 3: 18687 1388088 [C 4: 16605 1328608 <methodKlass> 5: 27595 1296832 <symbolKlass> 6: 1699 940392 <constantPoolKlass> 7: 2520 883408 [I 8: 1699 724944 <instanceKlassKlass> 9: 1472 565136 <constantPoolCacheKlass> 10: 256 561152 [Lnet.sf.ehcache.store.chm.SelectableConcurrentHashMap$HashEntry; 11: 12148 291552 java.lang.String 12: 4505 288320 net.sf.ehcache.Element 13: 7290 233280 java.lang.ThreadLocal$ThreadLocalMap$Entry 14: 1946 186816 java.lang.Class 15: 4509 180360 net.sf.ehcache.store.chm.SelectableConcurrentHashMap$HashEntry
查看一下總的內存開銷(參考資料: http://yytian.blog.51cto.com/535845/574527)
ps -e -o 'pid,comm,args,pcpu,rsz' | grep java | sort -nrk5 1239 java java -jar -Djava.io.tmpdir= 0.1 52816
或者:
top -pid pid
查看到只有52m,看來JDK7佔用內存果真增長了!
使用140,000個隨機域名作壓力測試。發現以前使用的JDK7 Developer Preview u04,在短期產生大量對象的時候,GC會失去做用,內存迅速飆升到200M,後來更新到1.7.0u25,穩定到了130m,qps大概在49000~50000之間。
嘗試使用ConcurrentHashMap代替EhCache,qps提升到50000~51000之間,變化不明顯,EhCache仍是至關優秀的。
爲了提升吞吐量,查看GC狀況:
sudo jstat -gcutil 2960 S0 S1 E O P YGC YGCT FGC FGCT GCT 0.00 0.75 30.35 12.06 72.92 25 0.063 0 0.000 0.063
140,000個請求產生了25次YGC。
參考了關於JVM的調優文章http://blog.csdn.net/kthq/article/details/8618052
從新設置新生代爲200m,並開啓並行收集:
JVM_OPTION="-XX:+UseParallelGC -XX:NewSize=200m"
140,000個請求只產生了3次YGC,可是qps變化並不明顯。看來新生代設置大以後,雖然YGC少了,可是一次回收的時間多了,最終其實沒啥影響啊,那仍是弄小一點好了。
看來折騰JVM效果不明顯,除了內存開銷以外,其餘沒有明顯變化。