内联函数和编译器对Go代码的优化

发表于 2年以前  | 总阅读数:335 次

什么是内联函数

图片版权:Renee French.

在很多讲 Go 语言底层的技术资料和博客里都会提到内联函数这个名词,也有人把内联函数说成代码内联、函数展开、展开函数等等,其实想表达的都是 Go 语言编译器对函数调用的优化,编译器会把一些函数的调用直接替换成被调函数的函数体内的代码在调用处展开,以减少函数调用带来的时间消耗。它是Go语言编译器对代码进行优化的一个常用手段。

内联函数并不是 Go 语言编译器独有的,很多语言的编译器在编译代码时都会做内联函数优化,维基百科对内联函数的解释如下 (我把重点需要关注的信息特意进行了加粗):

在计算机科学中,内联函数(有时称作在线函数编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。但在选择使用内联函数时,必须在程序占用空间和程序执行效率之间进行权衡,因为过多的比较复杂的函数进行内联扩展将带来很大的存储资源开支。另外还需要特别注意的是对递归函数的内联扩展可能引起部分编译器的无穷编译。

Note:内联优化一般用于能够快速执行的函数,因为在这种情况下函数调用的时间消耗显得更为突出,同时内联体量小的函数也不会明显增加编译后的执行文件占用的空间

Go 语言里的内联函数

举个例子来说,假设我有下面这样一个算两数之和的程序(不要紧张,不是算法题-两数之和...)

package main
import "fmt"
func main() {
  x := 20
  y := 5
  res := add(x, y)
  fmt.Println(res)
}

func add(x int, y int) int {
 return x + y
}

上面的函数非常简单,add 函数对两个参数进行加和,编译器在编译上面的 Go 代码时会做内联优化,把 add 函数的函数体直接在调用处展开,等价于上面的 Go 代码是这么编写的。

package main
import "fmt"
func main() {
  x := 20
  y := 5
  // 内联函数, 或者叫把函数展开在调用处
  res := x + y 
  fmt.Println(res)
}

func add(x int, y int) int {
 return x + y
}

告诉编译器不对函数进行内联

在源码编译的汇编代码里我们也看不到对 add 函数的调用,不过我们可以通过在 add 函数上增加一个特殊的注释来告诉编译器不要对它进行内联优化

// 注意下面这行注释,"//"后面不要有空格
//go:noinline
func add(x int, y int) int {
 return x + y
}

怎么验证这个注释真实有效,能让编译器不对add函数做内联优化呢?我们可以用 go tool compile -S scratch.go 打印出的 Go 代码被编译成的汇编代码,在汇编代码里我们可以发现对add函数的调用。

0x0053 00083 (scratch.go:6)  CALL    "".add(SB)

这也反向证明了,正常情况下 Go 编译器会对 add 函数进行内联优化。

编译器会对代码做哪些优化

除了分析编译后的汇编源码外,我们还可以通过给 go build 命令传递 -gcflags -m 参数

$ go build -gcflags --help
[.......]
// 传递 -m 选项会输出编译器对代码的优化
-m    print optimization decisions

让编译器告诉我们它在编译 Go 代码对代码都做了哪些优化。

接下用 -gcflags -m 构建一下我们的小程序

$ go build -gcflags -m scratch.go

./scratch_16.go:10:6: can inline add
./scratch_16.go:6:12: inlining call to add
./scratch_16.go:7:13: inlining call to fmt.Println
./scratch_16.go:7:13: res escapes to heap
./scratch_16.go:7:13: main []interface {} literal does not escape
./scratch_16.go:7:13: io.Writer(os.Stdout) escapes to heap

通过终端的输出可以了解到,编译器判断 add函数可以进行内联,也对 add 函数进行了内联,除此之外还对fmt.Println 进行了内联优化。还有一个 io.Writer(os.Stdout) escapes to heap 的输出代表的是 io 对象逃逸到了堆上,堆逃逸是另外一种优化,在先前 Go内存管理系列的文章 -- [Go内存管理之代码的逃逸分析] 有详细说过。

哪些函数不会被内联

那么 Go 的编译器是不是会对所有的体量小,执行快的函数都会进行内联优化呢?我查查了资料发现 Go 在决策是否要对函数进行内联时有一个标准:

函数体内包含:闭包调用,select ,for ,defer,go 关键字的的函数不会进行内联。并且除了这些,还有其它的限制。当解析AST时,Go申请了80个节点作为内联的预算。每个节点都会消耗一个预算。比如,a = a + 1这行代码包含了5个节点:AS, NAME, ADD, NAME, LITERAL。以下是对应的SSA 输出:

当一个函数的开销超过了这个预算,就无法内联

以上描述翻译自文章:https://medium.com/a-journey-with-go/go-inlining-strategy-limitation-6b6d7fc3b1be

总结

内联是高性能编程的一种重要手段。每个函数调用都有开销:创建栈帧,读写寄存器,这些开销可以通过内联避免,对性能的提升大概在5~6%左右。但内联对函数体进行拷贝也会增大编译后二进制文件的大小,不过好在使用Go语言编程时,编译器会帮助我们决策哪些函数可以内联,大大降低了使用者的心智负担 。

关于编译器编译时对Go代码做的优化,推荐阅读我的另一篇文章:

[Go内存管理之代码的逃逸分析]

本文由哈喽比特于2年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/ujWkFUqJiY3DCWeKZeS8uw

 相关推荐

刘强东夫妇:“移民美国”传言被驳斥

京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。

发布于:1年以前  |  808次阅读  |  详细内容 »

博主曝三大运营商,将集体采购百万台华为Mate60系列

日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。

发布于:1年以前  |  770次阅读  |  详细内容 »

ASML CEO警告:出口管制不是可行做法,不要“逼迫中国大陆创新”

据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。

发布于:1年以前  |  756次阅读  |  详细内容 »

抖音中长视频App青桃更名抖音精选,字节再发力对抗B站

今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。

发布于:1年以前  |  648次阅读  |  详细内容 »

威马CDO:中国每百户家庭仅17户有车

日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。

发布于:1年以前  |  589次阅读  |  详细内容 »

研究发现维生素 C 等抗氧化剂会刺激癌症生长和转移

近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。

发布于:1年以前  |  449次阅读  |  详细内容 »

苹果据称正引入3D打印技术,用以生产智能手表的钢质底盘

据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。

发布于:1年以前  |  446次阅读  |  详细内容 »

千万级抖音网红秀才账号被封禁

9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...

发布于:1年以前  |  445次阅读  |  详细内容 »

亚马逊股东起诉公司和贝索斯,称其在购买卫星发射服务时忽视了 SpaceX

9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。

发布于:1年以前  |  444次阅读  |  详细内容 »

苹果上线AppsbyApple网站,以推广自家应用程序

据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。

发布于:1年以前  |  442次阅读  |  详细内容 »

特斯拉美国降价引发投资者不满:“这是短期麻醉剂”

特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。

发布于:1年以前  |  441次阅读  |  详细内容 »

光刻机巨头阿斯麦:拿到许可,继续对华出口

据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。

发布于:1年以前  |  437次阅读  |  详细内容 »

马斯克与库克首次隔空合作:为苹果提供卫星服务

近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。

发布于:1年以前  |  430次阅读  |  详细内容 »

𝕏(推特)调整隐私政策,可拿用户发布的信息训练 AI 模型

据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。

发布于:1年以前  |  428次阅读  |  详细内容 »

荣耀CEO谈华为手机回归:替老同事们高兴,对行业也是好事

9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI操控无人机能力超越人类冠军

《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。

发布于:1年以前  |  423次阅读  |  详细内容 »

AI生成的蘑菇科普书存在可致命错误

近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。

发布于:1年以前  |  420次阅读  |  详细内容 »

社交媒体平台𝕏计划收集用户生物识别数据与工作教育经历

社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”

发布于:1年以前  |  411次阅读  |  详细内容 »

国产扫地机器人热销欧洲,国产割草机器人抢占欧洲草坪

2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。

发布于:1年以前  |  406次阅读  |  详细内容 »

罗永浩吐槽iPhone15和14不会有区别,除了序列号变了

罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。

发布于:1年以前  |  398次阅读  |  详细内容 »
 相关文章
Android插件化方案 5年以前  |  237235次阅读
vscode超好用的代码书签插件Bookmarks 2年以前  |  8071次阅读
 目录