一文读懂内联概念和示例
【摘要】 1 函数内联简介这可能涉及编译器优化、语言设计和性能分析几个方面。内联是将较小的函数组合到各自的调用者中的行为。在计算的早期,这种优化通常是手动执行的。如今,内联是在编译过程中自动执行的一类基本优化之一。内联很重要,原因有两个。首先是它消除了函数调用本身的开销。其次,它允许编译器更有效地应用其他优化策略。在Go中,一个协程会有一个单独的栈,栈又会包含多个栈帧,栈帧是函数调用时在栈上为函数所...
1 函数内联简介
这可能涉及编译器优化、语言设计和性能分析几个方面。内联是将较小的函数组合到各自的调用者中的行为。
在计算的早期,这种优化通常是手动执行的。如今,内联是在编译过程中自动执行的一类基本优化之一。
内联很重要,原因有两个。
首先是它消除了函数调用本身的开销。
其次,它允许编译器更有效地应用其他优化策略。
在Go中,一个协程会有一个单独的栈,栈又会包含多个栈帧,栈帧是函数调用时在栈上为函数所分配的区域。
但其实,函数调用是存在一些固定开销的,例如维护帧指针寄存器BP、栈溢出检测等。因此,对于一些代码行比较少的函数,编译器倾向于将它们在编译期展开从而消除函数调用,这种行为就是内联。
2 内联的核心(Inlining)?
内联(Inlining) 是编译器优化的一种形式,其核心是:
将函数调用的地方替换成函数体本身,避免函数调用的开销。
调用函数在任何语言中都有成本。将参数编组到寄存器或堆栈上(取决于 ABI)并在返回时反转过程会产生开销。
函数调用涉及将程序计数器从指令流中的一个点跳转到另一个点,这可能会导致管道停滞。
一旦进入函数,通常需要一些前导码来为函数执行准备新的堆栈帧,并且需要一个类似的尾声来在返回给调用者之前停用该帧。
在 Go 中,函数调用会带来额外的成本来支持动态堆栈增长。
在进入时,协程可用的堆栈空间量与函数所需的堆栈空间量进行比较。
如果可用的堆栈空间不足,序号会跳转到运行时逻辑,通过将其复制到新的、更大的位置来增加堆栈。
一旦完成此作,运行时就会跳回到原始函数的开头,再次执行堆栈检查,现在通过了,调用继续。
通过这种方式,协程可以从一个小的堆栈分配开始,该堆栈分配仅在需要时增长。
这种检查很廉价——只有几条指令——而且因为 goroutine 堆栈呈几何增长,所以检查很少失败。
因此,现代处理器内部的分支预测单元可以通过假设它总是成功的来隐藏堆栈检查的成本。
如果处理器错误地预测了堆栈检查,并且不得不丢弃在推测性执行时完成的工作,
那么与 runtime 和goroutines 堆栈增长所需的工作成本相比,流水线停顿的成本相对较小。
虽然使用推测执行技术的现代处理器很好地优化了每个函数调用的泛型组件和 Go 特定组件的开销,但这些开销无法完全消除,因此每个函数调用都会带来超出执行有用工作所花费时间的性能成本。
由于函数调用的开销是固定的,因此较小的函数相对于较大的函数支付更高的成本,因为它们每次调用往往执行的有用工作较少。
因此,消除这些函数调用开销的解决方案必须是消除函数调用本身,
Go 编译器在某些情况下通过将对函数的调用替换为函数的内容来做到这一点。
这被称为内联,因为它使函数的主体与其调用者保持一致。
- 性能的提高优化
Cliff Click 博士将内联描述为现代编译器执行的优化,因为它构成了常量传播和死代码消除等优化的基础。
实际上,内联允许编译器看到更远的地方,允许它在调用特定函数的上下文中观察可以进一步简化或完全消除的逻辑。
由于内联可以递归应用,因此不仅可以在每个单独函数的上下文中做出优化决策,还可以应用于调用路径中的函数链。
例如:
func add(a, b int) int {
return a + b
}
调用:
result := add(2, 3)
编译器可能优化为:
result := 2 + 3
3 为什么需要内联其作用是什么?
✅ 减少函数调用开销
函数调用需要栈帧的构建与销毁,这是有成本的。尤其在频繁调用的场景中(如循环内),内联可以避免这些开销。
✅ 优化编译器进一步优化空间
内联后,编译器可以更容易分析和优化代码(比如常量传播、循环展开、死代码删除等)。
✅ CPU性能提升
内联可以减少跳转,使指令执行更加线性,更好利用 CPU 指令缓存(I-cache)。
4 总结
内联的作用 描述
✅ 性能优化 减少函数调用开销,提高指令局部性
✅ 提高并发效率 goroutine 使用更少栈帧,更易扩展
✅ 编译期优化 编译器能做更多优化,如常量折叠
Go 内联机制自动决定是否优化,但你可以使用 //go:noinline 强制控制,以便做精细性能测试。
事实上的 Go 编译器是 gc。讨论的概念广泛适用于其他 Go 编译器,如 gccgo 和 tinygo,但在实现和功效上可能有所不同。
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)