天天看點

聊一聊 golang 的測試與性能調優

聊一聊 golang 的測試與性能調優

背景:上周技術三面被面試官問道golang中如何做測試和性能優化,一時間沒有反應過來, 不過還好沒挂。 特此記錄一貼,系統地講解 golang 中如何做測試,如何查找性能瓶頸。

測試的分類

說到測試,一般有兩種:單例測試和壓力測試。

所謂單例測試就是拿着一些測試用例依次去測試一下,強調的是通過與不通過的問題。

而壓力測試則是挑一些特别複雜,極端的測試用例多次重複地進行測試,強調地是性能上的問題。

golang 中通過 testing.T 和 testing.B 能夠很好的支援 單例測試和壓力測試。

寫一個簡單的被測試函數

package test

func Add(a,b int) int  {
   return a+b
}
           

寫一個單例測試函數

golang 的測試函數命名是有規範的,以Test打頭,後面緊跟被測函數名。如果在IDE中,當你寫完Test加被測函數的首字母時應該會有補全提示的。

package test

import (
   "testing"
)

func TestAdd(t *testing.T) {

   testCases := []struct{
      a int
      b int
      c int
   }{
      {3,2,1 },
      {10,5,5},
      { 1000000,1,999999},
   }

   for _, testCase := range testCases{
      if result:=Add(testCase.b,testCase.c); result!=testCase.a{
         t.Errorf("Expected get %d, but got: %d ", testCase.a, result)
      }
   }
}
           

當一個函數的參數為 testing.T時,同樣标志着這是一個單例測試函數。

随後我們可以直接在IDE 中點選函數旁邊的小三角進行運作, 也可以在指令行中輸入

go test -run TestAdd
           

這條指令會 指定測試 哪一個函數,如果想要測試目前包下的所有測試函數,也可以用下面這條指令

go test .
           

寫一個壓力測試函數

說完單例測試,該說壓力測試了。在剛剛的 TestAdd 下面寫一個 BenchmarkAdd 函數。

同樣的壓力測試函數也是有命名規則的,以Benchmark打頭,接上被測試函數的名字, 并且參數wei tesing.B 。同樣的,若果你在IDE中,寫完 Bench 也應該會有代碼補全提示。

func BenchmarkAdd(b *testing.B) {

   b.ResetTimer()
   for i := 0; i<b.N;i++  {
      if result:=Add(1,9999999); result !=10000000 {
         b.Errorf("Expected get %d, but got: %d ", 10000000 , result)
      }
   }
}
           

壓力測試同樣也可以在IDE中函數旁邊的小三角運作,但更多的使用的是指令行。可以使用下面兩條指令的任意一種。差別隻在于第一條指令指定了運作哪一個函數,第二條指令運作所有壓測函數。

go test -bench  BenchmarkAdd  -cpuprofile cpu.out
go test -bench  .  -cpuprofile cpu.out
           

go test -bench 函數名 指明了測試哪一個函數。 後面的 -cpuprofile cpu.out 則說明了監控CPU運作時的狀态并且輸出到了 一個 cpu.out 檔案。

安裝 graphviz

想要看這個 cpu.out 檔案需要用到一個 graphviz的插件,大家可以去官網直接下載下傳對應的版本即可。 下載下傳完成後将安裝目錄下的 bin 目錄加到環境變量中, 重新開機即可。如果不重新開機,在IDE中可能仍然無法使用,這是個大坑。 重新開機完成後在指令行輸入下面這條指令如果有輸出graphviz資訊,說明安裝成功

dot -version
           

回到剛剛的壓力測試,在輸出的 cpu.out 路徑下輸入下面這行指令:

go tool pprof cpu.out
           

然後會進入到 pprof 指令行, 我們可以輸入 web , 那麼則會彈出浏覽器得到一張圖,詳細展示了 運作過程中每一個函數的消耗時間。

聊一聊 golang 的測試與性能調優

你可能會好奇這張圖怎麼看。細節我也不太會,但是你隻要看到框框越大,顔色越紅,就代表這個函數消耗時間越多。

你也可以在 pprof 的指令行中輸入 top 獲得排名靠前的資源消耗函數。結果大概張這樣

Showing nodes accounting for 170ms, 100% of 170ms total
      flat  flat%   sum%        cum   cum%
     160ms 94.12% 94.12%      160ms 94.12%  GoBasic/test.BenchmarkAdd
      10ms  5.88%   100%       10ms  5.88%  runtime.stdcall3
         0     0%   100%       10ms  5.88%  runtime.(*pageAlloc).scavenge
         0     0%   100%       10ms  5.88%  runtime.(*pageAlloc).scavengeOne
         0     0%   100%       10ms  5.88%  runtime.(*pageAlloc).scavengeRangeLocked
         0     0%   100%       10ms  5.88%  runtime.bgscavenge.func2
         0     0%   100%       10ms  5.88%  runtime.sysUnused
         0     0%   100%       10ms  5.88%  runtime.systemstack
         0     0%   100%      160ms 94.12%  testing.(*B).launch
         0     0%   100%      160ms 94.12%  testing.(*B).runN
           

喜歡軟體測試的小夥伴們,如果我的部落格對你有幫助、如果你喜歡我的部落格内容,請 “點贊” “評論” “收藏” 一 鍵三連哦!

聊一聊 golang 的測試與性能調優
聊一聊 golang 的測試與性能調優

繼續閱讀