golang-performance

golang-performance

熱門

Golang 效能最佳化模式與方法論 — 若遇到 X 瓶頸,則套用 Y。涵蓋減少記憶體配置、CPU 效率、記憶體佈局、GC 調校、物件池、快取以及熱路徑最佳化。在效能分析或基準測試已找出瓶頸,且需要正確的最佳化模式來解決時使用。也可在進行效能程式碼審查時使用,以提出改善建議或可協助找出快速效能增益的基準測試。不適用於測量方法論(→ 請參閱 `samber/cc-skills-golang@golang-benchmark` 技能)或除錯流程(→ 請參閱 `samber/cc-skills-golang@golang-troubleshooting` 技能)。

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

Golang 效能最佳化模式與方法論 — 若遇到 X 瓶頸,則套用 Y。涵蓋減少記憶體配置、CPU 效率、記憶體佈局、GC 調校、物件池、快取以及熱路徑最佳化。在效能分析或基準測試已找出瓶頸,且需要正確的最佳化模式來解決時使用。也可在進行效能程式碼審查時使用,以提出改善建議或可協助找出快速效能增益的基準測試。不適用於測量方法論(→ 請參閱 `samber/cc-skills-golang@golang-benchmark` 技能)或除錯流程(→ 請參閱 `samber/cc-skills-golang@golang-troubleshooting` 技能)。

角色設定: 你是一位 Go 效能工程師。未經效能分析絕不進行最佳化 — 先測量、提出假設、一次只改一個變數、重新測量。

思考模式: 進行效能最佳化時使用 ultrathink。淺層分析容易誤判瓶頸 — 深度推理才能確保對的問題套用正確的最佳化。

模式:

  • 審查模式(架構) — 對套件或服務進行廣泛掃描,找出結構性反模式(缺少連線池、無限制的 goroutine、錯誤的資料結構)。最多使用 3 個平行子代理,按關注領域拆分:(1) 記憶體配置與佈局、(2) I/O 與並行、(3) 演算法複雜度與快取。
  • 審查模式(熱路徑) — 針對呼叫者指定的單一函式或緊湊迴圈進行聚焦分析。循序進行;一個子代理即足夠。
  • 最佳化模式 — 已透過效能分析找出瓶頸。遵循迭代循環(定義指標 → 基準線 → 診斷 → 改善 → 比較)循序進行 — 一次只改一個變數是紀律。

相依套件:

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

Go 效能最佳化

核心哲學

  1. 先效能分析再最佳化 — 對瓶頸的直覺約有 80% 是錯的。使用 pprof 找出真正的熱點(→ 請參閱 samber/cc-skills-golang@golang-troubleshooting 技能)
  2. 減少記憶體配置能獲得最大投資報酬率 — Go 的 GC 很快但並非免費。減少每次請求的記憶體配置通常比微調 CPU 更重要
  3. 記錄最佳化 — 在程式碼中加入註解說明為何某個模式較快,並附上基準測試數據(若有的話)。未來閱讀程式碼的人需要這些背景資訊,以免將「不必要的」最佳化還原

先排除外部瓶頸

在最佳化 Go 程式碼之前,請先確認瓶頸是在你的程序中 — 如果 90% 的延遲來自慢速的資料庫查詢或 API 呼叫,減少記憶體配置並不會有幫助。

診斷: 1- fgprof — 捕捉 on-CPU 和 off-CPU(I/O 等待)時間;如果 off-CPU 佔主導,則瓶頸在外部 2- go tool pprof(goroutine 分析)— 大量 goroutine 阻塞在 net.(*conn).Readdatabase/sql = 外部等待 3- 分散式追蹤(OpenTelemetry)— span 分解顯示哪個上游服務慢

當瓶頸在外部時: 最佳化該元件 — 查詢調校、快取、連線池、斷路器(→ 請參閱 samber/cc-skills-golang@golang-database 技能、快取模式)。

迭代最佳化方法論

循環:定義目標 → 基準測試 → 診斷 → 改善 → 基準測試

  1. 定義你的指標 — 延遲、吞吐量、記憶體或 CPU?沒有目標,最佳化就是亂槍打鳥
  2. 撰寫原子基準測試 — 每個基準測試只隔離一個函式,避免結果污染(→ 請參閱 samber/cc-skills-golang@golang-benchmark 技能)
  3. 測量基準線go test -bench=BenchmarkMyFunc -benchmem -count=6 ./pkg/... | tee /tmp/report-1.txt
  4. 診斷 — 使用每個深入探討章節中的診斷行來選擇正確的工具
  5. 改善 — 一次只套用一個最佳化,並加上說明註解
  6. 比較benchstat /tmp/report-1.txt /tmp/report-2.txt 以確認統計顯著性
  7. 提交 — 將 benchstat 輸出貼在 commit 內文中,讓審查者和未來閱讀者看到確切的改善;遵循 perf(scope): summary 提交類型
  8. 重複 — 遞增報告編號,處理下一個瓶頸

在發明自訂解決方案之前,請先查閱函式庫文件了解已知模式。保留所有 /tmp/report-*.txt 檔案作為稽核軌跡。

決策樹:時間花在哪裡?

瓶頸 訊號(來自 pprof) 行動
太多記憶體配置 heap profile 中 alloc_objects 很高 記憶體最佳化
CPU 密集型熱迴圈 函式佔據 CPU profile 主導地位 CPU 最佳化
GC 暫停 / OOM GC% 高、容器限制 執行時期調校
網路 / I/O 延遲 goroutine 阻塞在 I/O I/O 與網路
重複的昂貴工作 相同計算/擷取多次 快取模式
錯誤的演算法 O(n²) 但存在 O(n) 的解法 演算法複雜度
鎖競爭 mutex/block profile 熱點 → 請參閱 samber/cc-skills-golang@golang-concurrency 技能
慢查詢 DB 時間佔據追蹤主導 → 請參閱 samber/cc-skills-golang@golang-database 技能

常見錯誤

錯誤 修正
未經效能分析就最佳化 先用 pprof 分析 — 直覺約有 80% 是錯的
使用預設 http.Client 而未設定 Transport MaxIdleConnsPerHost 預設為 2;請設定為符合你的並行層級
在熱迴圈中記錄日誌 日誌呼叫會阻止內嵌,即使層級已停用也會配置記憶體。請使用 slog.LogAttrs
panic/recover 當作控制流程 panic 會配置堆疊追蹤並展開堆疊;請使用錯誤回傳
未經基準測試證明就使用 unsafe 只有在效能分析顯示在驗證過的熱路徑中改善超過 10% 時才合理
在容器中未進行 GC 調校 GOMEMLIMIT 設為容器記憶體的 80-90%,以防止 OOM 終止
在正式環境中使用 reflect.DeepEqual 比型別比較慢 50-200 倍;請使用 slices.Equalmaps.Equalbytes.Equal

深入探討

  • 記憶體最佳化 — 配置模式、底層陣列洩漏、sync.Pool、結構體對齊
  • CPU 最佳化 — 內嵌、快取區域性、虛假共享、ILP、避免反射
  • I/O 與網路 — HTTP 傳輸設定、串流、JSON 效能、cgo、批次操作
  • 執行時期調校 — GOGC、GOMEMLIMIT、GC 診斷、GOMAXPROCS、PGO
  • 快取模式 — 演算法複雜度、編譯模式、singleflight、避免重複工作
  • 正式環境可觀測性 — Prometheus 指標、PromQL 查詢、持續效能分析、告警規則

CI 迴歸檢測

在 CI 中自動化基準測試比較,在迴歸進入正式環境前就捕捉到。→ 請參閱 samber/cc-skills-golang@golang-benchmark 技能了解 benchdiffcob 的設定。

交叉參考

  • → 請參閱 samber/cc-skills-golang@golang-benchmark 技能了解基準測試方法論、benchstatb.Loop()(Go 1.24+)
  • → 請參閱 samber/cc-skills-golang@golang-troubleshooting 技能了解 pprof 流程、逸出分析診斷和效能除錯
  • → 請參閱 samber/cc-skills-golang@golang-data-structures 技能了解 slice/map 預先配置和 strings.Builder
  • → 請參閱 samber/cc-skills-golang@golang-concurrency 技能了解工作者池、sync.Pool API、goroutine 生命週期和鎖競爭
  • → 請參閱 samber/cc-skills-golang@golang-safety 技能了解迴圈中的 defer、slice 底層陣列別名
  • → 請參閱 samber/cc-skills-golang@golang-database 技能了解連線池調校和批次處理
  • → 請參閱 samber/cc-skills-golang@golang-observability 技能了解正式環境中的持續效能分析