譯 | Diagnostics

來源:cyningsun.github.io/07-21-2019/…php

Introduction

Go生態系統提供了大量API和工具來診斷Go程序中的邏輯和性能問題。 此頁面總結了可用的工具,並幫助Go用戶針對他們的特定問題選擇正確的工具。html

診斷解決方案可分爲如下幾組:前端

  • Profiling:Profiling 工具分析Go程序的複雜性和成本,例如其內存使用狀況和頻繁調用的函數,以識別Go程序的昂貴部分。
  • Tracing:Tracing 是一種檢測代碼的方法,用於分析調用或用戶請求的整個生命週期中的延遲。 Traces 提供了每一個組件對系統整體延遲影響的概覽。 Traces 能夠跨越多個Go進程。
  • Debugging: Debugging 容許咱們暫停Go程序並檢查其執行。能夠經過 debugging 驗證程序狀態和流程。
  • Runtime statistics and events: 對運行時統計信息、事件的收集和分析提供了Go程序運行情況的高層次概覽。 指標的尖峯/降低有助於咱們識別吞吐量,利用率和性能的變化。

注意:某些診斷工具可能會相互干擾。 例如,精確的 memory profiling 會扭曲 CPU profiles,而goroutine blocking profiling 會影響 scheduler trace。 隔離使用工具可得到更精確的信息。git

Profiling

Profiling 對於識別昂貴或常常調用的代碼段頗有用。 Go runtime 以 pprof 可視化工具所指望的格式提供 profiling data。 在測試期間能夠經過 go testnet/http/pprof 包提供的 endpoints 收集 profiling data。 用戶須要收集 profiling data 並使用 pprof 工具來過濾和可視化頂部代碼路徑。github

runtime/pprof 包提供的預約義 profiles:golang

  • cpu: CPU profile 肯定程序在活躍的消耗CPU週期(而不是在睡眠或等待I/O時)花費時間的位置。
  • heap: Heap profile 報告內存分配樣本; 用於監視當前和歷史內存使用狀況,並檢查內存泄漏。
  • threadcreate: Thread creation profile 報告程序中致使建立新OS線程的部分。
  • goroutine: Goroutine profile 報告全部當前 goroutines 的 stack traces。
  • block: Block profile 顯示goroutine阻止等待同步原語(包括 timer channels)的位置。 Block profile 默認狀況下未開啓; 使用 runtime.SetBlockProfileRate 啓用。
  • mutex: Mutex profile 報告鎖競爭。 若是您認爲因爲互斥競爭而未充分利用您的CPU,請使用此 profile。 Mutex profile 默認狀況下未開啓,請參閱 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 以查看它們的實際使用。

738fb1d54bd36c74ac3c98052ed7db24.png

文本方式查看最大的消耗的調用

9271bb2658eb3b3fb8bf034d2675f4d2.png

圖片方式可視化最大的消耗的調用

Weblist視圖在HTML頁面中逐行顯示源代碼最大消耗的部分。 在如下示例中,530ms用於 runtime.concatstrings,每行的消耗顯示在列表中。

18b069d57a4f697cc580ea69478dea77.png

weblist方式可視化最大的消耗的調用

另外一種可視化輪廓數據的方法是火焰圖。 火焰圖容許您在特定的祖先路徑中移動,所以您能夠放大/縮小特定的代碼段。upstream pprof支持火焰圖。

77471e15e5c54e282982377b454320c5.png

火焰圖方式可視化以發現最昂貴的代碼路徑

我是否僅限於內置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

Tracing 是一種檢測代碼的方法,用於分析一系列調用的生命週期中的延遲。 Go提供 golang.org/x/net/trace 包做爲每一個Go節點的最小 tracing backend,並提供一個帶有簡單儀表板的最小檢測庫。 Go還提供了一個執行跟蹤器來跟蹤時間間隔內的 runtime events。

Tracing 使咱們可以:

  • 檢測和分析Go進程中應用程序延遲。
  • 衡量一長串調用中特定調用的耗時。
  • 弄清楚使用狀況和性能改進點。 沒有tracing數據,瓶頸並不老是顯而易見。

在單機系統中,從程序的構成模塊收集診斷數據相對容易。 全部模塊都位於一個進程中,並共享公共資源以報告日誌,錯誤和其餘診斷信息。一旦您的系統超出單個進程並開始變爲分佈式,跟蹤從前端Web服務器到其全部後端的調用,直到將響應返回給用戶,將變得更加困難。這就是分佈式 tracing 在檢測和分析生產系統方面發揮重要做用的地方。

分佈式 tracing 是一種檢測代碼的方法,用於分析用戶請求在整個生命週期中的延遲。 當系統分佈式化,而且傳統的分析和調試工具沒法scale時,您可能但願使用分佈式 tracing 工具來分析用戶請求和RPC的性能。

分佈式 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

Debugging 是識別程序錯誤行爲的過程。調試器容許咱們理解程序的執行流程和當前狀態。有幾種調試方式;本節只關注將調試器 attach 到程序和 core dump 調試。

GO用戶主要使用如下調試器:

  • Delve :Delve是Go編程語言的調試器。 它支持Go的 runtime 概念和內置類型。 Delve正試圖成爲Go程序的全功能可靠調試器。
  • GDB :Go經過標準Go編譯器和 Gccgo 提供 GDB 支持。 堆棧管理、線程和運行時包含的方面與 GDB 執行模型有足夠的不一樣,所以可能會使調試器難以理解。即便程序是使用 gccgo 編譯的。 儘管GDB可用於調試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 statistics and events

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泄漏。

Execution tracer

Go附帶了一個runtime execution tracer,用於捕獲各類運行時事件。 調度,系統調用,垃圾收集,堆大小和其餘由 runtime 收集的事件,並可經過 go tool trace 進行可視化。 Execution tracer 是一種檢測延遲和利用率問題的工具。 您能夠檢查CPU的使用狀況,以及當網絡或系統調用成爲goroutines搶佔的緣由。

Tracer 使咱們可以:

  • 瞭解你的 goroutines 如何執行。
  • 瞭解一些核心 runtime 事件,例如GC運行。
  • 識別並行化不足的執行。

可是,識別熱點(如分析內存過多或CPU使用率的緣由)並非很好用。 首先使用 profiling tools 來解決它們。

229748672006e67fead3212695e267cc.png

以上,go tool trace 可視化顯示執行開始正常,而後它變得順序化。 它代表可能存在共享資源的鎖競爭致使的瓶頸。

請參閱 go tool trace 以收集和分析 runtime traces。

GODEBUG

若是相應地設置了 GODEBUG 環境變量,Runtime 也會發出事件和信息。

  • GODEBUG=gctrace=1 在每一個集合中打印垃圾收集器事件,總結收集的內存量和暫停的長度。
  • GODEBUG=schedtrace=X 每X毫秒打印一次調度事件。

GODEBUG 環境變量可用於禁用標準庫和 runtime 中 instruction set extensions 的使用。

  • GODEBUG=cpu.all=off 禁用全部可選指令集擴展的使用。
  • GODEBUG=cpu.extension=off 禁止使用指定指令集擴展中的指令。

extension 是指令集擴展名的小寫名稱,例如 sse41 或 avx 。

原文:golang.org/doc/diagnos…

相關文章
相關標籤/搜索