
1. 編譯閾值
1.1. 一旦代碼執行到一定次數,就達到了它的編譯閾值,編譯器就會認為它有足夠的資訊來編譯代碼
1.2. 在當前的JVM中,優化閾值的意義不大
1.2.1. 從JDK 7以及更早期遺留下來的
1.3. -XX:CompileThreshold=N
1.3.1. 當禁用分層編譯時有效
1.3.2. 默認值是10 00
1.3.3. 降低這個標志的值可以改善使用C2編譯器的應用程式的啟動時間
1.3.3.1. 可能會導致一些方法被編譯,而這些方法本來是永遠都不會被編譯的
1.4. 編譯器使用的計數器會隨著方法和回圈的執行增加計數,但是它們也會隨著時間的推移而減少
1.4.1. 計數器只是方法或回圈最近熱度的相對度量
1.4.2. 有些頻繁執行的代碼可能永遠不會被C2編譯器編譯,即使這個程式永遠運行
1.5. -XX:Tier3InvocationThreshold=N
1.5.1. 默認值200
1.5.2. 讓C1編譯器更快地編譯方法
1.6. -XX:Tier4InvocationThreshold=N
1.6.1. 默認值5000
1.6.2. 讓C2編譯器更快地編譯方法
2. 編譯執行緒
2.1. 呼叫次數更多的方法有更高的優先級
2.1.1. 可以確保最重要的方法先被編譯
2.2. 需要編譯的代碼會放在編譯佇列中
2.2.1. 佇列中的代碼越多,應用程式達到最佳性能需要的時間就越長
2.3. C1編譯器和C2編譯器有不同的佇列
2.3.1. 對于放在編譯佇列中的方法,編譯是異步進行的
2.4. -XX:CICompilerCount=N
2.4.1. JVM用來處理佇列的總執行緒數
2.4.2. 三分之一(至少一個)用來處理C1編譯器佇列
2.4.3. 剩下的執行緒(也是至少一個)用來處理C2編譯器佇列
2.4.4. 如果分層編譯被禁用,則只啟動給定數量的C2編譯器執行緒
2.5. 在Docker容器中運行舊版本的JDK 8會導致自動優化出問題
2.5.1. 需要手動將此標志設定為需要的值
2.6. 可用的CPU有限,較少的執行緒競爭系統資源對性能有益
2.6.1. 減少執行緒數量可以幫助提升整體吞吐量
2.6.2. 代價是預熱期會持續更長時間
2.7. -XX:+BackgroundCompilation
2.7.1. 默認值為true
2.7.1.1. 意味著佇列會進行異步處理
2.7.2. 設定為false
2.7.2.1. 一旦方法可以被編譯,想要執行它的代碼就會等待,直到方法實際上完成編譯,而不是繼續在解釋器中執行
2.8. -Xbatch
2.8.1. 可以禁用后臺編譯
3. 行內
3.1. 對性能提升非常重要
3.1.1. 編譯器能做的最有利的優化,特別是對于屬性封裝良好的面向物件代碼
3.1.2. 不要害怕小方法,特別是getter和setter,因為它們很容易被行內
3.2. -XX:-Inline
3.2.1. 默認啟用
3.3. -XX:MaxFreqInlineSize=N
3.3.1. 頻繁行內
3.3.2. 默認325位元組
3.3.3. 一個方法因為呼叫得很頻繁而可以被行內,那么只有在它的位元組碼小于325位元組時
3.4. -XX:MaxInlineSize=N
3.4.1. 正常行內
3.4.2. 默認35位元組
3.4.3. 只有在位元組碼小于35位元組時,方法才會被行內
3.4.4. 它可能會縮短測驗所需的預熱時間,但是不太可能對一個長期運行的應用程式產生很大影響
3.5. 注意事項
3.5.1. 將MaxInlineSize的值設定為大于35位元組,意味著一個方法在首次呼叫時可能就被行內了
3.5.2. 如果方法經常被呼叫,就說明它的性能重要得多,它總歸是會被行內的(假設它小于325位元組)
4. 逃逸分析
4.1. 編譯器能夠進行的最復雜的優化
4.1.1. 常導致微基準測驗出錯
4.1.2. 可以產生更快的代碼,但復雜回圈結構和大型方法限制了有效性
4.2. -XX:+DoEscapeAnalysis
4.2.1. 默認值是true
4.2.2. C2編譯器會進行大幅度的優化
4.2.3. 在極少數情況下,它會出錯
4.2.4. 禁用這個特性可能會帶來更穩定的代碼
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/545904.html
標籤:Java
上一篇:讀Java性能權威指南(第2版)筆記08_即時編譯器中
下一篇:配置完maven環境變數后cmd輸入mvn -v命令后報錯:NB: JAVA_HOME should point to a JDK not a JRE
