三種提升Java程式碼效能的簡單技巧 - levelup

banq發表於2021-05-19

優先考慮組成而不是繼承、盡一切可能內聯方法、建立小方法是簡單的提升程式碼效能方法:
大多數開發人員會遇到有關Java效能的問題。大多數開發人員不知道正確的答案。這裡提供三種簡單最佳化技巧:
 

1.內聯Java
內聯方法是JIT編譯器使用的一種最佳化技術。研究表明,其加速比高達93倍。
哪些方法易於內聯?靜態,私有,最終final方法很容易內聯;虛擬呼叫如果是monomorphic單態呼叫,則可以內聯。方法呼叫預設是虛擬的,這意味著您需要搜尋vtable以獲得方法引用,透過一種多型性,您可以為一個方法擁有多個呼叫入口。
可以內聯哪些方法?公開public方法,但必須滿足一些標準方法。方法大小是一項標準。在Linux 64位上,將大小定為325位元組以下的方法可以內聯。小型方法可以內聯,而大型方法則不能。
JIT編譯器如何最佳化單態呼叫?使用內聯快取。預設情況下,只有單態呼叫。發生子類呼叫時,它會分支為megamorphic巨形呼叫。
什麼是巨形呼叫?子類中的重寫方法會導致巨形呼叫。呼叫vtable,就不會產生包含所有可能的方法呼叫的表。
內聯可以為您做什麼?為什麼單態呼叫比多型呼叫更好?讓我們來看看:我們可以使用此基準測試方法的大小最佳化。為了測試方法呼叫的內聯快取,我們可以使用這裡的基準。

不能內聯哪些方法?
如何搜尋未最佳化的方法?使用jarScan限制為325個位元組。該限制可能因平臺而異。此限制是大方法的指標。這是一個大方法的示例。

./jarScan.sh --mode=maxMethodSize --limit=325 ./yourproject.jar
"com.yourproject","HugeClass","com.yourproject.HugeClass$Builder",637

 

2.組合如何擊敗繼承
Bimorphic雙態呼叫在行內快取中獲得匹配。我們可以看到,雙態使操作次數提高了35%。
做簡單instanceof可以改善內聯快取中的點選率。最佳化使吞吐量提高了30%。
是什麼使巨形呼叫的執行效果不佳?線上快取中未命中。轉到vtable。遍歷vtable會降低執行速度。
這是多型性的主要問題:

像Java這樣的程式語言提供了多型的便利,作為構造模組化和可重用軟體的方法之一。這種語言選擇自然是有代價的,因為沒有硬體支援虛擬呼叫,因此執行時必須模仿這種行為。— AlekseyShipilёv
單態的效能比雙態的效能高4倍。
透過基準測速表明:內聯方法的效能更好。多型方法的效能比單態方法差。
我們可以瞭解到為什麼合成勝過繼承。繼承為vtable帶來了更多方法,從而導致效能瓶頸。力爭使用較小的方法,這些方法可以內聯並表現更好。
 

 

3.小方法快大方法慢?
讓我們從一開始就嘗試我們的基準測試。較小的方法的效能要好26倍。如果我們不內聯較小的方法怎麼辦?內聯方法如何影響平均時間?內聯方法的效能比同類方法好2倍。
我們可以從這些基準中學到什麼?盡一切可能使您的方法內聯。建立較小的方法,並減少專案中現有的較大方法。吞吐量效能取決於大小。小型內聯方法平均快2倍。

 

相關文章