golang-benchmark

golang-benchmark

熱門

Golang 基準測試、效能剖析與效能測量。當你需要撰寫、執行或比較 Go 基準測試、使用 pprof 剖析熱點路徑、解讀 CPU/記憶體/追蹤剖析結果、使用 benchstat 分析結果、設定 CI 基準測試回歸偵測,或使用 Prometheus 執行時期指標調查生產環境效能時使用。也適用於開發者需要對特定效能指標進行深入分析時——此技能提供測量方法論,而 `samber/cc-skills-golang@golang-performance` 則提供最佳化模式。

2261星標
150分支
更新於 2026/6/6
SKILL.md
readonlyread-only
name
golang-benchmark
description

Golang 基準測試、效能剖析與效能測量。當你需要撰寫、執行或比較 Go 基準測試、使用 pprof 剖析熱點路徑、解讀 CPU/記憶體/追蹤剖析結果、使用 benchstat 分析結果、設定 CI 基準測試回歸偵測,或使用 Prometheus 執行時期指標調查生產環境效能時使用。也適用於開發者需要對特定效能指標進行深入分析時——此技能提供測量方法論,而 `samber/cc-skills-golang@golang-performance` 則提供最佳化模式。

角色設定: 你是一位 Go 效能測量工程師。你絕不會從單次基準測試結果中得出結論——統計嚴謹性與受控條件是任何最佳化決策的前提。

思考模式: 在基準測試分析、剖析結果解讀與效能比較任務中使用 ultrathink。深度推理可避免誤判剖析資料,並確保得出統計上可靠的結論。

相依套件:

  • benchstat:go install golang.org/x/perf/cmd/benchstat@latest

Go 基準測試與效能測量

沒有測量就沒有效能改善——若能測量,就能改善。

此技能涵蓋完整的測量工作流程:撰寫基準測試、執行它、剖析結果、以統計嚴謹性比較前後差異,並在 CI 中追蹤回歸。若需在測量後套用最佳化模式,請參閱 samber/cc-skills-golang@golang-performance 技能。若需在執行中的服務上設定 pprof,請參閱 samber/cc-skills-golang@golang-troubleshooting 技能。

撰寫基準測試

b.Loop()(Go 1.24+)——建議使用

對於 Go 1.24+,新基準測試建議使用 b.Loop()。它只計時迴圈本體,並保持函式參數/回傳值存活,減少死碼消除的錯誤。

func BenchmarkParse(b *testing.B) {
    data := loadFixture("large.json") // 設定——排除在計時之外
    for b.Loop() {
        Parse(data)  // 編譯器無法消除此呼叫
    }
}

傳統的 b.N 迴圈仍可編譯,且在保留現有基準測試或支援 Go <1.24 時可以繼續使用。但較容易出錯:設定可能需要 b.ResetTimer(),且若編譯器可消除工作,結果可能需要一個 sink。Go 1.26 修復了早期 b.Loop() 內聯限制——1.24–1.25 上的基準測試已受益於 b.Loop(),但可能錯過 1.26 提供的內聯最佳化。

記憶體追蹤

func BenchmarkAlloc(b *testing.B) {
    b.ReportAllocs() // 或使用 -benchmem 旗標執行
    var sink []byte
    for b.Loop() {
        sink = make([]byte, 1024)
    }
    _ = sink
}

b.ReportMetric() 可加入自訂指標(例如吞吐量):

b.ReportMetric(float64(totalBytes)/b.Elapsed().Seconds(), "bytes/s") // b.Elapsed() 僅在 b.Loop() 內有效

子基準測試與表格驅動

func BenchmarkEncode(b *testing.B) {
    for _, size := range []int{64, 256, 4096} {
        b.Run(fmt.Sprintf("size=%d", size), func(b *testing.B) {
            data := make([]byte, size)
            for b.Loop() {
                Encode(data)
            }
        })
    }
}

執行基準測試

go test -bench=BenchmarkEncode -benchmem -count=10 ./pkg/... | tee bench.txt
旗標 用途
-bench=. 執行所有基準測試(正規表達式過濾)
-benchmem 報告配置量(B/op, allocs/op)
-count=10 執行 10 次以達統計顯著性
-benchtime=3s 每次基準測試最小時間(預設 1s)
-cpu=1,2,4 以不同 GOMAXPROCS 值執行
-cpuprofile=cpu.prof 寫入 CPU 剖析檔
-memprofile=mem.prof 寫入記憶體剖析檔
-trace=trace.out 寫入執行追蹤檔

輸出格式: BenchmarkEncode/size=64-8 5000000 230.5 ns/op 128 B/op 2 allocs/op——-8 後綴是 GOMAXPROCS,ns/op 是每次操作時間,B/op 是每次操作配置的位元組數,allocs/op 是每次操作的堆積配置次數。

在提交中記錄結果

當變更對效能有可測量的影響時,將 benchstat 輸出貼在提交說明中。這記錄了為何進行最佳化,防止未來讀者還原它,並讓審查者無需重新執行基準測試即可驗證主張。

提交格式:

perf(parser): reduce Parse allocations 50% with sync.Pool

Replace per-call []byte allocation with a pooled buffer.

goos: linux / goarch: amd64 / cpu: AMD Ryzen 9 5950X
          │    old     │              new               │
          │  sec/op    │  sec/op     vs base            │
Parse-32    4.592µ ± 2%  3.041µ ± 1%  -33.78% (p=0.000 n=10)

          │   old    │             new              │
          │   B/op   │   B/op     vs base           │
Parse-32   1.024Ki ± 0%  0.512Ki ± 0%  -50.00% (p=0.000 n=10)

          │ old  │            new             │
          │ allocs/op │ allocs/op  vs base    │
Parse-32   12.00 ± 0%   6.000 ± 0%  -50.00% (p=0.000 n=10)

規則:

  • 只包含直接受變更影響的基準測試——刪除不相關的行
  • 絕不貼上帶有 ~(無統計顯著性)的結果——無法主張改善
  • 包含硬體環境行(goos/goarch/cpu)以便結果可重現
  • 僅效能變更使用 perf(scope): 提交類型

從基準測試進行剖析

直接從基準測試執行產生剖析檔——無需 HTTP 伺服器:

# CPU 剖析
go test -bench=BenchmarkParse -cpuprofile=cpu.prof ./pkg/parser
go tool pprof cpu.prof

# 記憶體剖析(alloc_objects 顯示 GC 流失,inuse_space 顯示記憶體洩漏)
go test -bench=BenchmarkParse -memprofile=mem.prof ./pkg/parser
go tool pprof -alloc_objects mem.prof

# 執行追蹤
go test -bench=BenchmarkParse -trace=trace.out ./pkg/parser
go tool trace trace.out

完整的 pprof CLI 參考(所有指令、非互動模式、剖析解讀),請參閱 pprof 參考。執行追蹤解讀請參閱 追蹤參考。統計比較請參閱 benchstat 參考

參考檔案

  • pprof 參考 — CPU、記憶體與 goroutine 剖析的互動與非互動分析。完整的 CLI 指令、剖析類型(CPU vs alloc*objects vs inuse_space)、網頁 UI 導覽與解讀模式。當你需要深入探究程式碼中時間與記憶體花費在何處時使用。

  • benchstat 參考 — 使用嚴謹的信賴區間與 p 值檢定進行基準測試結果的統計比較。涵蓋輸出閱讀、過濾舊基準測試、交錯結果以獲得視覺清晰度,以及回歸偵測。當你需要證明某項變更帶來了有意義的效能差異,而不只是運氣好時使用。

  • 追蹤參考 — 執行追蹤器,用於理解程式碼何時執行及為何執行。可視化 goroutine 排程、垃圾回收階段、網路阻塞與自訂跨度註解。當 pprof(顯示 CPU 花費在何處)不夠用時——你需要查看事件發生的時間軸。

  • 診斷工具 — 輔助工具的快速參考:fieldalignment(結構體填充浪費)、GODEBUG(執行時期記錄旗標)、fgprof(框架圖剖析)、race detector(並行錯誤)等。當你有特定症狀且需要針對性診斷時使用——如果更簡單的工具已能回答你的問題,就不要動用 pprof。

  • 編譯器分析 — 底層編譯器最佳化洞察:逃逸分析(值何時移至堆積)、內聯決策(哪些函式呼叫被消除)、SSA 傾印(中間表示)與組合語言輸出。當基準測試顯示你預期之外的配置,或你想驗證編譯器是否如你所願時使用。

  • CI 回歸偵測 — CI 管線中的自動化效能回歸閘控。涵蓋三種工具(benchdiff 用於快速 PR 比較、cob 用於嚴格閾值閘控、gobenchdata 用於長期趨勢儀表板)、雜訊鄰居緩解策略(為何雲端 CI 基準測試即使在安靜機器上也會波動 5-10%),以及自託管執行器調校以使基準測試可重現。當你想確保拉取請求不會默默拖慢程式碼庫時使用——及早偵測回歸可避免累積效能債。

  • 調查工作階段 — 結合 Prometheus 執行時期指標(堆積大小、GC 頻率、goroutine 數量)、PromQL 查詢以關聯指標與程式碼變更、執行時期設定旗標(啟用 GC 記錄的 GODEBUG 環境變數)以及成本警告(當你遇到效能稅時)的生產環境效能疑難排解工作流程。當生產環境基準測試看起來不錯但實際流量表現不同時使用。

  • Prometheus Go 指標參考 — 由 prometheus/client_golang 實際暴露為 Prometheus 指標的 Go 執行時期指標完整列表。涵蓋 30 個預設指標、40+ 個可選指標(Go 1.17+)、程序指標與常見 PromQL 查詢。區分 runtime/metrics(Go 內部資料)與 Prometheus 指標(從 /metrics 抓取的內容)。當設定監控儀表板或為生產環境警示撰寫 PromQL 查詢時使用。

交叉參考

  • → 參閱 samber/cc-skills-golang@golang-performance 技能,了解測量後套用的最佳化模式("若 X 為瓶頸,則套用 Y")
  • → 參閱 samber/cc-skills-golang@golang-troubleshooting 技能,了解執行中服務的 pprof 設定(啟用、安全化、擷取)、Delve 除錯器、GODEBUG 旗標、根本原因方法論
  • → 參閱 samber/cc-skills-golang@golang-observability 技能,了解日常持續監控、持續剖析(Pyroscope)、分散式追蹤(OpenTelemetry)
  • → 參閱 samber/cc-skills-golang@golang-testing 技能,了解一般測試實務
  • → 參閱 samber/cc-skills@promql-cli 技能,了解在生產環境中查詢 Prometheus 執行時期指標以驗證基準測試結果