首頁  >  文章  >  後端開發  >  使用 Golang 進行基準測試

使用 Golang 進行基準測試

WBOY
WBOY原創
2024-09-05 21:31:03928瀏覽

你好地鼠?

在這篇文章中,我將向您展示如何使用 #golang 測試包中內建的出色工具。您將如何測試一段程式碼或函數的效能?使用基準測試。

我們走吧。

對於此測試,我將使用經典的斐波那契數列或斐波那契數列,它由以下因素決定:

if (x < 2) 
   F(0) = 1
   F(2) = 2
else 
   F(x) = F(x-1) + F(x-2)

In practice, the sequence is:
1, 1, 2, 3, 5, 8, 13, etc.

這個序列很重要,因為它也出現在數學和自然的多個部分中,如下所示:

Benchmark with Golang

有多種方法可以實現此程式碼,我將選擇兩種方法進行基準測試:計算它的遞歸方法和迭代方法。這些函數的主要目標是提供位置並傳回該位置的斐波那契數。

遞迴法

// main.go

func fibRecursive(n int) int {
    if n <= 2 {
        return 1
    }
    return fibRecursive(n-1) + fibRecursive(n-2)
}

迭代法

// main.go

func fibIterative(position uint) uint {
    slc := make([]uint, position)
    slc[0] = 1
    slc[1] = 1

    if position <= 2 {
        return 1
    }

    var result, i uint
    for i = 2; i < position; i++ {
        result = slc[i-1] + slc[i-2]
        slc[i] = result
    }

    return result
}

這些方法並未經過最佳化,但即使對於少數情況,測試結果也有顯著差異。您將在測試中看到這一點。若要跟隨程式碼進行操作,您可以點擊此處。

現在,對於基準測試,讓我們在 _main_test.go 檔案中寫一些測試。使用 Golang 的 benchmark 文檔,您可以建立要測試的函數,如下所示:

// main_test.go

// The key is to start every function you want to benchmark with the keyword Benchmark and use b *testing.B instead of t *testing.T as input 
func BenchmarkFibIterative(b *testing.B) {
    // Use this for-loop to ensure the code will behave correctly. 
    // Now, you can put the function or piece of code you want to test
    for i := 0; i < b.N; i++ { 
        fibIterative(uint(100))
    }
}

// Same as above
func BenchmarkFibRecursive(b *testing.B) {
    for i := 0; i < b.N; i++ {
        fibRecursive(100)
    }
}

在繼續之前先問一個問題:哪個比較快?

讓我們對一個較小的數字 (10) 和一個稍大的數字 (80) 進行測試。要執行基準測試,您只需執行指令:

go test -bench=函數名稱

如果您想了解更多有關此命令的信息,請查看此處。

第一次檢定:position=10

//(fibIterative)
Results:
cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibIterative-8         24491042                42.50 ns/op
PASS
ok      playground      1.651s

讓我們藉由這張圖來分析一下:

Benchmark with Golang

根據圖像,我們有8個核心用於測試,沒有時間限制(它將運行到完成)。花了1.651s完成任務。

==== Extra ====
We got 24,491,042 iterations (computations), and each iteration (op) took 42.50 ns.

Doing some math, we can calculate how much time one op took:

42.50 ns/op with 1 ns = 1/1,000,000,000 s
op ≈ 2.35270590588e-12 s
==== Extra ====

這是一個很好的結果。讓我們檢查一下位置 10 的遞歸函數:

// Results
BenchmarkFibRecursive-8          6035011               187.8 ns/op
PASS
ok      playground      1.882s

我們可以看到,完成任務花了1.882s

迭代函數以幾十分之一的優勢獲勝。讓我們再試試一項測驗:

位置 50

// Results for the Iterative Function

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibIterative-8         27896118                45.37 ns/op
PASS
ok      playground      2.876s

// Results for the Recursive Function

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibRecursive-8          6365198               186.3 ns/op
PASS
ok      playground      1.918s

哇!現在遞歸函數更快了?

讓我們以稍微大一點的數字來結束。

位置 80

// Results for the Iterative Function

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibIterative-8          5102344               229.5 ns/op
PASS
ok      playground      1.933s

// Results for the Recursive Function
// My poor PC couldn’t handle it, so I had to reduce the position to 50 just to get some results printed.

cpu: Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
BenchmarkFibRecursive-8                1        44319299474 ns/op
PASS
ok      playground      44.951s

差異是巨大的。對於位置 80,迭代方法大約需要 2 秒。對於位置 50,遞歸函數花費了大約 45 秒。這證明了當您的 Golang 專案開始變慢時對程式碼進行基準測試的重要性。

結論

如果您的生產程式碼運行緩慢或不可預測地變慢,您可以使用此技術,結合pprof 或內建測試包中的其他工具來識別和測試程式碼的執行位置不好以及如何優化它。

附註:並非所有看起來漂亮的程式碼都具有更高的效能。

額外運動

你能找到更好的方法來改進遞歸函數嗎? (提示:使用動態規劃)。本文解釋了為什麼對於一些小數字,遞歸策略會更好。

以上是使用 Golang 進行基準測試的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn