golang基准测试Benchmark和Jmeter压测实践
golang的性能测试Benchmark
go test 自带有三种测试:
- 功能测试(单元测试)
- 基准测试 (性能测试)
- 实例测试 (举例测试)
今天主要是写一下基准测试也就是我们的性能测试实践相关。
基准测试是测量一个程序在固定工作负载下的性能。
在Go语言中,基准测试函数和普通测试函数写法类似,但是以Benchmark为前缀名,并且带有一个testing.B类型的参数;testing.B参数除了提供和*testing.T类似的方法,还有额外一些和性能测量相关的方法。
它还提供了一个整数N,用于指定操作执行的循环次数。
func BenchmarkAdapter_GetReport(b *testing.B) {
a := &Adapter{
Server: "127.0.0.1:9094/tenant",
}
for i := 0; i < b.N; i++ {
b.ReportAllocs() // 这里可以直接调用 ReportAllocs 方法,就省去了再命令行中输入 -benchmem ,用于查看内存分配的大小和次数
_, _ = a.GetReport("devices", "appsinfo", "")
}
}
然后在命令行输入如下:
go test -bench=GetReport
又或者直接填入测试函数名:
go test -bench=BenchmarkAdapter_GetReport
最终显示数据如下:
goos: darwin
goarch: amd64
pkg: safeuem/report/service/adapter
BenchmarkAdapter_GetReport-4 500 2351618 ns/op 20770 B/op 301 allocs/op
PASS
ok safeuem/report/service/adapter 2.741s
- BenchmarkAdapter_GetReport-4 :
这里的-4中的4 表示最大 P 数量,最大 P 数量相当于可以同时运行 goroutine 的逻辑 CPU 的最大个数。这里的逻辑 CPU,也可以被称为 CPU 核心,但它并不等同于计算机中真正的 CPU 核心,只是 Go 语言运行时系统内部的一个概念,代表着它同时运行 goroutine 的能力。
对应 golang 就是 GOMAXPROCS 的值。这个你可以自行设置,可以通过调用 runtime.GOMAXPROCS 函数改变最大P数量,也可以在命令行 go test 加入 -cpu=2 。
- 500 2351618 ns/op
显示每次调用 GetReport 函数花费 2.351618毫秒 ,是执行 500次 的平均时间。
1s=1000ms=1000000us=1000000000ns
因为基准测试驱动器开始时并不知道每个基准测试函数运行所花的时间,它会尝试在真正运行基准测试前先尝试用较小的N运行测试来估算基准测试函数所需要的时间,然后推断一个较大的时间保证稳定的测量结果
- 20770 B/op 301 allocs/op
表示平均500此种,每次分配了内存为 20770 B(字节) = 20.28KB = 0.0198MB 和 每次调用分配了 301次
1MB=1024KB
1KB=1024B
- 2.741s
表示测试总耗时。
小提示:
其实这里的总耗时,其实默认是1s,当测试次数逐渐递增到时间刚好超过1s 时测试就会停止,并显示测试,这里是500次。
当然如果你的本身的测试函数运行一次就已经大于了1s,为了提高测试的精确性,你可以在命令行输入 :
go test -bench=GetReport -benchtime=5s
jmeter 压力测试
首先要安装 请看链接不多说
如果下载页面进不去 移步到此处下载即可
注意 : 一定要配置好java的环境变量才开始压测哦!
运行启动如图所示:
image1. 你可以开始配置要测试的http接口:
image2. 线程数的配置:
image3. 建立HTTP请求接口:
image4. 建立监控器 数据展示
可以建立三个查看,一般我建立聚合报告看看就可以了。
image聚合报告数据说明:
来看如图所示的数据:
中文版
image英文版
image这里我的线程数改变了 2 。
-
Label:每个 JMeter 的 element(例如 HTTP Request)都有一个 Name 属性,这里显示的就是 Name 属性的值
-
Samples:表示你这次测试中一共发出了多少个请求,如果模拟10个用户,每个用户迭代10次,那么这里显示100,每个用户只迭代一次就是10了。我这里自然是 2.
-
Average:平均响应时间(单位ms,1s=1000ms)——默认情况下是单个 Request 的平均响应时间,当使用了 Transaction Controller 时,也可以以Transaction 为单位显示平均响应时间
-
Median:中位数,也就是 50% 用户的响应时间
-
90% Line:90% 用户的响应时间
-
Min:最小响应时间
-
Max:最大响应时间
-
Error%:本次测试中出现错误的请求的数量/请求的总数
-
Throughput:吞吐量——默认情况下表示每秒完成的请求数(Request per Second),如果你的接口超过了每秒请求一次就会按照每分钟展示, 当使用了 Transaction Controller 时,也可以表示类似 LoadRunner 的 Transaction per Second 数
-
Received KB/Sec:每秒从服务器端接收到的数据量,相当于LoadRunner中的Throughput/Sec
-
Send KB/Sec: 每秒向服务器端接发送的数据量。
所以如图中的线程数为2的测试中,平均每次响应时间为 554 毫秒相当于半秒,吞吐量为每秒处理了 1.9 次,额。。。很渣的性能。
因为这个接口本来就没有高并发场景要求,而且里面有个比较麻烦的递归查询操作很消耗性能的。
加大压力进行测试
那么如果出现较多的访问该接口,较高并发访问性能是如何的呢。
来个小 50 试试呢。
image好吧,这个接口性能确实很差。。。平均一个接口处理要6s的时间。
具体分析原因:
- 一个是递归耗性能
- 另一个应该是Cassandra数据库I/O是性能瓶颈,pool可以从10调大到100试试。
将Cassandra连接池pool调为100压测数据
image将线程数设置为200压测数据如下:
image果然性能处理要好很多了。