來源:cyningsun.github.io/07-21-2019/…php
Go生態系統提供了大量API和工具來診斷Go程序中的邏輯和性能問題。 此頁面總結了可用的工具,並幫助Go用戶針對他們的特定問題選擇正確的工具。html
診斷解決方案可分爲如下幾組:前端
注意:某些診斷工具可能會相互干擾。 例如,精確的 memory profiling 會扭曲 CPU profiles,而goroutine blocking profiling 會影響 scheduler trace。 隔離使用工具可得到更精確的信息。git
Profiling 對於識別昂貴或常常調用的代碼段頗有用。 Go runtime 以 pprof 可視化工具所指望的格式提供 profiling data。 在測試期間能夠經過 go test
或 net/http/pprof 包提供的 endpoints 收集 profiling data。 用戶須要收集 profiling data 並使用 pprof 工具來過濾和可視化頂部代碼路徑。github
runtime/pprof 包提供的預約義 profiles:golang
runtime.SetBlockProfileRate
啓用。runtime.SetMutexProfileFraction
啓用。我可使用其餘哪些 profilers 來介紹Go程序?web
在Linux上,perf tools 可用於分析Go程序。 Perf 能夠 profile 和展開 cgo/SWIG 代碼和內核,所以深刻了解native/內核性能瓶頸很是有用。 在macOS上, Instruments 套件能夠用來 profile Go 程序。編程
我能夠 profile 個人生產環境的服務嗎?後端
是的。 在生產環境中對程序進行 profile 是安全的,但啓用某些 profiles(例如:CPU profile)會增長消耗。 您應該會看到性能降級。 在生產中打開探測器以前,能夠經過測量 profiler 的開銷來估計性能損失。安全
您可能但願按期分析您的生產服務。 特別是在具備單進程多副本的系統中,按期選擇隨機副本是安全的選擇。 選擇一個生產服務, 每隔Y秒 profile X秒並保存結果以進行可視化和分析; 而後按期重複。 能夠 手動/自動 檢查結果以發現問題。 profiles 收集可能會相互干擾,所以建議一次只收集一個 profile。
可視化分析數據的最佳方法是什麼?
Go tools使用 go tool pprof
提供文本,圖形和 callgrind 可視化的 profile data。 閱讀 Profiling Go programs 以查看它們的實際使用。
文本方式查看最大的消耗的調用
圖片方式可視化最大的消耗的調用
Weblist視圖在HTML頁面中逐行顯示源代碼最大消耗的部分。 在如下示例中,530ms用於 runtime.concatstrings
,每行的消耗顯示在列表中。
weblist方式可視化最大的消耗的調用
另外一種可視化輪廓數據的方法是火焰圖。 火焰圖容許您在特定的祖先路徑中移動,所以您能夠放大/縮小特定的代碼段。upstream pprof支持火焰圖。
火焰圖方式可視化以發現最昂貴的代碼路徑
我是否僅限於內置profiles?
除了 runtime 提供的工具以外,Go用戶還能夠經過 pprof.Profile 建立自定義 profiles,並使用現有工具對其進行檢查。
我能夠在不一樣的路徑和端口上提供 profiler handlers(/debug/pprof/...) 嗎?
是的。 默認狀況下, net/http/pprof
包將其 handlers 註冊到默認的mux,但您也可使用從包中導出的handler net/http/pprof註冊它們。
例如,如下示例將在7777端口/custom_debug_path/profile上提供 pprof.Profile handler:
package main
import (
"log"
"net/http"
"net/http/pprof"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/custom_debug_path/profile", pprof.Profile)
log.Fatal(http.ListenAndServe(":7777", mux))
}
複製代碼
Tracing 是一種檢測代碼的方法,用於分析一系列調用的生命週期中的延遲。 Go提供 golang.org/x/net/trace 包做爲每一個Go節點的最小 tracing backend,並提供一個帶有簡單儀表板的最小檢測庫。 Go還提供了一個執行跟蹤器來跟蹤時間間隔內的 runtime events。
Tracing 使咱們可以:
在單機系統中,從程序的構成模塊收集診斷數據相對容易。 全部模塊都位於一個進程中,並共享公共資源以報告日誌,錯誤和其餘診斷信息。一旦您的系統超出單個進程並開始變爲分佈式,跟蹤從前端Web服務器到其全部後端的調用,直到將響應返回給用戶,將變得更加困難。這就是分佈式 tracing 在檢測和分析生產系統方面發揮重要做用的地方。
分佈式 tracing 是一種檢測代碼的方法,用於分析用戶請求在整個生命週期中的延遲。 當系統分佈式化,而且傳統的分析和調試工具沒法scale時,您可能但願使用分佈式 tracing 工具來分析用戶請求和RPC的性能。
分佈式 tracing 使咱們可以:
GO生態系統爲每一個跟蹤系統提供了不一樣的分佈式跟蹤庫和後端無關的跟蹤庫。
有沒有辦法自動攔截每一個函數調用並建立 tracing ?
Go沒有提供自動攔截每一個函數調用和建立trace spans的方法。 您須要手動檢測代碼以建立,結束和註釋 spans。
我應該如何在Go庫中傳播 trace headers ?
您能夠在 context.Context
傳播trace標識符和標記。 目前行業中尚未 trace key 的規範和 trace headers 的通用表示。 每一個tracing提供程序都負責在其Go庫中提供傳播工具。
標準庫或 runtime 中的其餘低級事件能夠包含在 trace 中嗎?
標準庫和 runtime 試圖公開幾個額外的API來通知低級內部事件。 例如, httptrace.ClientTrace
提供API以跟蹤傳出請求生命週期中的低級事件。 目前正在努力從 runtime execution tracer 中檢索低級運行時事件,並容許用戶定義和記錄其用戶事件。
Debugging 是識別程序錯誤行爲的過程。調試器容許咱們理解程序的執行流程和當前狀態。有幾種調試方式;本節只關注將調試器 attach 到程序和 core dump 調試。
GO用戶主要使用如下調試器:
調試器與 Go 程序的兼容性如何?
gc
編譯器執行優化,例如函數內聯和變量註冊。 這些優化有時會使調試器調試更困難。 目前正在努力提升優化後的二進制文件的DWARF 信息的質量。 在這些改進可用以前,咱們建議在構建正在調試的代碼時禁用優化。 如下命令構建一個沒有編譯器優化的包:
$ go build -gcflags=all="-N -l"
複製代碼
做爲改進工做的一部分,Go 1.10引入了一個新的編譯器flag -dwarflocationlists
。 該標誌使編譯器添加位置列表,以幫助調試器使用優化後的二進制文件。 如下命令構建使用優化但包含 DWARF 位置列表的包:
$ go build -gcflags="-dwarflocationlists=true"
複製代碼
推薦的用戶界面調試器是什麼?
儘管 delve 和 gdb 都提供了 CLI,但大多數集成編輯器和IDE都提供了特定於調試的用戶界面。
是否可使用Go程序進行過後調試?
core dump 文件是包含正在運行的進程及其進程狀態的 memory dump 文件。 它主要用於程序的過後調試,並瞭解它仍在程序運行時的狀態。 這兩種狀況使 core dump 的調試成爲一種良好的診斷工具,可用於過後分析和分析生產服務。 能夠從Go程序獲取core文件,並使用delve或gdb進行調試,請參閱 core dump debugging 頁面以獲取分步指南。
runtime 爲用戶提供內部事件的統計信息和報告,以便在 runtime 級別診斷性能和利用率問題。
用戶能夠監控這些統計數據,以更好地瞭解Go程序的總體運行情況和性能。 一些常常監控的統計數據和狀態:
runtime.ReadMemStats
報告與堆分配和垃圾回收相關的metrics。 內存統計信息對於監視進程正在消耗多少內存資源,進程是否能夠很好地利用內存以及捕獲內存泄漏很是有用。debug.ReadGCStats
讀取有關垃圾收集的統計信息。 查看有多少資源用於GC暫停很是有用。 它還報告垃圾收集器暫停和暫停時間百分比的 timeline。debug.Stack
返回當前 stack trace。stack trace 有助於查看當前正在運行的 goroutine 數量,它們正在執行的操做,以及它們是否被阻塞。debug.WriteHeapDump
掛起全部 goroutine 的執行,並容許您將堆 dump 到文件中。 heap dump 是給定時間Go進程的內存快照。 它包含全部已分配的對象以及 goroutine,finalizers 等。runtime.NumGoroutine
返回當前 goroutine 的數量。 能夠監視該值以查看是否使用了足夠的goroutine,或檢測goroutine泄漏。Go附帶了一個runtime execution tracer,用於捕獲各類運行時事件。 調度,系統調用,垃圾收集,堆大小和其餘由 runtime 收集的事件,並可經過 go tool trace 進行可視化。 Execution tracer 是一種檢測延遲和利用率問題的工具。 您能夠檢查CPU的使用狀況,以及當網絡或系統調用成爲goroutines搶佔的緣由。
Tracer 使咱們可以:
可是,識別熱點(如分析內存過多或CPU使用率的緣由)並非很好用。 首先使用 profiling tools 來解決它們。
以上,go tool trace 可視化顯示執行開始正常,而後它變得順序化。 它代表可能存在共享資源的鎖競爭致使的瓶頸。
請參閱 go tool trace
以收集和分析 runtime traces。
若是相應地設置了 GODEBUG 環境變量,Runtime 也會發出事件和信息。
GODEBUG 環境變量可用於禁用標準庫和 runtime 中 instruction set extensions 的使用。
extension 是指令集擴展名的小寫名稱,例如 sse41 或 avx 。