golang基准测试Go语言基础操作性能插件库gocostmodel的使用
Go语言基础操作性能插件库gocostmodel的使用
简介
gocostmodel包受到Brian W. Kernighan和Rob Pike的书籍《The Practice of Programming》(Addison-Wesley, 1999)的启发。在第7章关于性能的部分,第7.6节(估算)中提到:
“提前估算程序运行速度很困难[…]。但是,为一种语言或系统创建成本模型很容易,这至少能让你对重要操作的耗时有一个大致了解。”
这是一个为Go语言基准测试常见基本操作的成本模型。为了使它有意义,应该在目标硬件上运行,操作的相对性能可能比实际数字更重要。
示例
以下是在Toshiba Chromebook 64位运行Ubuntu (LXDE)上的基准测试结果示例:
BenchmarkConvIntToFloat64 1000000000 2.16 ns/op 0 B/op 0 allocs/op
BenchmarkConvFloat64ToInt 2000000000 1.26 ns/op 0 B/op 0 allocs/op
BenchmarkConvIntToFloat32 2000000000 1.44 ns/op 0 B/op 0 allocs/op
BenchmarkConvFloat32ToInt 2000000000 1.42 ns/op 0 B/op 0 allocs/op
BenchmarkConvStringToInt 30000000 57.8 ns/op 0 B/op 0 allocs/op
BenchmarkConvIntToString 20000000 108 ns/op 1 B/op 1 allocs/op
BenchmarkStringToByte 20000000 110 ns/op 8 B/op 1 allocs/op
BenchmarkByteToString 20000000 84.8 ns/op 4 B/op 1 allocs/op
BenchmarkFindSliceInt5 100000000 13.0 ns/op 0 B/op 0 allocs/op
BenchmarkFindSliceStr5 20000000 64.9 ns/op 0 B/op 0 allocs/op
BenchmarkFindSliceInt100 10000000 236 ns/op 0 B/op 0 allocs/op
BenchmarkFindSliceStr100 1000000 1248 ns/op 0 B/op 0 allocs/op
BenchmarkFindMapInt5 100000000 22.2 ns/op 0 B/op 0 allocs/op
BenchmarkFindMapStr5 20000000 77.6 ns/op 0 B/op 0 allocs/op
BenchmarkFindMapInt100 30000000 58.3 ns/op 0 B/op 0 allocs/op
BenchmarkFindMapStr100 20000000 76.2 ns/op 0 B/op 0 allocs/op
BenchmarkFloat32Assign 2000000000 0.99 ns/op 0 B/op 0 allocs/op
安装
go get github.com/PuerkitoBio/gocostmodel
运行基准测试
go test -run zz -bench . [-benchmem]
示例代码
以下是一个如何使用gocostmodel进行基准测试的示例:
package main
import (
"testing"
)
// 测试整数到浮点数的转换性能
func BenchmarkConvIntToFloat64(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = float64(42)
}
}
// 测试字符串到字节切片的转换性能
func BenchmarkStringToByte(b *testing.B) {
s := "hello"
for i := 0; i < b.N; i++ {
_ = []byte(s)
}
}
// 测试在小切片中查找整数的性能
func BenchmarkFindSliceInt5(b *testing.B) {
slice := []int{1, 2, 3, 4, 5}
target := 3
for i := 0; i < b.N; i++ {
for _, v := range slice {
if v == target {
break
}
}
}
}
// 测试在大切片中查找字符串的性能
func BenchmarkFindSliceStr100(b *testing.B) {
slice := make([]string, 100)
for i := range slice {
slice[i] = string(rune(i))
}
target := "50"
for i := 0; i < b.N; i++ {
for _, v := range slice {
if v == target {
break
}
}
}
}
贡献
欢迎提交Pull Request,但基准测试应该是针对常见基本操作的,符合现有基准测试的精神。
许可证
此源代码根据BSD 3-clause许可证发布。
更多关于golang基准测试Go语言基础操作性能插件库gocostmodel的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang基准测试Go语言基础操作性能插件库gocostmodel的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Go语言基准测试与gocostmodel使用指南
Go基准测试基础
Go语言内置了强大的基准测试工具,可以方便地测量代码性能。基准测试文件通常以_test.go
结尾,测试函数以Benchmark
开头。
基本示例
package main
import (
"testing"
)
func BenchmarkStringConcatenation(b *testing.B) {
for i := 0; i < b.N; i++ {
var s string
for j := 0; j < 100; j++ {
s += "a"
}
}
}
func BenchmarkStringBuilder(b *testing.B) {
for i := 0; i < b.N; i++ {
var builder strings.Builder
for j := 0; j < 100; j++ {
builder.WriteString("a")
}
_ = builder.String()
}
}
运行基准测试:
go test -bench=. -benchmem
gocostmodel简介
gocostmodel是一个Go语言性能分析插件库,它可以帮助开发者更精确地测量和建模Go程序的性能特征。
安装gocostmodel
go get github.com/gocostmodel/gocostmodel
基本使用示例
package main
import (
"fmt"
"github.com/gocostmodel/gocostmodel"
"time"
)
func main() {
// 初始化cost model
cm := gocostmodel.NewCostModel()
// 开始测量
cm.Start("operation1")
// 模拟耗时操作
time.Sleep(100 * time.Millisecond)
// 结束测量
cm.End("operation1")
// 获取测量结果
result := cm.Get("operation1")
fmt.Printf("Operation1 - Count: %d, Total: %v, Avg: %v\n",
result.Count, result.Total, result.Avg())
// 测量多个操作
for i := 0; i < 5; i++ {
cm.Start("operation2")
time.Sleep(time.Duration(i*20) * time.Millisecond)
cm.End("operation2")
}
// 输出所有测量结果
fmt.Println("\nAll measurements:")
for _, name := range cm.Names() {
r := cm.Get(name)
fmt.Printf("%s - Count: %d, Total: %v, Avg: %v\n",
name, r.Count, r.Total, r.Avg())
}
}
结合基准测试与gocostmodel
package main
import (
"github.com/gocostmodel/gocostmodel"
"testing"
)
func BenchmarkWithCostModel(b *testing.B) {
cm := gocostmodel.NewCostModel()
b.ResetTimer()
for i := 0; i < b.N; i++ {
cm.Start("iteration")
// 被测代码
fibonacci(30)
cm.End("iteration")
}
// 输出每次迭代的平均耗时
b.Logf("Average iteration time: %v", cm.Get("iteration").Avg())
}
func fibonacci(n int) int {
if n <= 1 {
return n
}
return fibonacci(n-1) + fibonacci(n-2)
}
高级功能
内存分配统计
func BenchmarkMemoryAllocation(b *testing.B) {
cm := gocostmodel.NewCostModel()
var stats gocostmodel.MemStats
b.ResetTimer()
for i := 0; i < b.N; i++ {
cm.StartMemProfile("memory_operation")
// 模拟内存分配
data := make([]byte, 1024*1024) // 分配1MB
_ = data
cm.EndMemProfile("memory_operation", &stats)
}
b.Logf("Allocs: %d, TotalAlloc: %d, HeapAlloc: %d",
stats.Allocs, stats.TotalAlloc, stats.HeapAlloc)
}
并发性能测试
func BenchmarkConcurrentOperations(b *testing.B) {
cm := gocostmodel.NewCostModel()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
cm.Start("concurrent_op")
// 并发执行的代码
time.Sleep(10 * time.Millisecond)
cm.End("concurrent_op")
}
})
b.Logf("Total operations: %d", cm.Get("concurrent_op").Count)
}
最佳实践
- 始终在基准测试中使用
b.ResetTimer()
来跳过初始化代码的测量 - 使用
-benchmem
标志来获取内存分配信息 - 对于复杂操作,使用gocostmodel细分测量不同部分的性能
- 多次运行基准测试以获取稳定结果
- 在真实环境下验证基准测试结果
通过结合Go内置的基准测试工具和gocostmodel插件库,开发者可以获得更全面、更精确的性能分析数据,从而更好地优化Go应用程序。