6

Go语言对象跟闭包性能比较

 3 years ago
source link: https://www.zenlife.tk/object-vs-closure-performance.md
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go语言对象跟闭包性能比较

2015-03-09

上篇文章中提到了一下这个问题,但我之前只是写“直觉上认为”,并且还不解释。因为我了解Go的底层,知道方法和闭包分别是怎么实现的,然后用直觉做的判断。但是事后觉得写博客不能这么不严谨,所以做了个测试。

结论大致是对的,但结果也有一些出乎之间意料的地方。

假设我们要实现下面这个接口:

type I interface { XXX() }

分别用闭包和对象的方式实现。闭包或是对象,在这里都是想封装一些状态。用对象的写法:

type Object struct { A int }

func (obj *Object) XXX() { obj.A++ }

用闭包的写法:

func Closure() func() { var A int return func() { A++ } }

为了实现接口I,闭包写法需要一点辅助:

type IFunc func()

func (f IFunc) XXX() { f() }

现在测试:

var ( obj I clo I )

obj = &Object{} clo = IFunc(Closure())

for i := 0; i < 10000000; i++ { obj.XXX() } for i := 0; i < 10000000; i++ { clo.XXX() }

在我的机器上得到的结果:

object: 30.026664ms closure: 54.920985ms

所以说结论大致是对的。

我又测试了一下直接调用Object.XXX()跟Closure()(),两者性能其实没差异。主要问题是在闭包写法多了一层转换步骤,直觉地认为闭包比方法慢是有偏见的。这是我所说的有点出乎意料的地方。

Go语言中,方法在底层的实现,实际上就是普通函数多加了一个参数,将对象作为这个参数。比如上面的

func (obj *Object) XXX() { obj.A++ }

变换为底层的处理就是

func XXX(obj *Object) { obj.A++ }

至于闭包,则是会将一个函数指针和各个upvalue打包到一起。

func Closure() func() { var A int return func() { A++ } }

转化之后等价于

func fun001(A *int) { (*A)++ } func Closure() struct { return &struct{ fun001, new(int), } }

应该说,性能上真的没有差异。可能对象写法比闭包写法对内存更友好一点点。

如果用两种方式都可以实现时,到底是选对象还是闭包呢?如果纠结的话,我还是更推荐对象写法一些。如果不纠结的话,都可以,无所谓。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK