- 適用於 JDK 23 的 GraalVM (最新版)
- 適用於 JDK 24 的 GraalVM (搶先體驗版)
- 適用於 JDK 21 的 GraalVM
- 適用於 JDK 17 的 GraalVM
- 封存
- 開發建置版
- Truffle 語言實作框架
- Truffle 分支檢測
- 動態物件模型
- 靜態物件模型
- 解譯器程式碼的主機最佳化
- Truffle 的函式內聯方法
- 分析 Truffle 解譯器效能
- Truffle Interop 2.0
- 語言實作
- 使用 Truffle 實作新語言
- Truffle 語言和工具遷移至 Java 模組
- Truffle 原生函式介面
- 最佳化 Truffle 解譯器
- 選項
- 堆疊上替換 (On-Stack Replacement)
- Truffle 字串指南
- 特化直方圖
- 測試 DSL 特化
- 基於 Polyglot API 的 TCK
- Truffle 的編譯佇列方法
- Truffle 函式庫指南
- Truffle AOT 概觀
- Truffle AOT 編譯
- 輔助引擎快取
- Truffle 語言安全點教學
- 單態化
- 分割演算法
- 單態化使用案例
- 向執行階段回報多型特化
分析 Truffle 解譯器效能
使用 Truffle 編寫的解譯器效能分析工具不虞匱乏。在 JVM 模式下執行時,您可以使用標準的 JVM 工具,例如 VisualVM、Java Flight Recorder 和 Oracle Developer Studio。在原生映像檔中執行時,您可以使用 Valgrind 工具套件中的 callgrind
,以及其他系統工具,例如 strace
。 作為在 GraalVM 上執行的語言,您也可以使用其他 GraalVM 工具。 對於足夠廣泛的效能分析定義,您也可以使用 Ideal Graph Visualizer (IGV) 和 C1 Visualizer 來檢查編譯器輸出。
本指南的重點不是如何使用每個工具,而是針對如何從工具中擷取最有用的資訊提出建議,並假設您對這些工具的基本用法有一定了解。
使用 CPU 取樣器分析效能 #
分析應用程式層級 (例如,找出大部分時間花費在哪些客語函式中) 的最簡單方法是使用 CPU 取樣器,它是 /tools
套件的一部分,也是 GraalVM 的一部分。只需將 --cpusampler
傳遞到您的語言啟動器即可
language-launcher --cpusampler --cpusampler.Delay=MILLISECONDS -e 'p :hello'
您可能需要使用 --cpusampler.Delay=MILLISECONDS
的取樣延遲,以便在暖機後才開始分析效能。這樣一來,您可以輕鬆識別哪些函式已編譯,哪些函式尚未編譯,但仍需花費大量時間來執行。
如需更多 --cpusampler
選項,請參閱 language-launcher --help:tools
。
從 CPU 取樣器取得編譯資料 #
CPU 取樣器不會顯示在編譯程式碼中花費的時間相關資訊。這至少在某種程度上是受到多層編譯導入的影響,因為「已編譯程式碼」的描述性不足。使用 --cpusampler.ShowTiers
選項可讓使用者控制是否要查看編譯資料,以及明確指定應在報表中考慮哪些編譯層級。例如,新增 --cpusampler.ShowTiers=true
將顯示執行期間遇到的所有編譯層級,如下所示。
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Sampling Histogram. Recorded 553 samples with period 10ms.
Self Time: Time spent on the top of the stack.
Total Time: Time spent somewhere on the stack.
T0: Percent of time spent in interpreter.
T1: Percent of time spent in code compiled by tier 1 compiler.
T2: Percent of time spent in code compiled by tier 2 compiler.
-----------------------------------------------------------------------------------------------------------------------------------------------------------
Thread[main,5,main]
Name || Total Time | T0 | T1 | T2 || Self Time | T0 | T1 | T2 || Location
-----------------------------------------------------------------------------------------------------------------------------------------------------------
accept || 4860ms 87.9% | 31.1% | 18.3% | 50.6% || 4860ms 87.9% | 31.1% | 18.3% | 50.6% || ../primes.js~13-22:191-419
:program || 5530ms 100.0% | 100.0% | 0.0% | 0.0% || 360ms 6.5% | 100.0% | 0.0% | 0.0% || ../primes.js~1-46:0-982
next || 5150ms 93.1% | 41.7% | 39.4% | 18.8% || 190ms 3.4% | 100.0% | 0.0% | 0.0% || ../primes.js~31-37:537-737
DivisibleByFilter || 190ms 3.4% | 89.5% | 10.5% | 0.0% || 100ms 1.8% | 80.0% | 20.0% | 0.0% || ../primes.js~7-23:66-421
AcceptFilter || 30ms 0.5% | 100.0% | 0.0% | 0.0% || 20ms 0.4% | 100.0% | 0.0% | 0.0% || ../primes.js~1-5:0-63
Primes || 40ms 0.7% | 100.0% | 0.0% | 0.0% || 0ms 0.0% | 0.0% | 0.0% | 0.0% || ../primes.js~25-38:424-739
-----------------------------------------------------------------------------------------------------------------------------------------------------------
或者,--cpusampler.ShowTiers=0,2
將僅顯示解譯時間和第二層已編譯程式碼中花費的時間,如下所示。
-----------------------------------------------------------------------------------------------------------------------------------------
Sampling Histogram. Recorded 620 samples with period 10ms.
Self Time: Time spent on the top of the stack.
Total Time: Time spent somewhere on the stack.
T0: Percent of time spent in interpreter.
T2: Percent of time spent in code compiled by tier 2 compiler.
-----------------------------------------------------------------------------------------------------------------------------------------
Thread[main,5,main]
Name || Total Time | T0 | T2 || Self Time | T0 | T2 || Location
-----------------------------------------------------------------------------------------------------------------------------------------
accept || 5510ms 88.9% | 30.9% | 52.3% || 5510ms 88.9% | 30.9% | 52.3% || ../primes.js~13-22:191-419
:program || 6200ms 100.0% | 100.0% | 0.0% || 320ms 5.2% | 100.0% | 0.0% || ../primes.js~1-46:0-982
next || 5870ms 94.7% | 37.3% | 20.6% || 190ms 3.1% | 89.5% | 10.5% || ../primes.js~31-37:537-737
DivisibleByFilter || 330ms 5.3% | 100.0% | 0.0% || 170ms 2.7% | 100.0% | 0.0% || ../primes.js~7-23:66-421
AcceptFilter || 20ms 0.3% | 100.0% | 0.0% || 10ms 0.2% | 100.0% | 0.0% || ../primes.js~1-5:0-63
Primes || 20ms 0.3% | 100.0% | 0.0% || 0ms 0.0% | 0.0% | 0.0% || ../primes.js~25-38:424-739
-----------------------------------------------------------------------------------------------------------------------------------------
從 CPU 取樣器建立火焰圖 #
CPUSampler 的直方圖輸出可能非常龐大,使其難以分析。此外,由於是平面格式,因此無法分析呼叫圖,因為該資訊根本未編碼在輸出中。火焰圖會顯示整個呼叫圖。其結構使得更容易查看應用程式的時間花費在哪裡。
建立火焰圖是一個多階段過程。首先,我們需要使用 JSON 格式器分析應用程式的效能
language-launcher --cpusampler --cpusampler.SampleInternal --cpusampler.Output=json -e 'p :hello' > simple-app.json
如果您想要分析內部來源 (例如標準函式庫函式) 的效能,請使用 --cpusampler.SampleInternal=true
選項。
JSON 格式器會編碼直方圖格式中無法使用的呼叫圖資訊。但是,若要從此輸出建立火焰圖,我們需要將其轉換為將呼叫堆疊樣本摺疊成單行的格式。這可以使用 Benoit Daloze 的 FlameGraph 分支中的 stackcollapse-graalvm.rb 來完成。
如果您尚未這麼做,您應該將 FlameGraph 的這個分支複製到父目錄中。現在,您可以執行腳本以轉換輸出,並將其導向至將產生 SVG 資料的腳本
../FlameGraph/stackcollapse-graalvm.rb simple-app.json | ../FlameGraph/flamegraph.pl > simple-app.svg
此時,您應該在基於 Chromium 的網路瀏覽器中開啟 SVG 檔案。您的系統可能會將不同的影像處理應用程式設定為 SVG 檔案的預設應用程式。雖然在此類應用程式中載入檔案可能會呈現圖形,但它可能無法處理火焰圖的互動式元件。Firefox 也可能有效,但基於 Chromium 的瀏覽器目前似乎對火焰圖檔案有更好的支援和效能。
使用 Oracle Developer Studio 分析效能 #
Oracle Developer Studio 包含一個可以與 GraalVM 一起使用的 效能分析器。Developer Studio 可以從 OTN 下載,而撰寫時的目前版本 (12.6) 提供永久免費的生產使用授權和商業應用程式開發授權。
使用 Developer Studio 效能分析器非常簡單。將 Developer Studio 二進位檔的路徑包含在您的 PATH
中,然後在您的正常命令列前面加上 collect
。例如
collect js mybenchmark.js
完成後,將會建立一個「實驗」(.er) 目錄,其中包含命令執行的效能分析資料,預設為 test.1.er
。若要檢視效能分析結果,請使用 analyzer
工具
analyzer test.1.er
analyzer
GUI 可讓您以多種不同的方式檢視擷取的效能分析資訊,例如,應用程式的時間軸、平面函式清單、呼叫樹狀結構、火焰圖等等。還有一個命令列工具 er_print
,可用於以文字形式輸出效能分析資訊,以進行進一步分析。
如需完整詳細資訊,請參閱 效能分析器 文件。