結論
這裡用的 Profiling 方法跟在 Java 沒什麼太大差別,仍是使用工具找出程式與資源間的關系, 會需要看點 Go 函式庫源始碼, 還好 Go net/http 函式庫的程式碼大部份都不會很長還滿好懂,過程也沒遇到什麼奇怪的狀況。
內建的 Profiling 工具某方面比 Java 內建的 JVisualVM 還要強大,能顯示關系圖,把數據與程式碼並列,像 block profiling 功能還是在 Solaris Studio 才有的進階選項, 雖然功能相較其它成熟語言的分析工具來的少,但一般狀況夠用了。
GC 目前沒找到專門的工具, 目前只能印出 gclog 來看數據,當 GC 頻率高的時候 log 就不好讀了,於是另外做了兩個小工具來協助分析。 profilingtool.go log2csv
其它一些 profiling 過程遇到零碎問題與解決方沒寫在文章裡,直接舉列在下方清單
Gotcha
- defer func 堆疊在 function return 時才會釋放, 若包在迴圈使用沒釋放的話,profiling 時候會看到 堆了很多 newdefer 跟 deferproc (由於忘了在哪裡踩到的,就沒寫在文章裡)
Standard Library
- net 底下的 read/write 都是跑 asynchronous 的,所以 cpu profiling 展開 gosched0 後會是各別 goroutine 的執行片段,片段之間的連帶關係還是要靠自已去抓出來的,工具沒那麼聰明
- Go1.1 有 timer.Reset 可以減少 Timer 重建
- 預設的 http package 裡沒有提供 timeout api,要把 http.Client 裡的 http.RoundTripper 整組換掉才能做到各階段連線與讀寫傳輸的 timeout 控制
Runtime
- GC & Goroutine scheduling 不是 free 的, pprof 是抓漏好幫手
- 目前 GC 實作還是陽春了點,能調效 latency 的手段有限
- Go1.1runtime.SetGCPercent
- Go1.1runtime.FreeOSMemory
- 用 cgo 自已管記憶體分配?
- GC 可以過透過 GOGC=off(or SetGCPercent(-1)) 配合 mem profiler 分析完整的 heap 配置狀況
- channel send/recv 跟 select 的 contention 會造成瓶頸,不過還沒遇到這種狀況,表面的知道
- cpu profiling 可以觀察有這類操作在消耗 cpu 資源,進而分析要不要調整 channel 的 buffer size,或是更換同步方式與演算法
- runtime.xchg / selectgo
- runtime.chanrecv
- runtime.chansend
- block profiling 可以看 goroutine 被 block 的 delay 時間
- cpu profiling 可以觀察有這類操作在消耗 cpu 資源,進而分析要不要調整 channel 的 buffer size,或是更換同步方式與演算法
Tool
- 內建的 go test 有提供 benchmark 的測試方法, 也能參數化加入 profiler, 有寫了一些但還是覺得整合的壓力測試不太會寫...
Other Issues
- 預設的 Http over TLS CPU吃很兇,有查到問題後就沒再試下去
- net/http: ssl performance problem
- 可以接OpenSSL來解決Apcera Case Study: The selection of the Go language
- 在 server side 要用的話,也有 ssl-offload 的 software/hardware 可以擋在前端
TODO
- 多核環境(>8)觀察 contention 與 GC 效能
No comments:
Post a Comment