轉載自 ---- http://agapple.iteye.com/blog/1038336
背景
前段時間一直在關注一些牛人的blog,主要的關注點在一些性能優化上,一些細小的jvm參數優化上。以前這一塊一直是自己的弱項,把這段時間看的內容做一個記錄。
過程
先認識一下幾位大牛的 http://rednaxelafx.iteye.com ?,? http://kenwublog.com/ , 貌似都是taobao中間件團隊的,blog文章都寫的比較不錯。
?
JIT優化
JIT全程: (Just-in-time) , sun的一些資料文檔: Just-In-Time Java Compiler ??, ?? http://java.sun.com/developer/onlineTraining/Programming/JDCBook/perf2.html#jit
主要的內容:
- Hot Spot Detection ?(熱點檢測)
- Native code & Method Inlining ?(本地代碼&方法內聯,根c++的內聯inline方法有點類似)
- Dynamic Deoptimization (去優化,可以針對代碼進行重復的優化/去優化的動作)
提到jit,必須得看一下jvm的解釋模式/編譯模式。
?
- java?-Xint?-version?##?解釋模式,輸出interpreted?mode??
- java?–Xcomp?-version?##編譯模式,輸出compiled?mode??
- java?-Xmixed?-version?##混合模式,輸出mixed?mode??
-XX:+PrintCompilation?(輸出jit編譯信息)
?
- 1 ???????java.lang.Object::<init>?( 1 ?bytes)??
- 2 ???????com.agapple.jvm.options.TestEAScalarReplacement::test?( 23 ?bytes)??
- 3 ???????com.agapple.jvm.options.Point::<init>?( 15 ?bytes)??
- 4 ???????com.agapple.jvm.options.TestEAScalarReplacement::driver0?( 20 ?bytes)??
- 5 ???????com.agapple.jvm.options.TestEAScalarReplacement::driver1?( 20 ?bytes)??
- 6 ???????com.agapple.jvm.options.TestEAScalarReplacement::driver2?( 20 ?bytes)??
- 7 ???????com.agapple.jvm.options.TestEAScalarReplacement::driver3?( 20 ?bytes)??
- 8 ???????com.agapple.jvm.options.TestEAScalarReplacement::driver?( 39 ?bytes)??
?
其他參數:
?
- -XX:CompileCommand=exclude,the/package/and/Class,methodName ?#判處指定的方法不做jit優化
- -XX:CompileCommand='compileonly,java/lang/StringBuffer.*' #指定方法做編譯
- -XX:CompileThreshold=1000 ?# 通過 JIT 編譯器,將方法編譯成機器碼的觸發閥值,可以理解為調用方法的次數,例如調 1000 次,將方法編譯為機器碼
逃逸分析
具體逃逸分析的解釋,可以查看:
?
- wiki文檔: http://en.wikipedia.org/wiki/Escape_analysis
- 原理分析: http://kenwublog.com/jvm-optimization-escape-analysis
- 演示例子: http://rednaxelafx.iteye.com/blog/659108
?
針對逃逸分析的優化,可以引出的優化:?
?
-
標量替換
- scalar?replacement:Java中的原始類型無法再分解,可以看作標量(scalar);指向對象的引用也是標量;而對象本身則是聚合量(aggregate),可以包含任意個數的標量。??
- 如果把一個Java對象拆散,將其成員變量恢復為分散的變量,這就叫做標量替換。拆散后的變量便可以被單獨分析與優化,可以各自分別在活動記錄(棧幀或寄存器)上分配空間;原本的對象就無需整體分配空間了。??
-
棧上分配
- 分析找到未逃逸的變量,將變量類的實例化內存直接在棧里分配(無需進入堆),分配完成后,繼續在調用棧內執行,最后線程結束,棧空間被回收,局部變量也被回收。<span?style= "font-family:?Arial,?sans-serif,?Helvetica,?Tahoma;?white-space:?normal;" >?</span>??
-
鎖削除
- 鎖削除是指虛擬機即時編譯器在運行時,對一些代碼上要求同步,但是被檢測到不可能存在共享數據競爭的鎖進行削除。鎖削除的主要判定依據來源于逃逸分析的數據支持,如果判斷到一段代碼中??
- 在堆上的所有數據都不會逃逸出去被其他線程訪問到,那就可以把它們當作棧上數據對待,認為它們是線程私有的,同步加鎖自然就無須進行??
-
鎖膨脹
- 原則上,我們在編寫代碼的時候,總是推薦將同步塊的作用范圍限制得盡量小——只在共享數據的實際作用域中才進行同步,這樣是為了使得需要同步的操作數量盡可能變小,如果存在鎖競爭,那等待鎖的線程也能盡快地拿到鎖。???
- 大部分情況下,上面的原則都是正確的,但是如果一系列的連續操作都對同一個對象反復加鎖和解鎖,甚至加鎖操作是出現在循環體中的,那即使沒有線程競爭,頻繁地進行互斥同步操作也會導致不必要的性能損耗。?<span?style= "font-family:?Arial,?sans-serif,?Helvetica,?Tahoma;?white-space:?normal;" >?</span>??
-XX:+DoEscapeAnalysis(開啟逃逸分析,jdk6默認開啟)
其他相關參數:
- -XX:+PrintInlining ?#方法內聯
- -XX:+PrintEscapeAnalysis??#逃逸分析內容
- -XX:+PrintEliminateAllocations??#標量替換
- -XX:+PrintAssembly #打印機器碼
鎖優化相關
幾個鎖優化的相關概念:
-
自旋鎖
- 自旋鎖優化的原理是在線程進入OS互斥前,通過CAS自旋一定的次數來檢測鎖的釋放。??
- 如果在自旋次數未達到預設值前鎖已被釋放,則當前線程會立即持有該鎖。??
-
輕量鎖
- 輕量級鎖(Lightweight?Locking),從Java6開始引入了輕量級鎖的概念,本意是為了減少多線程進入互斥的幾率,并不是要替代互斥。??
- 它利用了CPU原語Compare-And-Swap(CAS,匯編指令CMPXCHG),嘗試在進入互斥前,進行補救。??
- 相比于 synchronized 產生的bytecode原語:monitorenter與monitorexit這兩個控制多線程同步的是JVM依賴操作系統互斥(mutex)來實現的。??
- 互斥是一種會導致線程掛起,并在較短的時間內又需要重新調度回原線程的,較為消耗資源的操作。??
- ??
- 白話:每次進行lock之前,先嘗試一次CAS??
-
偏向鎖
- Java偏向鎖(Biased?Locking)是Java6引入的一項多線程優化。它通過消除資源無競爭情況下的同步原語,進一步提高了程序的運行性能。??
- 與輕量級鎖區別在于,輕量級鎖是通過CAS來避免進入開銷較大的互斥操作,而偏向鎖是在無競爭場景下完全消除同步,連CAS也不執行(CAS本身仍舊是一種操作系統同步原語,始終要在JVM與OS之間來回,有一定的開銷)。??
- ??
- 白話:記錄上一次訪問的ThreadId,后續有其他線程對資源競爭時,會觸發進行偏向鎖清除的動作??
-
鎖消除
- 在逃逸分析的基礎上,如果堆上的所有數據都不會逃逸出去被其他線程訪問到,那就可以把它們當作棧上數據對待,認為它們是線程私有的,同步加鎖自然就無須進行??
- 鎖膨脹 ?
- sun 文檔 :? http://java.sun.com/performance/reference/whitepapers/6_performance.html
- 輕量鎖 :? http://kenwublog.com/theory-of-lightweight-locking-upon-cas
- 偏向鎖:? http://kenwublog.com/theory-of-java-biased-locking
- jvm相關參數:? http://kenwublog.com/docs/java6-jvm-options-chinese-edition.htm
- Do Java 6 threading optimizations actually work?? http://www.infoq.com/articles/java-threading-optimizations-p1 ?, ? http://www.infoq.com/articles/java-threading-optimizations-p 2
-
- ?-XX:+DoEscapeAnalysis ?&&? -XX:+EliminateLocks ? #開啟鎖消除,注意鎖消除是基于逃逸分析的基礎,默認兩者都打開
- -XX:+PrintEliminateLocks ?#打印鎖消除日志
- -XX:+UseBiasedLocking ?#開啟偏向鎖
- -XX :+UseSpinning &? -XX:PreBlockSpin=10 ?#啟用自旋鎖
指針壓縮 (-XX:+UseCompressedOops)
OOP = “ordinary object pointer” 普通對象指針。
在64位HotSpot中使用32位指針,默認64位會比32位的內存使用多出1.5倍
啟用CompressOops后,會壓縮的對象:
- 每個Class的屬性指針(靜態成員變量)
- 每個對象的屬性指針
- 普通對象數組的每個元素指針
getter方法優化( -XX: UseFastAccessorMethods)
?
Use optimized versions of Get<Primitive>Field. 估計也是使用Jit + inline技術提升相應的訪問速度。
其他
還有一些jvm優化主要就是內存參數,GC算法。
?
內存參數主要關注-Xms -Xmn -Xmx -XX:PermSize -Xss 等參數的設置,其中eden堆的設置taobao的一位仁兄的建議是每次request消耗的內存大小×100,也有點道理。
每次request消耗內存的計算 =??young區大小/(young gc時間間隔×每秒請求數)
?
GC算法主要是一些CMS , G1算法。后續再補充
感觸?
隨著自己看jvm blog越來越多,發現自己對jvm真的是越來越陌生。
神啊,大家簡歷中盡量少提自己精通jvm了,不然會遭BS,簡歷和面試中是一大忌。
至少我現在看別人的面試簡歷就是有這樣的一種心態,O(∩_∩)O
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
