运行期优化
一、概述
即時編譯器(Just In Time Compiler,JIT編譯器):Java程序最初是通過解釋器進行解釋執行的,當虛擬機發現某個方法或代碼塊的運行
特別頻繁時,就會把這些代碼認定為“熱點代碼”。為了提高熱點代碼的執行效率,在運行時,虛擬機將會把這些代碼編譯成與本地平臺相關
的機器碼,并進行各種層次的優化,完成這個任務的編譯器稱為即時編譯器。
二、HotSpot虛擬機內的即時編譯器
1、解釋器與編譯器
當程序需要迅速啟動和執行的時候,解釋器可以首先發揮作用,省去編譯時間立即執行。
在程序運行后,隨時間推移,編譯器逐漸發揮作用,把越來越多的代碼編譯成本地代碼之后,可以提供執行效率。
HotSpot虛擬機中內置兩個即時編譯器,分別稱為Client Compiler 和Server Compiler,簡稱C1編譯器和C2編譯器。
默認C1編譯器,可以使用-client 或 -server 指定。
解釋器與編譯器搭配使用的方式在虛擬機中稱為混合模式,用戶可以通過參數-Xint強制虛擬機運行與解釋模式(Interpreted Mode),
這時編譯器完全不參與工作,全部代碼都使用解釋方式執行。
也可以使用-Xcomp強制虛擬機運行編譯模式(Compiled Mode),這時將優先采用編譯方式執行程序。
Client Compiler 可以獲得更高的編譯速度,Server Compiler可以獲得更好的編譯質量。
2、編譯對象與觸發條件u
熱點代碼:
- 被多次調用的方法
-
被多次執行的循環體
判斷一段代碼是不是熱點代碼,是不是需要觸發即時編譯,這樣的行為稱為熱點探測。熱點探測方式:
- 基于采樣的熱點探測:虛擬機周期性的檢查各個線程的棧頂,如果發現某個方法經常出現在棧頂,那這個方法就是熱點方法。
- 基于計數器的熱點探測:虛擬機為每個方法建立計數器,統計方法的執行次數,如果執行次數超過一定閾值,就認為是熱點方法。
HotSpot采樣的是基于計數器的熱點探測,為每個方法準備兩類計數器:方法調用計數器、回邊計數器。
方法調用計數器:統計方法被調用的次數,Client模式下默認1500次,Server模式下默認10000次,可以通過虛擬機參數-XX:CompiledThreshold修改。
回邊計數器:統計一個方法中循環體代碼執行次數。
三、編譯優化技術
1、公共子表達式消除
如果一個表達式E已經計算過了,并且從先前的計算到現在E中所有的變量的值都沒有發生變化,那么E的這次出現就成為了公共子表達式。
對于這種表達式就沒有必要花時間對它進行計算,只需直接用前面計算過的表達式結果代替E就可以了。
當這段代碼進入虛擬機即時編譯器編譯后,就變為了第二行代碼
2、數組邊界檢查消除
java 在訪問數組類型數據時會自動進行上下界范圍檢查,如果超出范圍將拋出ArrayIndexOutOfBoundsException,每次數據讀寫都帶有一次
隱含的條件判定,影響性能。對于循環體來說,如果編譯器可以判定循環變量取值范圍永遠在[0,length())之間,那在整個循環中就可以
把數組上下界檢查消除。
3、方法內聯
把目標的代碼復制到發起調用的方法中,避免發生真實的方法調用。
分析對象動態作用域:當一個對象在方法中被定義后,它可能被外部方法所引用,例如作為調用參數傳遞到其他方法中,稱為方法逃逸。
甚至可能被外部線程訪問到,譬如賦值給類變量或可以在其他線程中訪問的實例變量,稱為線程逃逸。
如果能證明一個對象不會逃逸到變量或線程外,也就是別的方法或線程無法通過任何途徑訪問到這個對象,則可能為為這個變量進行優化。
- 棧上分配:java虛擬機中,在java堆上分配創建對象的內存空間,java堆中的對象對于各個線程都是共享可見的,只要持有這個對象的引用,
就可以訪問堆中存儲的對象數據。虛擬機垃圾收集系統可以回收堆中不再使用的對象。
如果確定一個對象不會逃逸出方法之外,那讓這個對象在棧上分配,對象占用的內存就可以隨棧幀出棧而銷毀。
- 同步消除:線程同步本身就是一個相對耗時的過程,如果逃逸分析能夠確定一個變量不會逃逸出線程,無法被其他線程訪問,那這個變量的讀寫
肯定就不會有競爭,對這個變身實施同步措施也就可以消除。 - 標量替換:標量是指一個數據已經無法分解成更小的數據來表示,Java虛擬機中的原始數據類型都不能再進一步分解,就可以稱為標量。
相對的,如果一個數據可以繼續分解,稱為聚合量,java中的對象就是典型的聚合量。如果把一個Java對象拆散,根據程序訪問的情況,將其使用
到的成員變量恢復原始類型來訪問就叫標量替換。如果逃逸分析證明一個對象不會被外部訪問,并且對象可以被拆散的話, 程序真正執行的時候
可能不創建這個對象,而改為直接創建它的若干被這個方法使用到的成員變量替換。這些變量建立在棧上分配讀寫。
總結
- 上一篇: Kotlin难点解析:extension
- 下一篇: 写在前面-Terraform