參考文章:
整體描述:
標量替換:
虛擬機會用即時編譯器把執行頻繁的熱點**變成機器碼,並做相應優化。
1 直譯器和編譯器的優點
直譯器優點:
程式啟動快,占用記憶體小,編譯失敗時還能逆優化恢復到解析狀態
編譯器優點:
執行時可探測熱點**,並把位元組碼編譯成本地機器碼,這樣程式執行效率更高
2 在什麼情況下才會被判定為熱點**?需要編譯成機器碼了?
jvm啟動的時候只有直譯器進行解析,啟動完之後會根據執行狀態,然後依據執行模式(client、server模式,預設服務端預設都用server模式)來進行執行時編譯。
如何判斷為熱點**(多次呼叫的方法/迴圈體)
- 基於取樣熱點探測:
經常出現在棧頂,可判斷為熱點**,但對於迴圈體不好判斷
- 基於計數器熱點探測(hotspot就是用這種):
對呼叫次數加乙個計數器,呼叫方法(用 方法呼叫計數器)/迴圈體(應用 回邊計數器)此次到達上限,就會被編譯成機器碼。
備註:上面在沒編譯完成之前,都是用解析器執行位元組碼來執行程式,並且有些**編譯不成功就會退回用直譯器解析。
3 下面說下不同模式下編譯器做的優化
3.1 client模式(c1編譯器)優化
只針對耗時較高的做優化,佔記憶體小,主要有方法內聯、去虛擬化、冗餘消除等,做的區域性優化
1 方法內聯
多方法呼叫,引數傳來傳去,還要壓棧彈棧,這收他就把被呼叫的方法複製出來,避免頻繁彈棧出棧,例子如下:
*************************
int a(int val)
int b(int val)
優化後如下:
int a(int val)
*************************
其閾值設定引數如下:
-xx:compilethreshold
-- client,預設為1500;
-- server,預設為10000;
優化引數建議:
針對熱點方法,想要通過jit內聯優化來提公升效能的建議
1. 更小的方法體,jvm總是偏好更小的方法。
2. 盡量使用final、private、static修飾符,避免因為繼承而需要額外的型別檢查
3. 使用+printinlining引數校驗效果
2 去虛擬化
裝在.class的時候,發現類只有乙個實現類,那呼叫該類實現類的方法時,就直接進行內聯(對,就是1 的內聯 (╬▔皿▔)凸)來優化
3 冗餘消除
編譯時把多餘無用**摺疊或消除
3.2 server模式(c2編譯器)優化
占用記憶體多,大量優化,適合服務端,其優化有無用**消除、迴圈展開、迴圈表示式外提、消除公共子表示式、常量傳播、基本塊衝排序等,並且會做c1編譯器相關的優化
1 逃逸分析
c2優化的基礎,根據執行狀態來判斷方法中的變數是否會被外部讀取,如不會則認為此變數是不會逃逸的,那麼在編譯時會做標量替換、棧上分配和同步消除等優化。
- 方法逃逸:當前物件被外部方法引用
- 執行緒逃逸:當前物件被外部執行緒訪問
1.1 標量替換
替換為標量(基本的資料型別如int、long),通過標量替換將該物件分解,並在棧上分配記憶體
1.2 棧上分配
直接在棧上建立例項,而不用去堆上建立,這樣分配速度快,**方便
1.3 同步消除
如果發現物件不存在競爭,就會把他的鎖標識消除,這樣讀寫就不會有競爭
4 編譯期優化(早期優化)
優化語法糖,比如(不止三種):
1 泛型:編譯完成後替換為原生型別
2 條件編譯:比如發現必傳什麼值,就會把他預先處理好,如下:
if (false)
-- 比如上面發現if裡面必為false,就會直接消除掉這個**
3 自動裝箱/拆箱:會轉為基本資料型別
5 執行時優化(晚期優化)
hotspot採用解析器和編譯器並行策略,具體優化如下:
1 公共字表示式消除
發現這個表示式上面已經計算過了,下面直接用上面的結果值就行了,無需再次計算
2 陣列邊界檢查消除
發現**肯定不會越界,那直接不檢查邊界
3 方法內聯
4 逃逸分析
6 與c++比較
效能上比不過c++(因為他全是機器碼),但是可以做監控、熱點探測並且有選擇性地優化**
JVM 效能優化
最近發現服務cpu消耗不是很穩定,在150 600 之間不停跳動,以前沒有這種情況,check了一下,是old區記憶體不太夠導致每隔一小段時間cms gc了,old區記憶體不夠的主要原因是服務需要載入的資料變多了,使得old區頻繁gc 用 jmap heap pid 可以看到當old區佔比超過92 ...
jvm引數優化
堆記憶體優化 調整jvm啟動引數 xms xmx xx newsize xx maxnewsize,如調整初始堆記憶體和最大對記憶體 xms256m xmx512m。或者調整初始new generation的初始記憶體和最大記憶體 xx newsize 128m xx maxnewsize 128m...
jvm晚期優化
最具代表性的幾個優化技術 公共子表示式消除描述 如果乙個表示式e已經計算過了,並且從先前的計算到現在e中的所有變數的值都沒有發生變化,那麼e的這次出現就成為了公共子表示式 int d c b 12 a a b c 優化為int d e 12 a a e 優化為int d e 13 a 2陣列泛微檢查...