分層編譯和逃逸分析在1.8中是預設是開啟的;
即時編譯(just-in-time compilation,jit)是一種通過在執行時將位元組碼翻譯為機器碼,從而改善位元組碼編譯語言效能的技術。在hotspot實現中有多種選擇:c1、c2和c1+c2,分別對應client、server和分層編譯。
1、c1編譯速度快,優化方式比較保守;
2、c2編譯速度慢,優化方式比較激進;
3、c1+c2在開始階段採用c1編譯,當**執行到一定熱度之後採用g2重新編譯;
編譯閾值:
編譯優化只有在**執行足夠次數才會進行優化,在執行的過程中不斷收集各種資料作為優化決策;所以在優化完成之前,user還是在堆中分配的;
-xx:compilethreshold 進行閾值的設定;
除了標準編譯還有一種叫做osr(on stack replacement)棧上替換的編譯,對方法中迴圈執行的**進行優化,也需要乙個閾值;
-xx:compilethreshold = 10000 觸發編譯優化閾值
-xx:onstackreplacepercentage = 140 棧上替換百分比
-xx:interpreterprofilepercentage = 33 編譯內容百分比
osr trigger = (compilethreshold * (onstackreplacepercentage - interpreterprofilepercentage)) / 100 = 10700
jit編譯在預設情況是非同步進行的,當觸發某方法或某**塊的優化時,先將其放入編譯佇列,然後由編譯執行緒進行編譯,編譯之後的**放在codecache中,codecache的大小也是有限的,compilethreshold設定的太低,jit會將一大堆執行不那麼頻繁的**進行編譯,並放入codecache,導致之後真正執行頻繁的**沒有足夠的空間存放。
逃逸分析:通過動態分析物件的作用域,為其他優化手段如棧上分配、標量替換和同步消除等提供依據,發生逃逸行為的情況有:
方法逃逸:乙個物件在方法中定義之後,作為引數傳遞;
執行緒逃逸:類變數或例項變數可能被其他執行緒訪問到;
同步消除:如果確定物件不會發生執行緒問題,即使新增了同步也會被消除,預設是開啟的,引數是-xx:=eliminatelocks;
標量替換:標量是不可分割的量,可以繼續分解的叫聚合量;
如果發現乙個物件不會被外部訪問並且該物件可以被拆散,那麼經過優化之後,並不直接生成物件,而是在棧上建立成員變數;
-xx:+eliminateallocations可以開啟標量替換, -xx:+printeliminateallocations檢視標量替換情況。
棧上分配:理論上的概念是在棧上分配物件,但是現在是通過標量替換的方法實現的;
逃逸分析 Escape Analysis)
什麼是逃逸?逃逸是指在某個方法之內置立的物件,除了在方法體之內被引用之外,還在方法體之外被其它變數引用到 這樣帶來的後果是在該方法執行完畢之後,該方法中建立的物件將無法被gc 由於其被其它變數引用。正常的方法呼叫中,方法體中建立的物件將在執行完畢之後,將 其中建立的物件 故由於無法 即成為逃逸。無逃...
golang逃逸分析
帶gc語言給我們程式的編寫帶來了極大的便利,但是與此同時遮蔽了很多底層的細節,比如乙個物件是在棧上分配還是在堆上分配。對於普通的 來說雖然不需要關心這麼多,但是作為強迫症程式猿,還是希望能讓自己寫出來的 效能最優,所以還是需要了解什麼是逃逸,以及如何判斷是否發生了逃逸。首先需要知道,我們說的堆和棧是...
Go記憶體逃逸分析
分析記憶體逃逸之前要搞清楚一件事 我們編寫的程式中的函式和區域性變數是存放在棧上的 補充一點堆上儲存的資料的指標 是存放在棧上的 因為指標的大小是可以提前預知的 還有就是go的基本型別也是存放在棧內的 而其餘的變數是存在堆上的,棧是由作業系統層面控制 進行記憶體空間的釋放 堆預設是程式控制的 像c ...