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日

相关文章

  • Django–权限Permissions的例子

    下面是关于Django中权限Permissions的例子的详细攻略。 1. 什么是Permissions Permissions是Django中的一种权限控制系统。通过这个系统,我们可以根据用户的身份或者角色,对不同的访问控制进行限制。例如,我们可以设置只有管理员才能删除数据,而普通用户只能查看数据等等。 2. Permissions的应用 2.1 在视图函…

    人工智能概览 2023年5月25日
    00
  • 在PyCharm搭建OpenCV-python的环境的详细过程

    搭建OpenCV-python环境的过程如下: 步骤一:下载安装PyCharm 首先需要下载安装PyCharm,可以到PyCharm官网下载对应版本的PyCharm进行安装。 步骤二:创建Python项目 在PyCharm中创建一个Python项目,选择机器上已安装的Python版本,然后创建一个py文件。 步骤三:安装OpenCV-python 打开终端或…

    人工智能概论 2023年5月25日
    00
  • c#操作mongodb插入数据效率

    下面是关于C#操作MongoDB插入数据效率的完整攻略。 1.使用MongoDB.Driver库 要在C#中操作MongoDB,需要使用MongoDB.Driver库。可以通过nuget包管理器来安装MongoDB.Driver。 2.使用InsertOne和InsertMany方法 在MongoDB中插入数据可以使用InsertOne和InsertMany…

    人工智能概论 2023年5月25日
    00
  • node实现简单的增删改查接口实例代码

    让我们来详细讲解如何使用 Node.js 实现简单的增删改查接口,以下是完整攻略: 准备工作 在开始我们的实例代码前,需要先确保你已经完成了以下准备工作: 安装 Node.js 了解基本的 JavaScript 语法和操作 安装并掌握使用 Express 框架 新建项目并安装依赖 在你的本地环境中新建一个目录,进入该目录并初始化项目: mkdir myPro…

    人工智能概论 2023年5月24日
    00
  • tensorflow中next_batch的具体使用

    TensorFlow中的next_batch函数是一种数据集加载方式,它可以从总数据集中提取一部分数据用于训练。在神经网络训练中,我们通常将数据集分成训练集、验证集和测试集。其中,训练集用于训练模型,验证集用于验证模型的性能,测试集用于测试模型的泛化能力。next_batch函数可以从训练集中提取一部分数据用于训练,提高训练效率。 使用方法如下所述: 函数参…

    人工智能概论 2023年5月24日
    00
  • Python实现RGB与HSI颜色空间的互换方式

    Python可以通过使用colorsys模块来实现RGB和HSI颜色空间的互换,下面是具体的操作步骤: 安装模块 在Python中,colorsys模块是自带的,无需安装,您可以直接在代码中使用。 RGB转HSI 实现RGB到HSI颜色空间的转换,需要将RGB颜色空间中的Red、Green和Blue分量分别除以255,得到它们在0到1之间的值。 import…

    人工智能概览 2023年5月25日
    00
  • JPA使用乐观锁应对高并发方式

    使用乐观锁是一种解决高并发问题的有效方式,JPA也提供了相应的支持。 以下是使用JPA实现乐观锁的完整攻略: 什么是乐观锁? 乐观锁是一种并发控制的策略,它假设并发情况下的冲突是不常见的,因此只是在需要保存数据时去检查数据版本,如果版本号(或者时间戳、哈希值等)发生变化,则说明数据被修改过,此时抛出异常或者进行重试等操作。 如何在JPA中使用乐观锁? 在JP…

    人工智能概览 2023年5月25日
    00
  • Spring Cloud Alibaba之Sentinel实现熔断限流功能

    针对Spring Cloud Alibaba之Sentinel实现熔断限流功能,我会提供以下完整攻略: 1. 简介 Sentinel是一个开源的应用程序防护组件,主要用于服务熔断、限流等功能。Spring Cloud Alibaba则是阿里巴巴基于Spring Cloud开发的微服务解决方案,支持集成Sentinel。 本攻略主要介绍如何在Spring Cl…

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