日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

go Test Benchmark 性能测试

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 go Test Benchmark 性能测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

go 性能測試

基準測試

基準測試主要是通過測試CPU和內存的效率問題,來評估被測試代碼的性能,進而找到更好的解決方案。

編寫基準測試

func BenchmarkSprintf(b *testing.B){num:=10b.ResetTimer()for i:=0;i<b.N;i++{fmt.Sprintf("%d",num)} }
  • 基準測試的代碼文件必須以_test.go結尾
  • 基準測試的函數必須以Benchmark開頭,必須是可導出的
  • 基準測試函數必須接受一個指向Benchmark類型的指針作為唯一參數
  • 基準測試函數不能有返回值
  • b.ResetTimer是重置計時器,這樣可以避免for循環之前的初始化代碼的干擾
  • 最后的for循環很重要,被測試的代碼要放到循環里
  • b.N是基準測試框架提供的,表示循環的次數,因為需要反復調用測試的代碼,才可以評估性能
  • ? go test -bench=. -run=none BenchmarkSprintf-8 20000000 117 ns/op PASS ok flysnow.org/hello 2.474s

    使用?go test?命令,加上?-bench=?標記,接受一個表達式作為參數,?.表示運行所有的基準測試

    因為默認情況下?go test?會運行單元測試,為了防止單元測試的輸出影響我們查看基準測試的結果,可以使用-run=匹配一個從來沒有的單元測試方法,過濾掉單元測試的輸出,我們這里使用none,因為我們基本上不會創建這個名字的單元測試方法。

    也可以使用?-run=^$, 匹配這個規則的,但是沒有,所以只會運行benchmark

    go test -bench=. -run=^$

    有些時候在benchmark之前需要做一些準備工作,并且,我們不希望這些準備工作納入到計時里面,我們可以使用 b.ResetTimer(),代表重置計時為0,以調用時的時刻作為重新計時的開始。

    看到函數后面的-8了嗎?這個表示運行時對應的GOMAXPROCS的值。

    接著的20000000表示運行for循環的次數也就是調用被測試代碼的次數

    最后的117 ns/op表示每次需要話費117納秒。(執行一次操作話費的時間)

    以上是測試時間默認是1秒,也就是1秒的時間,調用兩千萬次,每次調用花費117納秒。

    如果想讓測試運行的時間更長,可以通過-benchtime指定,比如3秒。

    ? hello go test -bench=. -benchtime=3s -run=none // Benchmark 名字 - CPU 循環次數 平均每次執行時間 BenchmarkSprintf-8 50000000 109 ns/op PASS // 哪個目錄下執行go test 累計耗時 ok flysnow.org/hello 5.628s

    可以發現,我們加長了測試時間,測試的次數變多了,但是最終的性能結果:每次執行的時間,并沒有太大變化。一般來說這個值最好不要超過3秒,意義不大。

    性能對比

    上面那個基準測試的例子,其實是一個int類型轉為string類型的例子,標準庫里還有幾種方法,我們看下哪種性能更加.

    func BenchmarkSprintf(b *testing.B){num:=10b.ResetTimer()for i:=0;i<b.N;i++{fmt.Sprintf("%d",num)} }func BenchmarkFormat(b *testing.B){num:=int64(10)b.ResetTimer()for i:=0;i<b.N;i++{strconv.FormatInt(num,10)} }func BenchmarkItoa(b *testing.B){num:=10b.ResetTimer()for i:=0;i<b.N;i++{strconv.Itoa(num)} } ? hello go test -bench=. -run=none BenchmarkSprintf-8 20000000 117 ns/op BenchmarkFormat-8 50000000 33.3 ns/op BenchmarkItoa-8 50000000 34.9 ns/op PASS ok flysnow.org/hello 5.951s

    從結果上看strconv.FormatInt函數是最快的,其次是strconv.Itoa,然后是fmt.Sprintf最慢,前兩個函數性能達到了最后一個的3倍多。那么最后一個為什么這么慢的,我們再通過-benchmem找到根本原因。

    ? hello go test -bench=. -benchmem -run=none BenchmarkSprintf-8 20000000 110 ns/op 16 B/op 2 allocs/op BenchmarkFormat-8 50000000 31.0 ns/op 2 B/op 1 allocs/op BenchmarkItoa-8 50000000 33.1 ns/op 2 B/op 1 allocs/op PASS ok flysnow.org/hello 5.610s

    -benchmem可以提供每次操作分配內存的次數,以及每次操作分配的字節數。從結果我們可以看到,性能高的兩個函數,每次操作都是進行1次內存分配,而最慢的那個要分配2次;性能高的每次操作分配2個字節內存,而慢的那個函數每次需要分配16字節的內存。從這個數據我們就知道它為什么這么慢了,內存分配都占用都太高。

    在代碼開發中,對于我們要求性能的地方,編寫基準測試非常重要,這有助于我們開發出性能更好的代碼。不過性能、可用性、復用性等也要有一個相對的取舍,不能為了追求性能而過度優化。

    結合 pprof

    pprof 性能監控

    package bench import "testing" func Fib(n int) int {if n < 2 {return n}return Fib(n-1) + Fib(n-2) } func BenchmarkFib10(b *testing.B) {// run the Fib function b.N timesfor n := 0; n < b.N; n++ {Fib(10)} } go test -bench=. -benchmem -cpuprofile profile.out

    還可以同時看內存

    go test -bench=. -benchmem -memprofile memprofile.out -cpuprofile profile.out

    然后就可以用輸出的文件使用pprof

    go tool pprof profile.out File: bench.test Type: cpu Time: Apr 5, 2018 at 4:27pm (EDT) Duration: 2s, Total samples = 1.85s (92.40%) Entering interactive mode (type "help" for commands, "o" for options) (pprof) top Showing nodes accounting for 1.85s, 100% of 1.85s totalflat flat% sum% cum cum%1.85s 100% 100% 1.85s 100% bench.Fib0 0% 100% 1.85s 100% bench.BenchmarkFib100 0% 100% 1.85s 100% testing.(*B).launch0 0% 100% 1.85s 100% testing.(*B).runN

    這個是使用cpu 文件, 也可以使用內存文件

    然后你也可以用list命令檢查函數需要的時間

    (pprof) list Fib1.84s 2.75s (flat, cum) 148.65% of Total. . 1:package bench. . 2:. . 3:import "testing". . 4:530ms 530ms 5:func Fib(n int) int {260ms 260ms 6: if n < 2 {130ms 130ms 7: return n. . 8: }920ms 1.83s 9: return Fib(n-1) + Fib(n-2). . 10:}

    或者使用web命令生成圖像(png,pdf,...)

    報錯:Failed to execute dot. Is Graphviz installed? Error: exec: "dot": executable file not found in %PATH%

    是你電腦沒有安裝gvedit導致的

    fq進入gvedit官網https://graphviz.gitlab.io/_pages/Download/Download_windows.html?下載穩定版

    mac 安裝, 安裝好后就可以使用web進行展現了

    brew install graphviz

    火焰圖

    火焰圖(Flame Graph)是 Bredan Gregg 創建的一種性能分析圖表,因為它的樣子近似火焰而得名。

    火焰圖 svg 文件可以通過瀏覽器打開,它對于調用圖的最優點是它是動態的:可以通過點擊每個方塊來 zoom in 分析它上面的內容。

    火焰圖的調用順序從下到上,每個方塊代表一個函數,它上面一層表示這個函數會調用哪些函數,方塊的大小代表了占用 CPU 使用的長短。火焰圖的配色并沒有特殊的意義,默認的紅、黃配色是為了更像火焰而已。

    runtime/pprof分析項目, 會在當前文件夾內導出profile文件。然后用火焰圖去分析,就不能指定域名了,要指定文件。

    go-torch

    網上介紹大部分使用uber的開源工具

    go-torch。這是 uber 開源的一個工具,可以直接讀取 golang profiling 數據,并生成一個火焰圖的 svg 文件。

    go-torch 工具的使用非常簡單,沒有任何參數的話,它會嘗試從?http://localhost:8080/debug/pprof/profile?獲取 profiling 數據。它有三個常用的參數可以調整:

    • -u --url:要訪問的 URL,這里只是主機和端口部分
    • -s --suffix:pprof profile 的路徑,默認為 /debug/pprof/profile
    • --seconds:要執行 profiling 的時間長度,默認為 30s

    原生支持

    從 Go 1.11 開始, 火焰圖被集成進入 Go 官方的 pprof 庫.

    # This will listen on :8081 and open a browser. # Change :8081 to a port of your choice. $ go tool pprof -http=":8081" [binary] [profile]

    如果低于1.11版本那么請從git pprof

    # Get the pprof tool directly $ go get -u github.com/google/pprof$ pprof -http=":8081" [binary] [profile]

    pprof README.md

    一個web 小例子

    package mainimport ("fmt""log""net/http"_ "net/http/pprof""time" )func sayHelloHandler(w http.ResponseWriter, r *http.Request) {hellowold(10000)fmt.Println("path", r.URL.Path)fmt.Println("scheme", r.URL.Scheme)fmt.Fprintf(w, "Hello world!\n") //這個寫入到w的是輸出到客戶端的 }func main() {http.HandleFunc("/", sayHelloHandler) // 設置訪問路由log.Fatal(http.ListenAndServe(":8080", nil)) }func hellowold(times int) {time.Sleep(time.Second)var counter intfor i := 0; i < times; i++ {for j := 0; j < times; j++ {counter++}} }

    使用下面的命令開啟監控,然后訪問幾次localhost:8080

    go tool pprof -http=":8081" http://localhost:8080/debug/pprof/profile

    過一會兒會產生個web窗口, 選擇 VIEW->Flame Graph 得到火焰圖形

    http://localhost:8081/ui/flamegraph

    Testing flags

    go 測試后面可以跟哪些參數

    Testing flags

    常用flag

    • -bench regexp:性能測試,支持表達式對測試函數進行篩選。-bench .則是對所有的benchmark函數測試
    • -benchmem:性能測試的時候顯示測試函數的內存分配的統計信息
    • -count n:運行測試和性能多少此,默認一次
    • -run regexp:只運行特定的測試函數, 比如-run ABC只測試函數名中包含ABC的測試函數
    • -timeout t:測試時間如果超過t, panic,默認10分鐘
    • -v:顯示測試的詳細信息,也會把Log、Logf方法的日志顯示出來

    Go 1.7中開始支持?sub-test的概念。

    測試注意和調優

    golang性能測試與調優

    • 避免頻繁調用timer
    • 避免測試數據過大

    參考

    Go語言實戰筆記(二十一)| Go 單元測試

    Go語言實戰筆記(二十二)| Go 基準測試

    Profile your golang benchmark with pprof

    深入Go語言 - 12

    Go單元測試&性能測試

    golang性能測試與調優

    go pprof 性能分析

    go tool pprof

    Go 性能測試工具PProf--火焰圖

    PS: 覺得不錯的請點個贊吧!! (? ??_??)?

    總結

    以上是生活随笔為你收集整理的go Test Benchmark 性能测试的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。