【go的测试】2.性能测试

续上节:【go的测试】1.错误测试-CSDN博客

目录

1. Benchmark 基准性能测试

(1)基准测试

(2)执行参数

(3)一个简单的串行测试

(4)并行测试

(5)查看内存分配

2. pprof

普通代码性能分析

(1)CPU分析

(2)内存分析

(3)阻塞、互斥锁、goroutine分析

(4)Benchmark生成pprof

web服务性能分析

(1)在go原生http框架使用pprof

(2)在gin框架使用pprof

(3)使用火焰图分析cpu性能

(4)分析内存性能

3. abtest

(1)安装

(2)命令参数

(3)执行

4. 其他第三方工具


压测的目的就是通过压测(模拟真实用户的行为),测算出机器的性能(单台机器的 QPS),从而推算出系统在承受指定用户数(100W)时,需要多少机器能支撑得住。压测以后通过优化程序的性能或准备充足的机器,来保证用户的体验。

  • 压力测试:强度测试,测试一个系统的最大抗压能力,在强负载(大数据、高并发)的情况下,测试系统所能承受的最大压力,预估系统的瓶颈

  • 并发测试:通过模拟很多用户同一时刻访问系统或对系统某一个功能进行操作,来测试系统的性能,从中发现问题(并发读写、线程控制、资源争抢)

  • 耐久性测试:通过对系统在大负荷的条件下长时间运行,测试系统、机器的长时间运行下的状况,从中发现问题(内存泄漏、数据库连接池不释放、资源不回收)

  • QPS:每秒钟处理请求数量 (req/sec 请求数/秒 一段时间内总请求数/请求时间)

  • TPS:每秒钟处理事务数量(一个事务可能包括多个请求)

1. Benchmark 基准性能测试

(1)基准测试

验证方法在串行或者并行执行时的基准表现,了解代码的性能情况:

  • 平均耗时
  • 并发性能
  • 内存分配情况

(2)执行参数

-bench=.           # 指定基准测试函数名称
-benchtime=3s      # 每一轮运行3秒
-benchtime=300x    # 运行300次
-cpu=2,4           # 指定GOMAXPROCS的数量,模拟多核。分别2核和4核运行一次测试
-benchmem          # 显示堆内存分配情况,分配的越多越影响性能
-cpuprofile=cpu.pprof   # 生成cpu.pprof文件以进行pprof分析

(3)一个简单的串行测试

func BenchmarkReverse(b *testing.B) {
    for n := 0; n < b.N; n++ {
        Reverse("abcdefg")
    }
}

执行:

go test -v -run=none -bench=BenchmarkReverse

结果:

BenchmarkReverse-8      98738337   12.08 ns/op
GOMAXPROCS即cpu核数      执行次数    平均执行时间12.08ns

指定cpu核数执行:

go test -v -run=none -bench=BenchmarkReverse -cpu=2

结果:

BenchmarkReverse-2      100000000   11.53 ns/op

由于是串行执行所以cpu对结果没影响。

(4)并行测试

func BenchmarkReverse_Parallel(b *testing.B) {
    b.RunParallel(func(pb *testing.PB) {
        for pb.Next() {
            Reverse("abcdefg")
        }
    })
}

执行:

go test -v -run=none -bench=BenchmarkReverse -cpu=2,4,8

结果:

BenchmarkReverse-2              100000000               11.59 ns/op
BenchmarkReverse-4              100000000               11.49 ns/op
BenchmarkReverse-8              100000000               11.49 ns/op
BenchmarkReverse_Parallel-2     198732458                5.972 ns/op
BenchmarkReverse_Parallel-4     350899080                3.703 ns/op
BenchmarkReverse_Parallel-8     468575274                2.682 ns/op

其并发数默认是GOMAXPROCS

可以看到,执行次数随着并发数增加而增加,平均执行时间随着并发数增加而减小

(5)查看内存分配

执行:

go test -v -run=none -bench=BenchmarkArrayReverse -benchmem

结果:

BenchmarkArrayReverse-8     10122477    117.9 ns/op       120 B/op              4 allocs/op
8核数运行                     执行次数     平均运行时间        平均每次执行占用内存     平均每次执行分配内存的次数

2. pprof

几类性能分析:
  • CPU Profiling:CPU 分析
  • Memory Profiling:内存分析
  • Block Profiling:阻塞分析,分析 goroutine 阻塞等待同步(包括定时器通道)的情况
  • Mutex Profiling:互斥锁分析,分析互斥锁的竞争情况
应用场景:
  • 工具型:普通代码性能分析, runtime/pprof,github.com/pkg/profile (封装了runtime/pprof)
  • 服务型:web服务器性能分析,net/http/pprof
为了查看分析结果需要安装 graphviz 辅助工具:
brew install graphviz

普通代码性能分析

(1)CPU分析

import "github.com/pkg/profile"
func main() {
    // 开启cpu监控
     defer profile.Start(profile.CPUProfile).Stop()

     // 业务逻辑
     do()
}

运行 go run main.go 将生成文件cpu.pprof 到临时目录

输出文件位置:

2023/12/21 16:07:38 profile: cpu profiling enabled, /var/folders/1d/xxx/cpu.pprof

可以在浏览器查看分析:

go tool pprof -http=:9999 /xxx/cpu.pprof

或者命令行查看:

go tool pprof /xxx/cpu.pprof
(pprof) top          // 查看分析情况
(pprof) top --cum    // 按累计消耗cum排序

(2)内存分析

分析过程与上述相同,只需把cpu监控代码改为:
defer profile.Start(profile.MemProfile, profile.MemProfileRate(1)).Stop()

(3)阻塞、互斥锁、goroutine分析

- 阻塞分析:

用于了解程序在等待操作系统或网络调用时所花费的时间

defer profile.Start(profile.BlockProfile).Stop()

- 互斥锁分析

用于了解程序中哪些地方有竞争条件(mutexes)或死锁

defer profile.Start(profile.MutexProfile).Stop()

- goroutine分析

用于了解程序中当前运行和停止的 Goroutine 的数量

defer profile.Start(profile.GoroutineProfile).Stop()

(4)Benchmark生成pprof

go test -v -run=none -bench=BenchmarkReverse -cpuprofile=cpu.pprof

将在目录下生成cpu.pprof

可以进行cpu分析

go tool pprof -http=:9999 cpu.pprof

web服务性能分析

(1)在go原生http框架使用pprof

import (
    "fmt"
    "net/http"
    _ "net/http/pprof"
)

func HelloWorld(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintln(w, "hello world")
}

func main() {
    http.HandleFunc("/", HelloWorld)
    err := http.ListenAndServe(":9210", nil)
    if err != nil {
        fmt.Println(err)
    }
}

启动服务后直接访问pprof: http://127.0.0.1:9210/debug/pprof/

(2)在gin框架使用pprof

import (
    "fmt"
    "net/http"
    "github.com/gin-contrib/pprof"
    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default()
    pprof.Register(r)
    web := r.Group("/golang/web")
    ginMain(web)

    if err := r.Run(":9210"); err != nil {
        panic(err)
    }
}

func ginMain(r *gin.RouterGroup) {
    ginGroup := r.Group("/gin") //gin框架前缀
    {
        ginGroup.GET("/", func(c *gin.Context) {
            fmt.Println("hello Gin")
            c.String(http.StatusOK, "欢迎来到三体世界")
        })
    }
}

启动服务后直接访问pprof: http://127.0.0.1:9210/debug/pprof/

(3)使用火焰图分析cpu性能

安装:
// 安装go-torch
go install github.com/uber/go-torch

// 安装flamegraph
cd $GOOT/pkg/mod/github.com/uber/go-torch  // go-torch安装位置
git clone https://github.com/brendangregg/FlameGraph.git
cp FlameGraph/flamegraph.pl /usr/local/bin

采集数据,监控一段时间:

go-torch -u http://127.0.0.1:9210 -t 60

-u 为pprof监控的url,-t为采集数据的时间

监控完成会生成.svg文件,用浏览器打开分析

(4)分析内存性能

curl -s http://127.0.0.1:9210/debug/pprof/heap > t1.heap

过一段时间:

curl -s http://127.0.0.1:9210/debug/pprof/heap > t2.heap

比较差异:

go tool pprof --http :9999 --base t1.heap t2.heap

用浏览器打开:9999 分析

3. abtest

ab 属于一个轻量级的压测工具,结果不会特别准确,可以用作参考。

(1)安装

sudo apachectl -v     
sudo apachectl start   // 启动apache

打开浏览器,输入http://localhost测试是否正常

(2)命令参数

-n requests       #执行的请求数
-c concurrency    #请求并发数
-s timeout        #指定每个请求的超时时间,默认30s
-k                #启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。默认不启用
-r                #请求错误时不退出
-T content-type   #post或put请求
-H attribute      #header请求头
-p postfile       #post请求携带的body文件
-u putfile        #put请求携带的data文件

(3)执行

对baidu请求100次,并发数3

ab -n 100 -c 3 https://www.baidu.com/

 输出:

Concurrency Level:      3                // 并发数
Time taken for tests:   7.217 seconds    // 总耗时
Complete requests:      100              // 请求成功数
Failed requests:        0                // 请求失败数
Total transferred:      136096 bytes
HTML transferred:       22700 bytes
Requests per second:    13.86 [#/sec] (mean)    // qps, 每秒处理的请求数
Time per request:       216.520 [ms] (mean)
Time per request:       72.173 [ms] (mean, across all concurrent requests)
Transfer rate:          18.41 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:      130  158  12.5    158     193
Processing:    38   52  18.1     48     217
Waiting:       38   52  18.1     48     217
Total:        178  210  21.9    207     369

Percentage of the requests served within a certain time (ms)
  50%    207    // 50%的请求在207ms内返回
  66%    215
  75%    219
  80%    224
  90%    229
  95%    234
  98%    256
  99%    369
 100%    369 (longest request)

如何执行一个post请求:

ab -n 100 -c 10 -T "application/json" -H "Content-Type: application/json" -p ./req.json http://localhost:8088/api/hello

4. 其他第三方工具

GitHub - link1st/go-stress-testing

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值