博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go 性能优化技巧 4/10
阅读量:6954 次
发布时间:2019-06-27

本文共 726 字,大约阅读时间需要 2 分钟。

  hot3.png

延迟调用(defer)确实是一种 “优雅” 机制。可简化代码,并确保即便发生 panic 依然会被执行。如将 panic/recover 比作 try/except,那么 defer 似乎可看做 finally。

如同异常保护被滥用一样,defer 被无限制使用的例子比比皆是。

只需稍稍了解 defer 实现机制,就不难理解会有这样的性能差异。

编译器通过 runtime.deferproc “注册” 延迟调用,除目标函数地址外,还会复制相关参数(包括 receiver)。在函数返回前,执行 runtime.deferreturn 提取相关信息执行延迟调用。这其中的代价自然不是普通函数调用一条 CALL 指令所能比拟的。

或许你会觉得 4x 的性能差异算不得什么,但如果是下面这样呢?

当多个 goroutine 执行该函数时,只怕性能差异就不是 4x,还得算上 httpGet 所需时间。原本的并发设计,因为错误的 defer 调用变成 “串行”。

与之类似的,还有下面这样的写法。

如果 files 是个 “超大” 列表,只怕在 analysis 结束前,会有不小的隐式 “资源泄露”,这些不能及时回收的对象,会导致 GC 在内的相关性能问题。

解决方法么,要么去掉 f.close 前的 defer,要么将内层处理逻辑重构为独立函数(比如匿名函数调用)。

除此之外,单个函数里过多的 defer 调用可尝试合并。最起码,在并发竞争激烈时,mutex.Unlock 不应该使用 defer,而应尽快执行,仅保护最短的代码片段。

最新动态,请扫码关注

转载于:https://my.oschina.net/qyuhen/blog/667741

你可能感兴趣的文章
bootstrap-缩略图-默认样式的实例
查看>>
Spring4-BeanPropertyRowMapper
查看>>
我的友情链接
查看>>
MongoDB根据时间aggregate示例
查看>>
等级保护项目SQL Server审计方案
查看>>
Java 之集合
查看>>
改进了一下上周写的那个加域和迁移用户资料的程序
查看>>
归并排序和快速排序的衍生问题
查看>>
web工具
查看>>
Iptables 规则基础笔记
查看>>
nagios访问web界面出现Internal Server Error解决方法
查看>>
LVM逻辑卷管理
查看>>
51nod 1294:修改数组
查看>>
java自动化滑动学习
查看>>
Mongodb 副本集 数据同步简单测试
查看>>
我的友情链接
查看>>
iOS nil、Nil、NULL和NSNull 的使用
查看>>
c++ primer第五版 练习7.9
查看>>
前途是自己掌握的
查看>>
saltstack jobs管理
查看>>