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日

相关文章

  • 在Mac OS下搭建LNMP开发环境的步骤详解

    在Mac OS下搭建LNMP开发环境的步骤详解 简介 LNMP(Linux + Nginx + MySQL + PHP)是一种网站开发和运行环境,与传统的LAMP(Linux + Apache + MySQL + PHP)相比,LNMP具有更高的性能和更低的资源消耗,是目前非常流行的web开发环境之一。本文将详细介绍如何在Mac OS上搭建LNMP开发环境。…

    人工智能概览 2023年5月25日
    00
  • 阿里云部署SSL证书详解

    阿里云部署SSL证书详解 什么是SSL证书? SSL证书是一种基于SSL/TLS协议的数字身份证明。它用于在互联网中对数据进行加密传输,并为接收端验证发送端真实身份。 阿里云SSL证书申请 为了在阿里云上使用SSL证书,首先需要在阿里云上申请并购买SSL证书。申请步骤如下: 登录阿里云控制台并进入SSL证书管理页面。 点击“购买证书”,选择需要购买的SSL证…

    人工智能概览 2023年5月25日
    00
  • django连接数据库获取数据的简单步骤记录

    下面是关于Django连接数据库获取数据的简单步骤记录的完整攻略: 1. 设置数据库连接 在Django的settings.py文件中,我们可以设置数据库的连接信息,主要包括数据库类型、数据库名称、用户名、密码、主机等信息。其中,Django支持的数据库类型包括MySQL、PostgreSQL、SQLite、Oracle等,可以根据项目需求进行选择。 以下是…

    人工智能概论 2023年5月25日
    00
  • 利用nginx与ffmpeg搭建流媒体服务器过程详解

    下面是一份利用nginx与ffmpeg搭建流媒体服务器的攻略。 准备工作 安装nginx와 ffmpeg 在开始操作之前,应该先安装两个核心软件:nginx和ffmpeg。 要安装nginx和ffmpeg,可以使用以下的命令: 在Linux上的命令行终端中: sudo apt-get update sudo apt-get install nginx ffm…

    人工智能概览 2023年5月25日
    00
  • Mybatis分页插件的实例详解

    Mybatis作为一款流行的ORM框架,在开发过程中经常需要对查询结果进行分页操作。而Mybatis分页插件可以帮助我们轻松地实现分页功能。本文将详细介绍Mybatis分页插件的使用方法。 1. Mybatis分页插件介绍 Mybatis提供了一个分页插件,其核心代码在mybatis-3-mybatis-generator.jar包中的org.apache.…

    人工智能概论 2023年5月24日
    00
  • DjangoWeb使用Datatable进行后端分页的实现

    以下是关于“DjangoWeb使用Datatable进行后端分页的实现”的完整攻略: 一、什么是Datatable? Datatable 是一个强大的 JavaScript 表格插件,能够轻松地处理大量和多样化的数据。它提供了内置的搜索、排序、分页及对列宽等的设定等功能,可自由定制。 二、为什么用Datatable? 使用Datatable作为后台分页的实现…

    人工智能概览 2023年5月25日
    00
  • pytorch通过自己的数据集训练Unet网络架构

    下面是详细的步骤: 1. 准备数据集 首先要准备自己的数据集,建议按照 PyTorch 的 Dataset 和 DataLoader 的使用方法来组织数据集。可以将训练集和验证集分别存放在不同的文件夹中,其中每个文件夹中都对应一类图像。在实现数据增强的过程中,可以使用 torchvision.transforms 中的 transforms。例如,将图片随机…

    人工智能概论 2023年5月25日
    00
  • 在Debian下配置Python+Django+Nginx+uWSGI+MySQL的教程

    下面我为您详细讲解在Debian下配置Python+Django+Nginx+uWSGI+MySQL的完整攻略。 环境准备 在配置过程中,需要准备以下环境: Debian操作系统 Python环境 Django框架 Nginx服务器 uWSGI应用服务器 MySQL数据库 请确保在Debian系统中安装了相应的软件,在此不再赘述。 安装Python和Djan…

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