[译] Go1.14将内联defer提高性能

栏目: IT技术 · 发布时间: 4年前

内容简介:紧接前一篇在Go1.14之前,Go中的每一个defer函数,会在编译期在defer位置生成一个如下代码:

紧接前一篇 《Go1.14为time.Timer定时器带来巨幅性能提升》 ,本文介绍 Go 1.14针对defer做的优化。

在Go1.14之前,Go中的每一个defer函数,会在编译期在defer位置生成一个 runtime.deferproc 调用,并且在包含defer的函数退出时生成一个 runtime.deferreturn 调用。

如下代码:

0: func run() {
1:    defer foo()
2:    defer bar()
3:
4:    fmt.Println("hello")
5: }

编译器会生成类似如下的代码:

runtime.deferproc(foo) // generated for line 1
runtime.deferproc(bar) // generated for line 2

fmt.Println("hello")

runtime.deferreturn() // generated for line 5

这使得使用defer时增加了Go runtime函数调用开销。

另外值得一提的是,Go runtime中使用了先进后出的栈管理着一个函数中的多个defer调用,这也意味着defer越多,开销越大。

拿我们常见的互斥锁场景举例:

var mu sync.Mutex
mu.Lock()

defer mu.Unlock()

defer和非defer版本的benchmark如下:

BenchmarkMutexNotDeferred-8 	125341258    9.55 ns/op	       0 B/op	       0 allocs/op
BenchmarkMutexDeferred-8    	45980846     26.6 ns/op	       0 B/op	       0 allocs/op

尽管耗时都是纳秒级别,但是defer版本是非defer版本的2.7倍,换句话说,在一些简单的锁场景,defer的开销甚至超过了锁自身的开销。如果在性能热点路径上,这部分开销还是挺可观的。

这使得部分Go程序员在高性能编程场景下,舍弃了defer的使用。但是不使用defer,容易导致代码可读性下降,资源忘记释放的问题。

于是在Go1.14,编译器会在某些场景下尝试在函数返回处直接调用被defer的函数,从而使得使用defer的开销就像一个常规函数调用一样。

还拿上面那个例子举例,编译器将生成如下的代码:

fmt.Println("hello")

bar() // generated for line 5
foo() // generated for line 5

但是defer并不是所有场景都能内联。比如如果是在一个循环次数可变的循环中使用defer就没法内联。但是在函数起始处,或者不包含在循环内部的条件分支中的defer都是可以内联的。老实说,我们大部分时候也就是在这些简单场景使用defer。

在Go1.14beta再次执行上面mutex的基准测试:

BenchmarkMutexNotDeferred-8 	123710856    9.64 ns/op	       0 B/op	       0 allocs/op
BenchmarkMutexDeferred-8    	104815354    11.5 ns/op	       0 B/op	       0 allocs/op

可以看到defer版本从 26.6 ns/op 下降到了 11.5 ,与非defer版本的 9.64 已经非常接近了,性能确实有大幅提升。

本文内容来自一篇英文文章,但是省去了原文中关于defer的基础功能介绍,只对defer内联部分的内容进行意译,没有逐字翻译,感兴趣的可以观看原文: https://rakyll.org/inlined-defers/

Go 内联defe的设计、提案: https://github.com/golang/proposal/blob/master/design/34481-opencoded-defers.md

原文链接: https://pengrl.com/p/20023/

原文出处: yoko blog ( https://pengrl.com )

原文作者: yoko ( https://github.com/q191201771 )

版权声明:本文欢迎任何形式转载,转载时完整保留本声明信息(包含原文链接、原文出处、原文作者、版权声明)即可。本文后续所有修改都会第一时间在原始地址更新。

[译] Go1.14将内联defer提高性能


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java算法

Java算法

塞奇威克 / 赵文进 / 清华大学出版社 / 2004-06-01 / 59.0

《Java算法》用Java语言全面实现了当今最重要的计算机算法,并用大量图表和数学公式对算法进行了详尽的描述和分析。全书共分3卷,本书是其中的第1卷(第1至第4部分)。内容包括基本概念(第1部分)、数据结构(第2部分)、排序算法(第3部分)和查找算法(第4部分)。本书概念清楚,内容翔实,新颖,由浅入深地描述了算法。本书可作为高等院校计算机相关专业本科生和研究生的教材和补充读物,也可作为Java爱好一起来看看 《Java算法》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换