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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

go Test Benchmark 性能测试

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

go 性能測試

基準(zhǔn)測試

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

編寫基準(zhǔn)測試

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

    使用?go test?命令,加上?-bench=?標(biāo)記,接受一個表達(dá)式作為參數(shù),?.表示運行所有的基準(zhǔn)測試

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

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

    go test -bench=. -run=^$

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

    看到函數(shù)后面的-8了嗎?這個表示運行時對應(yīng)的GOMAXPROCS的值。

    接著的20000000表示運行for循環(huán)的次數(shù)也就是調(diào)用被測試代碼的次數(shù)

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

    以上是測試時間默認(rèn)是1秒,也就是1秒的時間,調(diào)用兩千萬次,每次調(diào)用花費117納秒。

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

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

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

    性能對比

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

    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

    從結(jié)果上看strconv.FormatInt函數(shù)是最快的,其次是strconv.Itoa,然后是fmt.Sprintf最慢,前兩個函數(shù)性能達(dá)到了最后一個的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可以提供每次操作分配內(nèi)存的次數(shù),以及每次操作分配的字節(jié)數(shù)。從結(jié)果我們可以看到,性能高的兩個函數(shù),每次操作都是進行1次內(nèi)存分配,而最慢的那個要分配2次;性能高的每次操作分配2個字節(jié)內(nèi)存,而慢的那個函數(shù)每次需要分配16字節(jié)的內(nèi)存。從這個數(shù)據(jù)我們就知道它為什么這么慢了,內(nèi)存分配都占用都太高。

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

    結(jié)合 pprof

    pprof 性能監(jiān)控

    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

    還可以同時看內(nèi)存

    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 文件, 也可以使用內(nèi)存文件

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

    (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導(dǎo)致的

    fq進入gvedit官網(wǎng)https://graphviz.gitlab.io/_pages/Download/Download_windows.html?下載穩(wěn)定版

    mac 安裝, 安裝好后就可以使用web進行展現(xiàn)了

    brew install graphviz

    火焰圖

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

    火焰圖 svg 文件可以通過瀏覽器打開,它對于調(diào)用圖的最優(yōu)點是它是動態(tài)的:可以通過點擊每個方塊來 zoom in 分析它上面的內(nèi)容。

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

    runtime/pprof分析項目, 會在當(dāng)前文件夾內(nèi)導(dǎo)出profile文件。然后用火焰圖去分析,就不能指定域名了,要指定文件。

    go-torch

    網(wǎng)上介紹大部分使用uber的開源工具

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

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

    • -u --url:要訪問的 URL,這里只是主機和端口部分
    • -s --suffix:pprof profile 的路徑,默認(rèn)為 /debug/pprof/profile
    • --seconds:要執(zhí)行 profiling 的時間長度,默認(rèn)為 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) // 設(shè)置訪問路由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++}} }

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

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

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

    http://localhost:8081/ui/flamegraph

    Testing flags

    go 測試后面可以跟哪些參數(shù)

    Testing flags

    常用flag

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

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

    測試注意和調(diào)優(yōu)

    golang性能測試與調(diào)優(yōu)

    • 避免頻繁調(diào)用timer
    • 避免測試數(shù)據(jù)過大

    參考

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

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

    Profile your golang benchmark with pprof

    深入Go語言 - 12

    Go單元測試&性能測試

    golang性能測試與調(diào)優(yōu)

    go pprof 性能分析

    go tool pprof

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

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

    總結(jié)

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

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。