最近在整理以前攢的 go 語言學習資料 -- 可能很多人都和我一樣, 随手一個收藏, 不動手也不深入, 然後就過去了. 這次從故紙堆裡掃出來, 當然不能錯過
資料:
- blog 位址:
https://www.cnblogs.com/sunsky303/p/9296188.html- 原作者已經提供好了代碼:
https://github.com/Deleplace/forks-golang-good-code-bad-code學習到的知識:
- 使用 `go test` 進行 單測/壓測
- 使用 `go tool` 進行 prof/trace
- 性能問題 debug 與優化思路
## let's party
- 作者準備好了代碼
- 确定基準, 使用 cpuprof 中的 `ns/op` 作為比較基準
```sh
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語言的細節, 後續的修改都基于 good 代碼進行
- 檢視 trace, 檢視 CPU 使用情況
# 使用 trace 工具
go test -bench=. -trace trace.out
go tool trace trace.out # 會在預設浏覽器中打開 trace

- trace 分析: 放大 CPU 部分 -> 數千個小的彩色計算切片 + 空閑插槽 -> 一些核心處于空閑狀态
- 首先進行競争檢測, **如果發生競争, 比性能問題更嚴重**
# 競争檢測
go test -race
- 嘗試 **不開協程**, 對應代碼:
https://github.com/Deleplace/forks-golang-good-code-bad-code/tree/nogo```go
// 改動就一行
for _, line := range in {
// go mapLine(line, ch)
mapLine(line, ch)
}
- 使用 cpuprof, 檢視熱函數調用, 定位到瓶頸
# 1. 生成 cpuprof
go test -bench=. -cpuprofile cpu.prof
# 2. 生成 svg
go tool pprof -svg cpu.prof > cpu.svg
# 3. 使用 chrome 打開 svg 檔案即可
- 根據瓶頸進行性能優化:
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.
- 協程使用(排程)優化: 5k message + 20/100 協程
- 20 協程:
https://github.com/Deleplace/forks-golang-good-code-bad-code/commit/a2dfc2a6e8397ae1a3dd6f4be19786ebb45008be- 100 協程:
https://github.com/Deleplace/forks-golang-good-code-bad-code/commit/26dbf25f2d01c96002a0e9ba66210a9e58ebbbbe- 到此, 已經優化達到的效果

- 還能不能再過分一點: 能, 用 `Lexer + Parser`
https://github.com/Deleplace/forks-golang-good-code-bad-code/tree/lexerparser## 寫在最後
> 總算把一個很久很久之前的坑給填上了, 開心😺
- prof 相關: 可以定位熱點函數, 友善定位瓶頸
go test -bench=. -cpuprofile cpu.prof # 壓測, 生成 prof 檔案
go tool pprof -svg cpu.prof > cpu.svg # 使用 prof 工具, prof 轉為 svg, svg 可以使用 chrome 打開
- trace 相關: 可以檢視 cpu 使用狀态
go tool trace trace.out
- goroutine 相關
首先要區分 CPU密集型任務/IO密集型任務, 協程更适合處理 **IO密集型任務**, 減少 IO wait 導緻的 CPU 空轉, 其次協程過多會導緻協程排程的開銷, 同樣會造成性能損失
- 推薦使用 github desktop
切換分支, 檢視 commit, so easy ~