在軟件開發過程中,性能優化是不可或缺的一部分。無論是在Web服務、數據處理系統還是實時通信中,良好的性能都是至關重要的。Golang 從1.20版版本開始引入的?Profile Guided Optimization(PGO)機制能夠幫助更好地優化 Go 程序的性能。
什么是 Profile Guided Optimization(PGO)?
編譯器在編譯程序的時候會對程序做很多優化,例如通過分析程序源代碼就可以實現的 inline optimization(內聯優化)、escape analysis(逃逸分析)、constant propagation(常數傳播)等優化手段。但是還有一些優化手段是無法通過分析源代碼來實現的,例如一個函數里有很多條件分支語句,我們會希望編譯器自動優化條件分支順序,來加快條件分支的判斷,提升程序性能。但是,編譯器是不知道知道實際業務場景中每個條件分支進入的次數情況的,因為這個和程序的輸入有關,所以編譯出的程序就沒辦法在具體的應用場景中達到最佳性能。在這種場景下,PGO 就能發揮很大的作用了。
Profile Guided Optimization(PGO ),也可以被稱為?feedback-directed optimization (FDO),是 Go 編譯器的一種優化技術,通過分析程序運行時的行為數據來優化程序的性能。PGO 工具在編譯過程中收集程序運行時的數據,然后利用這些數據對程序進行針對性的優化。這個過程的實現步驟如下:
- 在程序運行時,使用 profiling 工具采集 profile 數據。
- 根據采集到的 profile 數據,對程序進行重新編譯。
- 在重新編譯后的程序中,再次采集 profile 數據,并重復步驟2,直到程序達到理想的性能。
關于性能的提升情況,Golang 官方給出的數據是,在 Go 1.21中,一組具有代表性的 Go 程序的基準測試表明,使用 PGO 構建可以提高大約2-7%的性能。隨著 Golang 對 PGO的不斷優化,對性能的提升作用相信也會越來越大。
使用示例
可以通過 net/http/pprof 包生成的文件作為 profile 文件,示例如下:
package mainimport ("fmt""net/http"_ "net/http/pprof"
)func IndexHandler(w http.ResponseWriter, r *http.Request) {fmt.Fprintln(w, "hello world")
}func main() {http.HandleFunc("/test", IndexHandler)http.ListenAndServe(":8000", nil)
}
需要導入 net/http/pprof 這個庫,這個庫會生成用于采集 profile 文件的接口,這里使用 /debug/pprof/profile 接口,通過請求這個接口來獲取程序運行時的數據。
1、 采集 profile 數據
訪問 http://localhost:8000/debug/pprof/profile?seconds=30,這里的意思是采集30秒的數據,期間需要訪問程序提供的功能接口,采集完成后將數據保存到程序主目錄下,命名為?default.pgo(編譯的時候,設置?-pgo?選項的值為 auto,會自動查找到此文件,使用起來更方便)
2、編譯時啟用 PGO 優化
編譯的時候帶上?-pgo 參數并且將值設置為 auto(也可以指定具體的文件),如下:
$ go build -pgo=auto -o markdown.withpgo
Golang 官方推薦使用 auto ,并且把 default.pgo 文件存放在程序主目錄下維護,以方便項目的其他開發者使用 default.pgo 來對程序做性能優化。因為 PGO 是從 Go 1.20 開始引入的,所以需要將 Golang 升級到 1.20 及以上。