benchmark对程序进行基准测试: Benchmark
代码如下:
packageaesimport("bytes""crypto/aes""crypto/cipher""encoding/base64""fmt""log""os""testing")funcAesEncryptA(aesKey,IV,origin[]byte)[]byte{block,err:=aes.NewCipher(aesKey)iferr!=nil{returnnil}blocksize:=block.BlockSize()blockMode:=cipher.NewCBCEncrypter(block,IV)originData:=PKCS5Padding(origin,blocksize)crypted:=make([]byte,len(originData))blockMode.CryptBlocks(crypted,originData)returncrypted}funcAesEncryptB(aesKey,IV,origin[]byte)[]byte{block,err:=aes.NewCipher(aesKey)iferr!=nil{returnnil}blocksize:=block.BlockSize()blockMode:=cipher.NewCBCEncrypter(block,IV)originData:=PKCS5Padding(origin,blocksize)crypted:=make([]byte,len(originData))blockMode.CryptBlocks(crypted,originData)//把加密结果打印到日志看看f,_:=os.Create("temp.log")deferf.Close()log.SetOutput(f)log.Println(fmt.Sprintf("encryptresis%s",base64.StdEncoding.EncodeToString(crypted)))returncrypted}/**PKCS5包装*/funcPKCS5Padding(cipherText[]byte,blockSizeint)[]byte{padding:=blockSize-len(cipherText)%blockSizepadText:=bytes.Repeat([]byte{byte(padding)},padding)returnappend(cipherText,padText...)}/*解包装*/funcPKCS5Trimming(encrypt[]byte)[]byte{padding:=encrypt[len(encrypt)-1]returnencrypt[:len(encrypt)-int(padding)]}funcBenchmarkAesEncryptB(b*testing.B){aesKey:=[]byte("1234567890abcdef")IV:=[]byte("7878676756564545")originData:=bytes.Repeat([]byte{28},1<<29)b.ResetTimer()fori:=0;i<b.N;i++{AesEncryptB(aesKey,IV,originData)}}
命令执行:
gotest-benchBenchmarkAesEncryptB-runnone-benchmem-cpuprofilecpuprofile.out-memprofilememprofile.out
命令解释:
bench 表示执行某些基准测试函数,后面加需要执行的基础测试函数名称, 也可以加.
表示执行所有基准测试函数,(-bench 可以跟正则表达式)
run 表示执行某些单元测试和示例测试函数, 一般加 none ,表示都不执行
benchmem 表示打印机执行过程中的内存分配
cpuprofile 表示全过程的CPU 写到文件 cpuprofile.out 中
memprofile 表示全过程的内存数据行动一些该要数据写到文件。memprofile.out 中
执行结果:
goos:darwingoarch:amd64pkg:code.xxxx.org/xxxx.hit/GoProject/main/gobase/aescpu:Intel(R)Core(TM)i7-9750HCPU@2.60GHzBenchmarkAesEncryptB-1213597342551ns/op6218809432B/op51allocs/opPASSokcode.xxxx.org/xxxx.hit/GoProject/main/gobase/aes4.214s
上述执行结果可以看到:
从执行结果中能看到,for 循环每执行一次,耗时 3597342551 纳秒,同时会有55次内存分配操作,每次操作 6218809432 字节。
pprof 分析 CPU
pprof 是 go 中自带的分析 CPU 分析器,常用来分析性能瓶颈
pprof 既可以通过命令行交互的方式查看CPU(内存)的概要数据,也可以通过web的方式查看直观的图形化展示。这里我们主要通过web的方式来展示。
当然,使用pprof工具前,你需要先安装graphviz
,如果是mac,执行brew install graphviz
使用 pprof 分析 CPU
执行如下命令:
gotoolpprof-http=":8081"cpuprofile.out
然后通过访问地址http://localhost:8081/ui/
能看到
可以看到加密部分用了 2.64s 其中加密用了0.67s, 日志打印和字符串转化用了0.41+0.86s 。
用 pprof 分析内存
gotoolpprof-http=":8081"memprofile.out
通过地址http://localhost:8081/ui/
能看到
可以看到总共用了 5930.71MB,实际上加密用值用了 640MB 上,可以看到其他内存耗费在fmt 和 log 打印上了
AesEncryptA 对于 AesEncryptB 的优化
funcBenchmarkAesEncryptA(b*testing.B){aesKey:=[]byte("1234567890abcdef")IV:=[]byte("7878676756564545")originData:=bytes.Repeat([]byte{28},1<<29)b.ResetTimer()fori:=0;i<b.N;i++{AesEncryptA(aesKey,IV,originData)}}funcBenchmarkAesEncryptB(b*testing.B){aesKey:=[]byte("1234567890abcdef")IV:=[]byte("7878676756564545")originData:=bytes.Repeat([]byte{28},1<<29)b.ResetTimer()fori:=0;i<b.N;i++{AesEncryptB(aesKey,IV,originData)}}
执行命令:
gotest-bench.-runnone-benchmem-cpuprofilecpuprofile.out-memprofilememprofile.out
执行结果:
goos:darwingoarch:amd64pkg:code.xxxx.org/xxxx.hit/GoProject/main/gobase/aescpu:Intel(R)Core(TM)i7-9750HCPU@2.60GHzBenchmarkAesEncryptA-1211011892174ns/op1207970544B/op16allocs/opBenchmarkAesEncryptB-1213382908467ns/op6218813680B/op54allocs/opPASSokcode.xxxx.org/xxxx.hit/GoProject/main/gobase/aes5.014s
可以看到BenchmarkAesEncryptA 每次循环消耗 1011892174 ns 每次操作 1207970544 B 内存,比 BenchmarkAesEncryptB 每次循环消耗 3382908467 ns, 每次操作 6218813680 B 内存,可以看到得到了很大的改善,区别主要是 去掉了一些日志打印的结果。
总结
可以借助 benchmark 进行基准测试,跑出 cpuprofile.out 和memprofile.out ,然后利用 pprof 进行 cpu 和内存分析