最近在整理以前攢的 go 語言學(xué)習(xí)資料 -- 可能很多人都和我一樣, 隨手一個(gè)收藏, 不動(dòng)手也不深入, 然后就過去了. 這次從故紙堆里掃出來, 當(dāng)然不能錯(cuò)過
資料:
- blog 地址: https://www.cnblogs.com/sunsky303/p/9296188.html
- 原作者已經(jīng)提供好了代碼: https://github.com/Deleplace/forks-golang-good-code-bad-code
學(xué)習(xí)到的知識(shí):
- 使用
go test進(jìn)行 單測/壓測 - 使用
go tool進(jìn)行 prof/trace - 性能問題 debug 與優(yōu)化思路
let's party
作者準(zhǔn)備好了代碼 https://github.com/Deleplace/forks-golang-good-code-bad-code
確定基準(zhǔn), 使用 cpuprof 中的
ns/op作為比較基準(zhǔn)
cd bad
? bad git:(master) ? go test -bench=. -cpuprofile cpu.prof
goos: darwin
goarch: amd64
pkg: test/bad
BenchmarkParseAdexpMessage-8 18999 63848 ns/op
PASS
ok test/bad 2.007s
bad & good 代碼對比: good 更慣用,更易讀,利用go語言的細(xì)節(jié), 后續(xù)的修改都基于 good 代碼進(jìn)行
查看 trace, 查看 CPU 使用情況
# 使用 trace 工具
go test -bench=. -trace trace.out
go tool trace trace.out # 會(huì)在默認(rèn)瀏覽器中打開 trace

trace 分析: 放大 CPU 部分 -> 數(shù)千個(gè)小的彩色計(jì)算切片 + 空閑插槽 -> 一些核心處于空閑狀態(tài)
首先進(jìn)行競爭檢測, 如果發(fā)生競爭, 比性能問題更嚴(yán)重
# 競爭檢測
go test -race
- 嘗試 不開協(xié)程, 對應(yīng)代碼: https://github.com/Deleplace/forks-golang-good-code-bad-code/tree/nogo
// 改動(dòng)就一行
for _, line := range in {
// go mapLine(line, ch)
mapLine(line, ch)
}
- 使用 cpuprof, 查看熱函數(shù)調(diào)用, 定位到瓶頸
# 1. 生成 cpuprof
go test -bench=. -cpuprofile cpu.prof
# 2. 生成 svg
go tool pprof -svg cpu.prof > cpu.svg
# 3. 使用 chrome 打開 svg 文件即可
-
根據(jù)瓶頸進(jìn)行性能優(yōu)化: https://github.com/Deleplace/forks-golang-good-code-bad-code/tree/performance
- Fast custom trim func, to remove the space character only.
- Use bytes.HasPrefix.
- regexp.MustCompile is exactly what we need here.
- Instead of regexp, use a loop: 10x speedupgap .
- bytes.IndexByte is more appropriate here.
- Small parseLine and findSubfields refactoring, same perf.
- Remove startWith, call directly bytes.HasPrefix: slightly faster.
-
協(xié)程使用(調(diào)度)優(yōu)化: 5k message + 20/100 協(xié)程
到此, 已經(jīng)優(yōu)化達(dá)到的效果

- 還能不能再過分一點(diǎn): 能, 用
Lexer + Parserhttps://github.com/Deleplace/forks-golang-good-code-bad-code/tree/lexerparser
寫在最后
總算把一個(gè)很久很久之前的坑給填上了, 開心??
- prof 相關(guān): 可以定位熱點(diǎn)函數(shù), 方便定位瓶頸
go test -bench=. -cpuprofile cpu.prof # 壓測, 生成 prof 文件
go tool pprof -svg cpu.prof > cpu.svg # 使用 prof 工具, prof 轉(zhuǎn)為 svg, svg 可以使用 chrome 打開
- trace 相關(guān): 可以查看 cpu 使用狀態(tài)
go test -bench=. -trace trace.out
go tool trace trace.out
- goroutine 相關(guān)
首先要區(qū)分 CPU密集型任務(wù)/IO密集型任務(wù), 協(xié)程更適合處理 IO密集型任務(wù), 減少 IO wait 導(dǎo)致的 CPU 空轉(zhuǎn), 其次協(xié)程過多會(huì)導(dǎo)致協(xié)程調(diào)度的開銷, 同樣會(huì)造成性能損失
- 推薦使用 github desktop
切換分支, 查看 commit, so easy ~