08/02
2021

golang之defer性能测试

在golang编码中,各种规范都在告诉我们在释放资源的时候要使用defer,尽量的在申请完资源,立马defer资源。经典的比如lock的使用。

今天看了一个开源库的实现,发现在使用lock的时候,并没有用defer unlock,而是在每一个分支处理完成之后独立的去unlock。这样无疑比较容易出bug,但同时又让我产生了一丝好奇,使用defer和不使用defer的性能差距到底有多大呢。

写两个方法,一个使用defer,一个不使用defer。

func deferHandler(i int) {
	defer func() {
		i++
	}()

	return
}

func withoutDeferHandler(i int) {
	i++
	return
}

benchmark测试用例

func BenchmarkDeferHandlder(b *testing.B) {
	for i := 0; i < b.N; i++ {
		deferHandler(i)
	}
}

func BenchmarkWithoutDeferHandlder(b *testing.B) {
	for i := 0; i < b.N; i++ {
		withoutDeferHandler(i)
	}
}

测试结果

> go test -bench .
goos: darwin
goarch: amd64
pkg: blurty/test/benchtest
cpu: VirtualApple @ 2.50GHz
BenchmarkDeferHandlder-8                414536647                2.908 ns/op
BenchmarkWithoutDeferHandlder-8         1000000000               0.3134 ns/op
PASS

结论

可以看到,使用defer和不使用defer的性能相差10倍,正好一个数量级。

当然在业务代码里,我们基本可以放心的使用defer,毕竟3ns的耗时也可以忽略不计。毕竟在业务实现里,一个函数里,业务逻辑的操作已经远远超过3ns了。

不过在越靠近底层的基础库里,我们越需要考虑性能的话。3ns的影响也是不可忽视的,比如如果有个底层接口的调用qps是100w/s,那defer就需要耗时3ms,能优化是最好不过了。

本站总访问量 本站访客数人次 本文总阅读量