GraalVM中的多層編譯優點

banq發表於2021-04-22

GraalVM 21.1引入了一項新功能,稱為多層編譯,適用於在Truffle上實現的語言。多層模式改善了預熱行為,對於包含大型程式碼庫的程式特別有用,可將啟動時間縮短30%-50%。多層模式下的核心思想是將呼叫目標的編譯分為兩層-更快的第一層和較慢的第二層。第一層編譯執行的最佳化較少,但是可以快速獲得,因此可以幫助程式更快地啟動。第二層編譯的速度較慢,因為它們會進行更多的最佳化,但它們可以確保程式最終達到峰值效能。從21.1版本開始,GraalVM中的多層編譯預設情況下處於開啟狀態。
有幾種實驗選項可以控制多層編譯的行為。通常,預設值最有效,但是喜歡冒險的使用者可能希望在其工作負載上嘗試以下選項:
  • MultiTier-此選項啟用多層編譯。自GraalVM 21.1起,預設情況下為true。
  • FirstTierCompilationThreshold —在計劃進行第一層編譯之前在呼叫目標中執行的呼叫或迴圈迭代的次數。
  • LastTierCompilationThreshold-在計劃將其安排用於第二層編譯之前,在呼叫目標中執行的呼叫或迴圈迭代的次數。
  • FirstTierInliningPolicy-確定在第一層編譯中應使用哪種內聯策略。預設情況下,在GraalVM 21.1中將其設定為TrivialOnly,這意味著僅內聯小的方法。
  • FirstTierUseEconomy —此選項確定快速編譯是否應使用最少數量的最佳化。預設情況下為true。
  • FirstTierBackedgeCounts-此選項確定是否應將迴圈迭代計入第二層編譯閾值。預設情況下為true。
  • SingleTierCompilationThreshold-此選項確定關閉多層編譯時的編譯閾值。它具有與CompilationThreshold相同的效果,後者已不建議使用-它已有效地重新命名為此選項。

 

縮短啟動時間
為了演示多層編譯的好處,我們首先介紹一個預熱曲線的概念。程式內部執行的相同工作量越長,程式趨向於變得越來越快,這是因為程式程式碼最初並未進行編譯,而是在VM中執行程式時進行編譯的。程式越快越快,預熱就越好。預熱曲線是一種表徵程式執行速度如何隨時間變化的方式。一般而言,預熱曲線繪製了效能指標如何隨程式的每次重複而變化。在本文的大部分內容中,效能指標將是自VM啟動以來的總執行時間。總執行時間越短,預熱效果越好。
在多層執行中,程式花費大約33%的時間到達第一次迭代的末尾,而花費大約43%的時間到達第十次迭代的末尾。快速的第一層編譯可更快地減小預熱曲線的斜率,這意味著完成每次迭代所需的時間更少。單層編譯最終還會逐漸減小曲線的斜率。
 

“一次性”指標
“一次性”指標是VM啟動到工作負載的第一次重複結束之間的時間量。
“一次性”度量特別有趣,因為它在執行開始時捕獲了動態。在許多實際場景中,我們對短期執行的程式(例如命令列工具或單個單元測試執行)感興趣。在其他情況下,我們希望該程式儘早達到良好的執行效能,即使它在很晚之後達到最佳的峰值效能也是如此。
定義了“一次性”度量標準的概念後,現在讓我們透過檢視“一次性”度量標準而不是預熱曲線來檢查其他幾種GraalVM語言的預熱行為:
在“一次性”度量標準上,多層執行比單層執行快約33%;
多層TruffleRuby的“一次性”指標比MRI快2.75倍;
 

編譯時間
在預熱動力學中起作用的另一個因素是編譯時間。編譯器速度越快,程式就越早達到峰值效能。
編譯效能的提高將預熱曲線上的點(包括峰點)移到左側。
通常,有兩種方法可以使最佳化編譯器更快。第一種方法是檢查編譯器的實現,並改善程式碼在編譯器效能欠佳的位置。假設程式不是最佳程式,則可以最佳化任何程式。第二種方法是減少編譯器所做的最佳化量。雖然這可以使最佳化編譯器的速度更快,但也會降低峰值效能。

更多點選標題

 

相關文章