jvm之方法内联优化
前言
在日常中工作中,我們時不時會代碼進行一些優化,比如用新的算法,簡化計算邏輯,減少計算量等。對于java程序來說,除了開發者本身對代碼優化之外,還有一個"人"也在背后默默的優化我們的代碼,這個"人"就是jvm。jvm會幫我們分析出熱點代碼,優化代碼邏輯。其中jvm最常做的優化之一就是:方法內聯優化。
方法內聯
什么是方法內聯?又可以叫做函數內聯,java中方法可等同于其它語言中的函數。關于方法內聯維基百科上面解釋是:
在計算機科學中,內聯函數(有時稱作在線函數或編譯時期展開函數)是一種編程語言結構,用來建議編譯器對一些特殊函數進行內聯擴展(有時稱作在線擴展);也就是說建議編譯器將指定的函數體插入并取代每一處調用該函數的地方(上下文),從而節省了每次調用函數帶來的額外時間開支。
簡單通俗的講就是把方法內部調用的其它方法的邏輯,嵌入到自身的方法中去,變成自身的一部分,之后不再調用該方法,從而節省調用函數帶來的額外開支。
函數調用開銷
之所以出現方法內聯是因為函數調用除了執行自身邏輯的開銷外,還有一些不為人知的額外開銷。這部分額外的開銷主要來自方法棧幀的生成、參數字段的壓入、棧幀的彈出、還有指令執行地址的跳轉。比如有下面這樣代碼:
public static void function_A(int a, int b){
//do something
function_B(a,b);
}
public static void function_B(int c, int d){
//do something
}
public static void main(String[] args){
function_A(1,2);
}
則代碼的執行過程如下:
所以如果java中方法調用嵌套過多或者方法過多,這種額外的開銷就越多。
試想一下想get/set這種方法調用:
public int getI() {
return i;
}
public void setI(int i) {
this.i = i;
}
很可能自身執行邏輯的開銷還比不上為了調用這個方法的額外開鎖。如果類似的方法被頻繁的調用,則真正相對執行效率就會很低,雖然這類方法的執行時間很短。這也是為什么jvm會在熱點代碼中執行方法內聯的原因,這樣的話就可以省去調用調用函數帶來的額外開支。
這里舉個內聯的可能形式:
public int add(int a, int b , int c, int d){
return add(a, b) + add(c, d);
}
public int add(int a, int b){
return a + b;
}
內聯之后:
public int add(int a, int b , int c, int d){
return a + b + c + d;
}
這樣除了本身的相加邏輯的開銷,比內聯前減少了二次調用函數帶來的額外開銷。
內聯條件
一個方法如果滿足以下條件就很可能被jvm內聯。
1、熱點代碼。 如果一個方法的執行頻率很高就表示優化的潛在價值就越大。那代碼執行多少次才能確定為熱點代碼?這是根據編譯器的編譯模式來決定的。如果是客戶端編譯模式則次數是1500,服務端編譯模式是10000。次數的大小可以通過-XX:CompileThreshold來調整。
2、方法體不能太大。jvm中被內聯的方法會編譯成機器碼放在code cache中。如果方法體太大,則能緩存熱點方法就少,反而會影響性能。
3、如果希望方法被內聯,盡量用private、static、final修飾,這樣jvm可以直接內聯。如果是public、protected修飾方法jvm則需要進行類型判斷,因為這些方法可以被子類繼承和覆蓋,jvm需要判斷內聯究竟內聯是父類還是其中某個子類的方法。
所以了解jvm方法內聯機制之后,會有助于我們工作中寫出能讓jvm更容易優化的代碼,有助于提升程序的性能。
總結
以上是生活随笔為你收集整理的jvm之方法内联优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2108年计算机二级考试时间,计算机二级
- 下一篇: spring项目搭建云服务器,Sprin