注:本文的原文 Debugging performance issues in Go programs 由 Dmitry Vyukov 在 05/10/2014 - 07:06 編寫
注:原文太長,你們要看所有的請看原文,其餘的部分,後續慢慢翻譯。php
讓咱們假設你想提高你的GO程序的性能。這裏有一些工具能夠幫助你完成這個任務。這些工具能幫助你定位多種類型的熱點(CPU,IO,內存),你爲了可以顯著提高程序性能,你必須專一於熱點發生的地方。儘管如此,另一個結果是可能的--這些工具能幫助你肯定程序中明顯的性能缺陷。例如,當你在每一個程序啓動的時候,你能夠在每次查詢的以前準備一個 SQL 語句。另一個例子是若是一個 O(N^2)
算法在某種程度上陷入了一個明顯存在而且指望的 O(N)
狀況。爲了肯定這樣的狀況,你須要完整性的檢查你在 profiles 中看到的。例如第一種狀況下大量的時間花費在 SQL 語句的準備上,這已經超越了告警線了。html
一樣重要的是要理解性能影響的各類邊界因素。例如,一個程序經過 100 Mbps 的帶寬鏈接通信,而且它已經使用超過 90 Mbps,這裏就沒有什麼能夠對這程序作的來提高它的性能了。這些相似的邊界因素包括 磁盤 IO,內存消耗和計算任務。golang
考慮到這一點,咱們能夠查看這些可用的工具。web
注意:這些工具可能相互干擾,例如,精確的內存分析可能影響CPU分析。goroutine 阻塞分析可能影響調度追蹤等等,隔離地使用這些工具以便獲得更加精確的信息。算法
注意:這裏全部的描述都是基於 Go1.3 版本的windows
Go runtime 包含了內建的 CPU 分析器,這顯示了函數消耗的 CPU 時間百分比,這裏你有3種方式訪問它:服務器
go test
命令的 -cpuprofile 標記。例如,以下命令:$ go test -run=none -bench=ClientServerParallel4 -cpuprofile=cprof net/http
cprof
文件。$ go tool pprof --text http.test cprof
go tool pprof
來獲得最完整的列表。import net/http/pprof
而且用以下命令收集概要文件:$ go tool pprof --text mybin http://myserver:6060:/debug/pprof/profile
if *flagCpuprofile != "" { f, err := os.Create(*flagCpuprofile) if err != nil { log.Fatal(err) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() }
這份概要文件會被寫入指定的文件中,想象它和第一個選項同樣的命令行方式。網絡
這裏是一個使用 --web
選項產生的直觀的概要文件示例:
app
你可使用 -list=funcname
選項來研究單個函數,下面的 概要文件顯示了在 append 函數中所花費的時間:svg
. . 93: func (bp *buffer) WriteRune(r rune) error { . . 94: if r < utf8.RuneSelf { 5 5 95: *bp = append(*bp, byte(r)) . . 96: return nil . . 97: } . . 98: . . 99: b := *bp . . 100: n := len(b) . . 101: for n+utf8.UTFMax > cap(b) { . . 102: b = append(b, 0) . . 103: } . . 104: w := utf8.EncodeRune(b[n:n+utf8.UTFMax], r) . . 105: *bp = b[:n+w] . . 106: return nil . . 107: }
你能夠在這裏找到 pprof
工具的詳細信息和描述的數字圖。
當它不能解鎖堆棧的時候,這裏有關於分析器使用的3條特別條目:GC, System and ExternalCode。GC 表示內存垃圾回收的時間花費,見下面的內存分析器和垃圾收集器跟蹤優化建議部分。System 表示 goroutine 調度花費的時間,堆棧管理代碼以及其餘輔助的 runtime 代碼。ExternalCode 表示本地動態庫花費的時間。
這裏有些提示關於如何解釋說明你在 profile 中看到的信息。
若是不少時間花費在 runtime.mallocgc
函數,程序可能在小內存分配上面花費過多。 profile 會告訴你分配從哪裏來,看內存分析器建議如何優化的部分。
若是不少時間花費在 channel
操做部分,sync.Mutex
代碼和其餘 synchronization primitives
或者是系統組件,程序可能在承受資源競爭。考慮重構程序,以消除對共享資源的頻繁訪問。常見的技術包括分片、分區,本地緩衝/批量處理和寫時拷貝技術。
若是不少時間花費在 syscall.Read/Write
上面,程序可能在小讀寫上面花費代價太大。Bufio 包裝 os.File
或是 net.Conn
能對這種狀況有幫助。
若是不少時間花費在 GC 組件上面,程序不是分配了太多的臨時對象就是 heap size 設置太小致使垃圾回收頻繁發生。請看垃圾收集器跟蹤和內存分析器優化建議部分。
注意:
CPU profiler
目前不能在 darwin 上工做
注意: 在 windows 服務器上你須要安裝 Cygwin, Perl and Graphviz 來生成 svg/web 格式的概要文件
注意: 在 Linux 上你能夠嘗試 perf system profiler,它不能解鎖 GO 的堆棧,可是它能分析而且解鎖cgo/SWIG
代碼和內核。因此它在定位分析本地/內核性能瓶頸上很是有用。