地鼠们你好?
在这篇博文中,我将向您展示如何使用 #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.
这个序列很重要,因为它也出现在数学和自然的多个部分中,如下所示:
有多种方法可以实现此代码,我将选择两种方法进行基准测试:计算它的递归方法和迭代方法。这些函数的主要目标是提供位置并返回该位置的斐波那契数。
// 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
让我们借助这张图来分析一下:
根据图像,我们有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中文网其他相关文章!