曹大帶我學 Go之面向火焰圖編程
你好,我是小X。
曹大最近開 Go 課程了,小X 正在和曹大學 Go。
這個系列會講一些從課程中學到的讓人醍醐灌頂的東西,撥云見日,帶你重新認識 Go。
現實中聽過各種面向 XX 編程,什么面向過程編程、面向對象編程;也有一些俏皮的,面向薪資編程、面向老板編程;之前曹大還寫過一篇,面向事故編程。今天我們來講講面向火焰圖編程。
一般我們在做性能優化的時候,會先做壓測,然后進 pprof 尋找可能的原因及解法。
關注的指標,從服務角度看,包括:
- 請求量
- 錯誤數
- 延遲
從用戶角度看,則是:
- 延遲(Latency)
- 吞吐量(Throughput)
性能優化的最終目標就是在延遲可以接受的場景下,盡可能提高系統的吞吐量。
對于 Go 服務,還得看更多:
- 每秒鐘 GC 次數
- GC 停頓時長(p99, max)
- GC 占用的 CPU 大小
- 堆內存占用大小
- 協程數量
- 申請、釋放的內存大小
- 申請的對象數
對性能優化而言,我們可以在幾個層次分別進行優化:業務層、應用層、底層。
越在上層優化,回報越高。舉個簡單的例子,有業務方因為歷史原因,服務啟動之后,會周期性地調我們的接口拿一些數據。但是之后業務發生變動,拿的數據并沒有被使用,這塊代碼也沒相應地下線。而且因為對方的集群規模很大,所以這個調用量級還挺大。現在我們服務的容量即將到頂,需要優化服務或者擴容。
如果我們吭哧吭哧地去壓測、優化,擴容,很可能也能解決問題。并且,優化做得好的話,也能體現出自己的價值。但是平行世界有另一種解法,那就是去梳理業務方的使用場景,很可能直接就能下掉一半的訪問量,收益會大很多,而且操作起來也更簡單。
但是,通常情況下可能沒這么好運,我們還是得對著火焰圖來優化。
火焰圖的定義也不復雜:
在 Go 里,一般 pprof web 直接進去的圖不太好看懂,我們應該看火焰圖 。火焰圖就看寬度,寬度越寬,表示占用越大。
不怕它高,就怕它寬。
曹大說,想黑 Go,一張圖片就夠了:
我在這里有 2 個小點可以分享一下:
- pprof 的火焰圖用當前這個 bar 的時間除以最上層 bar 的時間,就可以得到某個函數的耗時占比。
- 用當前這個 bar 內存使用的占比乘以 RSS,得到的值是我們如果將這一塊內存使用優化掉之后,節省的內存大小。
火焰圖中的平頂山就很值得優化。什么是平頂山,最終要優化成什么樣子?
一句話,山頂很平的 bar 就叫平頂山??。優化之后,平頂山變窄或消失:
但有尖的是不好優化的 :
最后總結一下,面向火焰圖編程,非常簡單:我們逮著平頂山優化就行。
現實中可能因為公司的安全部門設置了很多阻礙,我們無法方便地獲取 profile 文件,自然就沒法愉快地去做性能優化了。基礎架構部門要做的事情就是盡可能方便地讓研發獲取到火焰圖。
好了,這就是今天全部的內容了~ 我是小X,我們下期再見~