Maison  >  Article  >  développement back-end  >  Un outil d’analyse comparative de référence

Un outil d’analyse comparative de référence

Go语言进阶学习
Go语言进阶学习avant
2023-07-21 13:11:051049parcourir
Dans Go, vous pouvez facilement effectuer des tests de performances sur un certain point de fonction en écrivant une fonction Benchmark. Pour les fonctions importantes, nous pouvons ajouter des processus de test correspondants dans CI/CD pour détecter les changements dans les performances des fonctions en temps opportun. Se pose alors la question : comment détecter les changements de performances de la fonction ?

En d'autres termes, vous avez écrit une certaine fonction mais avez constaté qu'elle s'exécute très lentement et vous devez optimiser la fonction lorsque vous effectuez une recherche sur Google pour trouver une meilleure implémentation, vous constatez qu'elle est effectivement devenue plus rapide. via la fonction Benchmark. Mais vous ne pouvez pas dire à quel point il est devenu plus rapide. Vous voulez connaître la comparaison des performances avant et après l'optimisation des fonctions, de combien de points de pourcentage elle s'est améliorée et est-elle très fiable ?

Pour les scénarios de demande ci-dessus, il existe un outil qui peut vous aider, c'est benchstat.

Exemple de référence

Examinons d'abord le benchmark. Pour faciliter la compréhension, nous prenons ici comme exemple le calcul classique des valeurs de séquence de Fibonacci.

func FibSolution(n int) int {
 if n < 2 {
  return n
 }

 return FibSolution(n-1) + FibSolution(n-2)
}

Le code ci-dessus est une implémentation récursive. Évidemment, lorsque n devient de plus en plus grand, le fonctionnement de cette fonction deviendra très long. En prenant n comme exemple 20, la fonction Benchmark est la suivante

func BenchmarkFib20(b *testing.B) {
 for i := 0; i < b.N; i++ {
  FibSolution(20)
 }
}

Exécution de la ligne de commande<code style='font-size: 14px;overflow-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin-right: 2px;margin-left: 2px;font-family: "Operator Mono", Consolas, Monaco, Menlo, monospace;word-break: break-all;background: rgba(14, 210, 247, 0.15);'><span style="font-size: 15px;">go test -bench=BenchmarkFib20</span>go test -bench=BenchmarkFib20Obtenez des résultats de performances

🎜
BenchmarkFib20-8           39452             30229 ns/op

其中,-8 代表的是 8 cpu,函数运行次数为 39452,每次函数的平均花费时间为 30229ns。如果我们想得到多次样本数据,可以指定 go test 的 <span style="font-size: 15px;">-count=N</span> 参数。例如想得到 5 次样本数据,则执行<span style="font-size: 15px;">go test -bench=BenchmarkFib20 -count=5</span>

BenchmarkFib20-8           39325             30297 ns/op
BenchmarkFib20-8           39216             30349 ns/op
BenchmarkFib20-8           39901             30251 ns/op
BenchmarkFib20-8           39336             30455 ns/op
BenchmarkFib20-8           39423             30894 ns/op

计算斐波那契数列值的迭代式实现如下

func FibSolution(n int) int {
 if n < 2 {
  return n
 }
 p, q, r := 0, 0, 1
 for i := 2; i <= n; i++ {
  p = q
  q = r
  r = p + q
 }
 return r
}

对比这两种函数的性能差异,最朴素的方式就是分别对这两个函数进行基准测试,然后通过手工分析这些基准测试结果,但是这并不直观。

benchstat

benchstat 是 Go 官方推荐的一款命令行工具,它用于计算和比较基准测试的相关统计数据。

我们可以通过以下命令进行安装

go install golang.org/x/perf/cmd/benchstat@latest

执行 -h 参数可以看到该工具的使用描述

~ $ benchstat -h
usage: benchstat [options] old.txt [new.txt] [more.txt ...]
options:
  -alpha α
     consider change significant if p < α (default 0.05)
  -csv
     print results in CSV form
  -delta-test test
     significance test to apply to delta: utest, ttest, or none (default "utest")
  -geomean
     print the geometric mean of each file
  -html
     print results as an HTML table
  -norange
     suppress range columns (CSV only)
  -sort order
     sort by order: [-]delta, [-]name, none (default "none")
  -split labels
     split benchmarks by labels (default "pkg,goos,goarch")

我们想比较 FibSolution(n) 从 15 到 20,两种实现方式的性能基准测试。

$ go test -bench=. -count=5 | tee old.txt
$ go test -bench=. -count=5 | tee new.txt

注意,这两条命令执行时,分别对应 FibSolution 函数采用递归式和迭代式实现逻辑。

此时,我们可以对这两个函数实现逻辑进行性能对比

 $ benchstat old.txt new.txt 
name     old time/op  new time/op  delta
Fib15-8  2.67µs ± 2%  0.01µs ± 5%  -99.81%  (p=0.008 n=5+5)
Fib16-8  4.20µs ± 1%  0.01µs ± 2%  -99.87%  (p=0.008 n=5+5)
Fib17-8  6.81µs ± 0%  0.01µs ± 2%  -99.92%  (p=0.008 n=5+5)
Fib18-8  11.1µs ± 1%   0.0µs ± 1%  -99.95%  (p=0.008 n=5+5)
Fib19-8  18.0µs ± 2%   0.0µs ± 4%  -99.97%  (p=0.008 n=5+5)
Fib20-8  29.2µs ± 1%   0.0µs ± 3%  -99.98%  (p=0.008 n=5+5)

可以看到,递归式实现的函数,他的执行时间随着 n 值变大增加非常明显。迭代式实现方式,相较于递归式,它的平均时间开销降低了 99 % 以上,优化效果非常明显。

另外,p=0.008 表示结果的可信程度,p 值越大表明可信度越低。一般以 0.05 作为临界值,超过该值,则结果不可信。n=5+5 表示分别使用的有效样本数量。

Résumé

benchstat est un outil statistique de référence qui peut être utilisé pour réduire le coût de l'analyse manuelle des données lorsque nous effectuons des travaux d'optimisation.

Si votre projet déploie des tests automatisés dans le processus CI/CD, vous souhaiterez peut-être ajouter cet outil. Lorsque des modifications sont apportées à des fonctions qui augmentent la perte de performances, cela peut vous aider à détecter les problèmes à l'avance.


Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer

Articles Liés

Voir plus