
“A Journey With Go” 專屬插圖,由 Renee French 根據原始 Go Gopher 制作。
ℹ️ 本文基于 Go 1.13.
go test 指令提供了許多出色的功能,比如代碼覆寫率,CPU 和 記憶體分析。要提供這些統計資訊,Go 就需要一種方式來跟蹤 CPU 使用率,或在代碼覆寫中跟蹤一個函數何時被用到。
本文是 Go語言中文網組織的 GCTT 翻譯,釋出在 Go語言中文網公衆号,轉載請聯系我們授權。
<h1 class="pgc-h-arrow-right" data-track="5">性能測量</h1>
Go 使用多種方式來産生這些統計資訊:
動态插入性能測量語句,使其可以跟蹤到代碼何時進入一個函數或條件。這個政策在代碼覆寫率[1]中使用。
每秒記錄多次程式樣本。這個政策在CPU 分析[2]中用到。
在代碼中使用靜态 hook,以便在執行期間調用所需函數。這個政策在記憶體分析中用到。
我們來寫一個簡單的程式并回顧所有内容。這是我們在後面的章節将使用的代碼:
main.go 托管在 [GitHub] (https://github.com/) 檢視[3]
<h1 class="pgc-h-arrow-right" data-track="13">代碼覆寫率</h1>
通過 GOSSAFUNC=run Go test -cover 指令生成的 SSA 代碼,我們可以檢視 Go 對程式進行了什麼樣的修改:
變量 GoCover_0_313837343662366134383538 是一個标志數組,其中每個鍵是一個代碼塊,當代碼實際進入這一塊時對應的标志設定為 1.
你可以在我的文章 “Go: Compiler Phases”[4] 中找到更多關于 SSA 的資訊。
生成的代碼将稍後在管理代碼覆寫率報告的函數中使用。我們可以通過使用 objdump 指令反彙編代碼覆寫期間生成的目标檔案來進行驗證。運作 go test -cover -o main.o && Go tool objdump main.go 将反彙編代碼并顯示缺少的部分。它首先初始化并在自動生成的 init 函數中注冊 coverage:
test.go 添加的 init 方法
然後,如前所述,測試将在執行期間收集覆寫率資料并且會觸發一個方法來實際寫入和顯示覆寫率:
go test 調用的 after 函數
<h1 class="pgc-h-arrow-right" data-track="24">CPU 分析</h1>
跟蹤 CPU 使用率的政策則有所不同。Go 會停止程式并收集正在運作程式的樣本。這裡是未開啟 CPU 分析的代碼的 trace:
這裡是相同代碼開啟了 CPU 分析的 trace:
增加的 trace 與 pprof 及性能分析相關。這裡是其中一個的放大圖:
profileWriter 方法将循環調用,每 100 毫秒收集 CPU 資料,以在性能分析結束時最終生成報告。
<h1 class="pgc-h-arrow-right" data-track="29">記憶體分析</h1>
記憶體分析包含在源碼中,并已內建在記憶體配置設定系統中。在使用 -memprofile 開啟記憶體分析[5]的情況下,位于 malloc.go[6] 中的記憶體配置設定器,将對已配置設定的記憶體進行分析[7]。這裡,依然可以通過反彙編代碼進行驗證。這裡是記憶體配置設定器的使用:
開啟了記憶體配置設定分析
你可以在我的文章 “Go: Unknown Parts of the Test Package[8]” 中找到更多關于 test 包的資訊.
via: https://medium.com/a-journey-with-go/go-instrumentation-in-go-e845cdae0c51
作者:Vincent Blanchon[9]譯者:krystollia[10]校對:polaris1119[11]
本文由 GCTT[12] 原創編譯,Go 中文網[13] 榮譽推出,釋出在 Go語言中文網公衆号,轉載請聯系我們授權。
<h1 class="pgc-h-arrow-right" data-track="36">參考資料</h1>
[1]
代碼覆寫率: https://golang.org/doc/go1.2#cover
[2]
CPU 分析: https://blog.golang.org/profiling-go-programs
[3]
GitHub] (https://github.com/) [檢視: https://gist.github.com/blanchonvincent/d4ed01d31b3ed99eb5cd87629ecfe926/raw/1fbac76f932d020a2b172b2385fb1cda69b83b1e/main.go
[4]
“Go: Compiler Phases”: https://medium.com/@blanchon.vincent/go-compiler-phases-4e5a153ca889
[5]
開啟記憶體分析: https://github.com/golang/go/blob/release-branch.go1.13/src/cmd/compile/internal/gc/util.go#L55-L77
[6]
malloc.go: https://github.com/golang/go/blob/release-branch.go1.13/src/runtime/malloc.go#L877
[7]
對已配置設定的記憶體進行分析: https://github.com/golang/go/blob/release-branch.go1.13/src/runtime/malloc.go#L1097-L1105
[8]
Go: Unknown Parts of the Test Package: https://medium.com/a-journey-with-go/go-unknown-parts-of-the-test-package-df8988b2ef7f
[9]
Vincent Blanchon: https://medium.com/@blanchon.vincent
[10]
krystollia: https://github.com/krystollia
[11]
polaris1119: https://github.com/polaris1119
[12]
GCTT: https://github.com/studygolang/GCTT
[13]
Go 中文網: https://studygolang.com/