Skip to main content

Gas 分析 (Gas Profiling)

了解 Gas 消耗有助於優化你的 Move 程式碼並估算交易成本。Move 測試框架提供了內建工具來測量測試執行期間的 Gas 使用量。除此之外,還提供了一個特殊的工具 sui analyze-trace 用於更徹底地分析 Gas 使用量。

-s 顯示的統計數據僅反映計算單位 (computation units) —— 它們不包括存儲成本。此外,編譯器計算單位並不直接對應於實際的鏈上 Gas 費用;它們顯示相對的計算複雜度,有助於比較不同實作。要獲得實際 Gas 成本,請將你的套件發布到測試網並測量真實交易。

簡單測量:測試統計

使用 -s--statistics 標誌與 sui move test 一起使用,以查看每個測試的執行時間和 Gas 消耗:

sui move test -s

輸出顯示一個包含三列的表格:

Test Statistics:

┌────────────────────────────────────────────────────────┬────────────┬───────────────────────────┐
│ Test Name │ Time │ Gas Used │
├────────────────────────────────────────────────────────┼────────────┼───────────────────────────┤
│ book::my_module::test_simple_operation │ 0.003 │ 1 │
├────────────────────────────────────────────────────────┼────────────┼───────────────────────────┤
│ book::my_module::test_complex_operation │ 0.011 │ 59 │
├────────────────────────────────────────────────────────┼────────────┼───────────────────────────┤
│ book::my_module::test_with_objects │ 0.008 │ 25 │
└────────────────────────────────────────────────────────┴────────────┴───────────────────────────┘

Test result: OK. Total tests: 3; passed: 3; failed: 0
  • Test Name:測試函式的完全限定名稱
  • Time:執行時間 (秒)
  • Gas Used:測試消耗的 Gas 單位

CSV 輸出

為了進行程式化分析或匯入試算表,請使用 csv 選項:

sui move test -s csv

這會產生逗號分隔的輸出:

test_name,time_ns,gas_used
book::my_module::test_simple_operation,3381750,1
book::my_module::test_complex_operation,8454125,59
book::my_module::test_with_objects,3905625,25

時間以奈秒 (nanoseconds) 為單位,這允許在比較相似操作時進行更精確的測量。

Gas 限制

使用 -i--gas-limit 標誌來設定測試的最大 Gas 預算。超過此限制的測試將會超時:

sui move test -i 50

當測試超過 Gas 限制時的輸出:

[ PASS    ] book::my_module::test_simple_operation
[ TIMEOUT ] book::my_module::test_complex_operation
[ PASS ] book::my_module::test_with_objects

Test failures:

Failures in book::my_module:

┌── test_complex_operation ──────
│ Test timed out
└──────────────────

這對於以下情況很有用:

  • 識別昂貴的操作:找出消耗意外 Gas 量的測試
  • 強制執行 Gas 預算:確保關鍵路徑保持在可接受的限制內
  • 測試 Gas 耗盡:驗證你的程式碼是否正確處理 Gas 耗盡的情況 (參見 預期失敗)

比較實作

使用統計數據來比較不同實作之間的 Gas 消耗:

module book::comparison;

use std::unit_test::assert_eq;

public fun sum_loop(n: u64): u64 {
let mut sum = 0;
n.do!(|i| sum = sum + i);
sum
}

public fun sum_formula(n: u64): u64 {
n * (n - 1) / 2
}

#[test]
fun test_sum_loop() {
let result = sum_loop(100);
assert_eq!(result, 4950);
}

#[test]
fun test_sum_formula() {
let result = sum_formula(100);
assert_eq!(result, 4950);
}

使用統計數據執行揭示了差異:

sui move test -s comparison
┌────────────────────────────────────┬────────────┬───────────────────────────┐
│ Test Name │ Time │ Gas Used │
├────────────────────────────────────┼────────────┼───────────────────────────┤
│ book::comparison::test_sum_loop │ 0.005 │ 201 │
├────────────────────────────────────┼────────────┼───────────────────────────┤
│ book::comparison::test_sum_formula │ 0.002 │ 3 │
└────────────────────────────────────┴────────────┴───────────────────────────┘

追蹤分析 (Trace Analysis)

為了更深入的剖析,你可以從測試中生成執行追蹤,並使用 speedscope 將其視覺化。這會顯示按函式調用細分的 Gas 消耗火焰圖 (flamegraph),使你可以輕鬆找出 Gas 實際花費在哪裡。

步驟 1:生成追蹤

使用 --trace 標誌執行測試以產生追蹤檔案:

sui move test --trace

追蹤檔案會寫入套件構建資料夾內的 traces/ 目錄中。

步驟 2:生成 Gas 設定檔 (Gas Profile)

使用 sui analyze-tracegas-profile 子命令將追蹤轉換為設定檔:

sui analyze-trace -p traces/<TRACE_FILE> gas-profile

這會在當前目錄中輸出一個 gas_profile_<TRACE_FILE>.json 檔案。你可以使用 -o 標誌指定不同的輸出目錄:

sui analyze-trace -p traces/<TRACE_FILE> gas-profile -o ./profiles

步驟 3:使用 Speedscope 視覺化

安裝 speedscope 並打開設定檔:

npm install -g speedscope
speedscope gas_profile_<TRACE_FILE>.json

Speedscope 提供三種視圖:

  • Time Order (時間順序):按調用順序從左到右顯示調用堆疊。條形寬度對應於 Gas 消耗。
  • Left Heavy (左側加重):將重複的調用分組在一起,按總 Gas 消耗排序 —— 對於查找最昂貴的程式碼路徑很有用。
  • Sandwich (三明治):列出每個函式的 Gas 消耗,包含 Total (包括被調用的函式) 和 Self (僅函式本身) 列。

延伸閱讀