记录一次golang代码优化实战
之前从来没搞过golang的代码优化,机缘巧合,有个golang的开源项目有性能优化的需要。于是就拿来试试看golang代码的优化了。
步骤一
使用benchmark与pprof, 进行性能测试
go test -cpuprofile cpu.prof -memprofile mem.prof -bench . --count=5
pprof -http=":8091" ./cpu.prof
步骤二
观察代码,很多地方可以明确使用uint32
却为定义变量类型。还有一些重复代码如
tmp = x+y
b += a
a = ...
b+=a
tmp = x+y
c +=a
这里tmp=a+b
重复计算两次。
步骤三
观察了源代码中的一些内容,发现代码内部大量使用了指针,而不是数据。这里不是说指针不好,而是项目中大量的
func sum(a,b){
return a+b
}
却实现为:
func sum(*c,*a,*b){
c=a+b
}
这样可以节约内存和数据从内存到栈的调用。
结果
before:
BenchmarkSM2Sign-16 3390 313408 ns/op 5426 B/op 117 allocs/op
BenchmarkSM2Sign-16 3765 353670 ns/op 5428 B/op 117 allocs/op
BenchmarkSM2Sign-16 3213 314760 ns/op 5448 B/op 117 allocs/op
BenchmarkSM2Sign-16 4060 300734 ns/op 5402 B/op 117 allocs/op
BenchmarkSM2Sign-16 3696 299816 ns/op 5431 B/op 117 allocs/op
BenchmarkSM2Verify-16 709 1637072 ns/op 78255 B/op 1602 allocs/op
BenchmarkSM2Verify-16 715 1646294 ns/op 81814 B/op 1675 allocs/op
BenchmarkSM2Verify-16 757 1653271 ns/op 78261 B/op 1617 allocs/op
BenchmarkSM2Verify-16 735 1693393 ns/op 76773 B/op 1588 allocs/op
BenchmarkSM2Verify-16 724 1634362 ns/op 79409 B/op 1643 allocs/op
after:
BenchmarkSM2Sign-16 4339 285344 ns/op 5404 B/op 117 allocs/op
BenchmarkSM2Sign-16 3986 276869 ns/op 5429 B/op 117 allocs/op
BenchmarkSM2Sign-16 4404 276076 ns/op 5431 B/op 117 allocs/op
BenchmarkSM2Sign-16 3960 274832 ns/op 5422 B/op 117 allocs/op
BenchmarkSM2Sign-16 3876 277349 ns/op 5413 B/op 117 allocs/op
BenchmarkSM2Verify-16 808 1461962 ns/op 78744 B/op 1628 allocs/op
BenchmarkSM2Verify-16 829 1450970 ns/op 77440 B/op 1594 allocs/op
BenchmarkSM2Verify-16 811 1447418 ns/op 77846 B/op 1601 allocs/op
BenchmarkSM2Verify-16 812 1420193 ns/op 74632 B/op 1538 allocs/op
BenchmarkSM2Verify-16 832 1436850 ns/op 76475 B/op 1572 allocs/op
产出
https://github.com/Hyperledger-TWGC/tjfoc-gm/pull/32
https://github.com/Hyperledger-TWGC/tjfoc-gm/pull/33
参考
https://my.oschina.net/wdyoschina/blog/710251
https://dave.cheney.net/2014/06/07/five-things-that-make-go-fast