go通过benchmark对代码进行性能测试详解

Go通过Benchmark对代码进行性能测试详解

前言

性能是软件开发中的一个重要指标,因为良好的性能可以提高软件的运行效率,增强用户体验。在Go语言中,有一种叫做benchmark的工具可以用来测试代码在特定条件下的性能表现。在本文中,我们将介绍如何使用Go的benchmark工具进行性能测试。

创建Benchmark函数

在Go语言中,一个benchmark测试函数必须满足以下要求:

  • 函数名称以Benchmark开头;
  • 函数有一个参数类型为*testing.B;
  • 函数头部必须包含t.ResetTimer(),用于重置计时器;
  • 函数头部必须包含t.StartTimer(),用于启动计时器;
  • 函数尾部必须包含t.StopTimer(),用于停止计时器。

以下是实现一个简单的benchmark测试的示例:

package main

import (
    "math/rand"
    "testing"
)

func BenchmarkRandomInt(b *testing.B) {
    for i := 0; i < b.N; i++ {
        rand.Intn(100)
    }
}

在上面的示例中,我们编写了一个名为BenchmarkRandomInt的测试函数,每次循环通过rand.Intn(100)生成一个随机整数。接下来,我们将演示该函数如何执行benchmark测试。

运行Benchmark测试

运行benchmark测试非常简单,只需要在终端中使用命令go test -bench=.即可。其中,-bench参数用于指定要运行的Benchmark测试函数的名称,点号表示运行所有的Benchmark测试函数。运行结果如下所示:

goos: darwin
goarch: amd64
pkg: github.com/mysite/myapp
BenchmarkRandomInt-4     2000000           713 ns/op
PASS
ok      github.com/mysite/myapp 2.449s

从上面的输出结果可以看出,BenchmarkRandomInt函数执行了2000000次,每次执行的平均时间为713纳秒(ns)。除了平均时间之外,还有很多其他信息可以帮助我们评估代码的性能表现,比如每个测试用例的执行时间、内存分配量等等。

示例说明

示例一

以下是一个基于切片实现的简单排序算法的代码:

package main

import (
    "fmt"
)

func bubbleSort(array []int) {
    for i := 0; i < len(array)-1; i++ {
        for j := 0; j < len(array)-i-1; j++ {
            if array[j] > array[j+1] {
                array[j], array[j+1] = array[j+1], array[j]
            }
        }
    }
}

func main() {
    array := []int{5, 3, 6, 2, 9}
    bubbleSort(array)
    fmt.Println(array)
}

为了测试这个排序算法的性能,我们编写一个benchmark测试函数BenchmarkBubbleSort,测试该算法对于1000个随机整数的处理时间:

func BenchmarkBubbleSort(b *testing.B) {
    data := make([]int, 1000)
    for i := 0; i < 1000; i++ {
        data[i] = rand.Intn(1000)
    }
    for i := 0; i < b.N; i++ {
        bubbleSort(data)
    }
}

运行测试命令go test -bench=BubbleSort -run=^$ -benchtime=3s -cpu=1,2,4,8,其中-benchtime用于指定执行时间,-cpu用于指定CPU核心数量。执行结果如下所示:

BenchmarkBubbleSort-4         179547         20653 ns/op
BenchmarkBubbleSort-4         740131          4099 ns/op
BenchmarkBubbleSort-4    2398084          1422 ns/op
BenchmarkBubbleSort-4    3041276           995 ns/op

从上述结果可以看出,在不同CPU核心数量下,测试函数的执行时间和操作次数是相应变化的。

示例二

考虑以下的常规任务:

  • 从一个列表中随机选择一个元素。
  • 如果选择的元素小于10,则将它除以10,否则将它乘以2。
  • 对结果取整后返回。

接下来,我们将定义一个带有三个步骤的函数,然后将进行好几次关于这个函数的基准测试。使用下面的代码创建函数和基准测试:

func TestChooser(t *testing.T) {
    tests := []struct {
        desc     string
        items    []int
        expected int
    }{
        {"returns a number below 10 unmodified", []int{2, 4, 6, 8}, 2},
        {"scales a number above 10", []int{16, 20, 40, 80}, 32},
        {"test10x", bigList, 42},
        {"test100x", hugeList, 42},
    }
    for _, test := range tests {
        t.Run(test.desc, func(t *testing.T) {
            rando := func() int { return test.items[rand.Intn(len(test.items))] }
            if v := choose(rando, rand.Intn); v != test.expected {
                t.Errorf("got %d, want %d", v, test.expected)
            }
        })
    }
}

func BenchmarkChooser(b *testing.B) {
    for i := 0; i < b.N; i++ {
        choose(rand.Intn, rand.Intn)
    }
}

func BenchmarkChooserAbove10(b *testing.B) {
    for i := 0; i < b.N; i++ {
        choose(scaledIntGen(10, 20), scaledIntGen(20, 40))
    }
}

func BenchmarkChooserAbove100(b *testing.B) {
    for i := 0; i < b.N; i++ {
        choose(scaledIntGen(100, 200), scaledIntGen(200, 400))
    }
}

var bigList []int
var hugeList []int

func init() {
    var maxI int
    if testing.Short() {
        maxI = 10000
    } else {
        maxI = 100000
    }
    bigList = make([]int, maxI)
    hugeList = make([]int, maxI*10)
    for i := 0; i < maxI*10; i++ {
        hugeList[i] = rand.Int()
    }
    for i := 0; i < maxI; i++ {
        bigList[i] = i
    }
}

func scaledIntGen(low, high int) func() int {
    return func() int {
        if rand.Intn(2) == 1 {
            return rand.Intn(low)
        }
        return rand.Intn(high) + low
    }
}

func choose(getter1 func() int, getter2 func() int) int {
    i := getter1()
    if i < 10 {
        i *= 10
    } else {
        i *= 2
    }
    j := getter2()
    if j < 10 {
        j *= 10
    } else {
        j *= 2
    }
    return (i + j) / 2
}

运行测试的命令是:

go test -bench=. -benchtime=1000x

这个输出的结果是:

BenchmarkChooser-4            1000          8167780 ns/op
BenchmarkChooserAbove10-4     1000          8243747 ns/op
BenchmarkChooserAbove100-4    1000          8212555 ns/op

上述的输出告诉我们,一千个运行时间中,分别花费了 8167780ns(0.00816毫秒)、8243747ns(0.00824毫秒)和 8212555(0.00821毫秒)。

结论

在本文中,我们详细讲解了如何使用Go语言的benchmark工具对代码进行性能测试,包括Benchmark测试函数的创建、运行Benchmark测试以及两个示例说明。性能测试是编写高质量代码的基本要求之一,希望这篇文章能够帮助你更好地学习和使用Go语言。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:go通过benchmark对代码进行性能测试详解 - Python技术站

(0)
上一篇 2023年5月25日
下一篇 2023年5月25日

相关文章

  • PyTorch 1.0 正式版已经发布了

    下面是详细的攻略。 PyTorch 1.0 正式版发布攻略 什么是 PyTorch? PyTorch 是一个开源的 Python 机器学习框架,由 Facebook AI Research 开发和维护。它是一个动态计算图框架,提供了一系列易用的工具和接口,以便于研究人员和开发者进行快速的原型设计和部署。 PyTorch 1.0 正式版有哪些新特性? PyTo…

    人工智能概览 2023年5月25日
    00
  • 网站如何通过nginx设置黑/白名单IP限制及国家城市IP访问限制

    Sure!下面我来简单介绍一下网站如何通过nginx设置黑/白名单IP限制及国家城市IP访问限制的完整攻略。 1.安装GeoIP2模块 首先要安装GeoIP2模块。GeoIP2可以根据IP地址查找与它相关的地理信息,包括国家、省份、城市、经纬度等等。这个模块对于限制来自某些国家或城市的访问非常有用。 sudo apt-get install libgeoip…

    人工智能概览 2023年5月25日
    00
  • Docker 部署HAProxy v2.2.29 并暴露指标接口的问题解决

    下面我将详细讲解“Docker 部署HAProxy v2.2.29 并暴露指标接口的问题解决”的完整攻略。 准备工作 首先需要安装Docker,如果已经安装可以跳过这一步。 示例一:在Ubuntu系统上安装Docker # 添加Docker GPG密钥 curl -fsSL https://download.docker.com/linux/ubuntu/g…

    人工智能概览 2023年5月25日
    00
  • Qt生成随机数的方法

    生成随机数是很多计算机程序都需要的功能之一。在 Qt 中,我们可以通过以下几种方式来生成随机数: 1. 使用 Qt 提供的 QRandomGenerator 类 QRandomGenerator 类可以生成质量较高的随机数序列。它在 Qt 5.10 中引入,在 Qt 6 中成为标准类。我们可以通过 QRandomGenerator::global() 来获取…

    人工智能概览 2023年5月25日
    00
  • 在Ubuntu系统上安装Nginx服务器的简单方法

    下面我将为你详细讲解在Ubuntu系统上安装Nginx服务器的简单方法的攻略。 准备工作 在安装Nginx服务器之前,你需要先确保你的Ubuntu系统是最新的,可以通过以下命令来升级系统: sudo apt update sudo apt upgrade 安装Nginx 在Ubuntu系统上安装Nginx服务器非常简单,只需要在终端中输入以下命令即可: su…

    人工智能概览 2023年5月25日
    00
  • PyTorch梯度裁剪避免训练loss nan的操作

    PyTorch梯度裁剪是一种用于避免训练过程中出现loss为nan的问题,其通过限制模型的参数梯度范围来提高训练稳定性和收敛效果。以下是PyTorch梯度裁剪的完整攻略: 什么是梯度裁剪 梯度裁剪是一种通过限制参数梯度范围的方法,防止训练过程中出现梯度爆炸或梯度消失的情况。这种现象常常发生在深层神经网络中,尤其是在使用长短时记忆网络(LSTM)等循环神经网络…

    人工智能概论 2023年5月25日
    00
  • 使Nginx服务器支持.htaccess的方法

    要使 Nginx 服务器支持 .htaccess 文件,可以通过以下步骤进行设置: 步骤一:安装 Nginx 首先需要安装 Nginx,具体安装方法可以参考官方文档或者相应的安装教程。 步骤二:修改 Nginx 配置文件 编辑 Nginx 的配置文件,一般在 /etc/nginx/nginx.conf 位置,找到以下代码段: server { listen …

    人工智能概览 2023年5月25日
    00
  • java如何用Processing生成马赛克风格的图像

    下面是关于“Java如何用Processing生成马赛克风格的图像”的完整攻略: 1. 确认环境 在做这个案例前,需要先确认自己的开发环境是否搭建好了Processing。如果还没有,则需要先到Processing官网上下载最新的版本,并安装好。 2. 导入图像 首先,需要在Processing中导入一张待处理的图像,使用的函数是loadImage()。示例…

    人工智能概论 2023年5月25日
    00
合作推广
合作推广
分享本页
返回顶部