其实关于性能优化的主题,网上已经讨论很多次,这里谈一下我的理解,那么其实核心就是 2 个点:
linux 程序常用的调试工具:
vmstat、iostat、 mpstat、netstat、 sar 、top:查看系统、程序信息等
gprof、perf、perf top:定位到具体函数、调用等
strace、ltrace:系统调用、函数调用、库函数调用等
pstack、ptree、pmap:堆栈信息
dmesg:系统 log 信息
对于 go 程序,如果遇到高负载等性能问题推荐使用:perf top、pprof 快速定位问题。
当前系统的 uptime:load average 2.50 左右,以下 perf top 信息中出现_raw_spin_unlock_irqrestore 表示系统可能比较“闲’‘,以及有较多的软中断(服务交互)。unknown 则是没有加载符号文件,所以没有显示函数名,vdso 很可能 time 相关系统调用。
runtime.scanobject、mallocgc 说明可能有较多小对象申请等等。
on cpu 类型的 pprof 收集原理:注册 settimer 系统调用回调,1 秒触发 100 次回调,然后遍历每个线程的堆栈信息并保存生成 prof 文件。(off cpu 则是 IO 较大的程序)
程序中如下使用,注册 pprof 监听的端口即可。
- import _ "net/http/pprof"
-
- gofunc() {
- http.ListenAndServe("0.0.0.0:8080", nil)
- }()
pprof.go 文件的 init 在 DefaultServeMux 默认路由上注册了多个 handle,分别用来收集 cpu、内存等信息
- pprof.go
- func init() {
- http.HandleFunc("/debug/pprof/", Index)
- http.HandleFunc("/debug/pprof/cmdline", Cmdline)
- http.HandleFunc("/debug/pprof/profile", Profile)
- http.HandleFunc("/debug/pprof/symbol", Symbol)
- http.HandleFunc("/debug/pprof/trace", Trace)
- }
对应的 handle,定期以固定 hz 频率收集程序信息到 profileBuilder 对象中。最终在收集完成返回收集的数据信息,最终 web 页面展示出来。
- type profileBuilder struct {
- start time.Time
- end time.Time
- havePeriod bool
- period int64
- m profMap
-
- // encoding state
- w io.Writer
- zw *gzip.Writer
- pb protobuf
- strings []string
- stringMap map[string]int
- locs map[uintptr]locInfo
- funcs map[string]int
- mem []memMap
- deck pcDeck
- }
-
- // and
- runtime.MemProfileRecord // goroutine堆栈信息
- runtime.MemStats // 内存数据统计信息
我们可以使用下面多种方式查看程序的内存、cpu、锁等信息。
- // Then use the pprof tool to look at the heap profile:
- //
- // go tool pprof http://localhost:6060/debug/pprof/heap
- //
- // Or to look at a 30-second CPU profile:
- //
- // go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
- //
- // Or to look at the goroutine blocking profile, after calling
- // runtime.SetBlockProfileRate in your program:
- //
- // go tool pprof http://localhost:6060/debug/pprof/block
- //
- // Or to look at the holders of contended mutexes, after calling
- // runtime.SetMutexProfileFraction in your program:
- //
- // go tool pprof http://localhost:6060/debug/pprof/mutex
- //
- // The package also exports a handler that serves execution trace data
- // for the "go tool trace" command. To collect a 5-second execution trace:
- //
- // wget -O trace.out http://localhost:6060/debug/pprof/trace?seconds=5
- // go tool trace trace.out
- //
- // To view all available profiles, open http://localhost:6060/debug/pprof/
- // in your browser.
- //
- // For a study of the facility in action, visit
- //
- // https://blog.golang.org/2011/06/profiling-go-programs.html
简单的示例,查看 goroutine 的堆栈、程序的内存信息、gc 次数等。
- go tool pprof http://localhost:6060/debug/pprof/heap?debug=1
-
- // runtime.MemProfileRecord
- heap profile: 71: 35532256 [15150: 492894072] @ heap/1048576
- 1: 31203328 [1: 31203328] @ 0xc2c83a 0x49ed0a 0x49ecd7 0x49ecd7 0x49ecd7 0x491985 0x4c79c1
- # 0xc2c839 git.code.oa.com/tmemesh.io/sidecar.init+0x39 git.code.oa.com/tmemesh.io/sidecar@v0.0.27/report.go:14
- # 0x49ed09 runtime.doInit+0x89 /usr/local/go/src/runtime/proc.go:5646
- # 0x49ecd6 runtime.doInit+0x56 /usr/local/go/src/runtime/proc.go:5641
- # 0x49ecd6 runtime.doInit+0x56 /usr/local/go/src/runtime/proc.go:5641
- # 0x49ecd6 runtime.doInit+0x56 /usr/local/go/src/runtime/proc.go:5641
- # 0x491984 runtime.main+0x1c4 /usr/local/go/src/runtime/proc.go:191
-
- // runtime.MemStats
- # runtime.MemStats
- # Alloc = 83374072
- # TotalAlloc = 8261199880
- # Sys = 216980496
- # Lookups = 0
- # Mallocs = 102656515
- # Frees = 102139727
- # HeapAlloc = 83374072
- # HeapSys = 199491584
- # HeapIdle = 94797824
- # HeapInuse = 104693760
- ...
- # NextGC = 163876768
- # LastGC = 1618924964269456488
- # NumGC = 333
- # NumForcedGC = 0
- # GCCPUFraction = 0.00011171208329868897
- # DebugGC = false
- # MaxRSS = 130633728
投放服务的主要工作就是给用户投放合适的内容(主播、会员广告)
这里压测 srf 服务可以使用 bm_tools 工具,可以很方便的压测 qps 以及查看服务平均延迟等(下面有示例)

资料领取直通车:Golang云原生最新资料+视频学习路线
Go语言学习地址:Golang DevOps项目实战