与像C 这样的语言(可以在其中明确声明状态)不同inline,在Go中,编译器动态地检测可以进行内联的候选函数(C 可以做到,但Go不能同时做到)。另外,还有一个调试选项可以查看可能的内联事件,但在线上很少有关于go编译器执行此操作的确切逻辑的文档。
inline
假设我需要在每个n周期内对一组数据重新运行一些大循环;
func Encrypt(password []byte) ([]byte, error) { return bcrypt.GenerateFromPassword(password, 13) } for id, data := range someDataSet { newPassword, _ := Encrypt([]byte("generatedSomething")) data["password"] = newPassword someSaveCall(id, data) }
例如,Encrypt为了正确地内联,对于编译器,我需要考虑什么逻辑?
Encrypt
我从C ++知道,通过引用传递将在没有显式inline关键字的情况下增加自动内联的可能性,但是要理解编译器在确定选择内联或不内联的决定时所做的工作并不容易。例如,如果您使用一个常数执行循环,addSomething($a, $b)以十亿个周期为基准进行测试,则它与$a + $b(内联)相比的成本几乎是荒谬的,例如PHP之类的脚本语言将遭受极大的损失。
addSomething($a, $b)
$a + $b
报价Minux(2013年1月31日):
默认情况下,内联函数将尝试内联不调用紧急事件或恢复或选择或切换或创建闭包或执行/延迟函数的叶子函数(不调用其他函数/方法/接口)(请参见下面的示例),以及表示时,小于40个节点(大致对应40个简单操作)。但是请注意,这仅描述了gc编译器的当前状态,并且将来肯定会有所改善。因此,请尽量不要依赖于此。
在出现性能问题之前,您无需关心。内联与否,它将执行相同的操作。
如果性能确实很重要,并且可以带来显着且显着的变化,则不要依赖当前(或过去)的内联条件,自己“内联”它(不要将其放在单独的函数中)。
规则可以在$GOROOT/src/cmd/compile/internal/gc/inl.go文件中找到。您可以使用'l'调试标志来控制其积极性。
$GOROOT/src/cmd/compile/internal/gc/inl.go
'l'
// The inlining facility makes 2 passes: first caninl determines which // functions are suitable for inlining, and for those that are it // saves a copy of the body. Then inlcalls walks each function body to // expand calls to inlinable functions. // // The debug['l'] flag controls the aggressiveness. Note that main() swaps level 0 and 1, // making 1 the default and -l disable. -ll and more is useful to flush out bugs. // These additional levels (beyond -l) may be buggy and are not supported. // 0: disabled // 1: 40-nodes leaf functions, oneliners, lazy typechecking (default) // 2: early typechecking of all imported bodies // 3: allow variadic functions // 4: allow non-leaf functions , (breaks runtime.Caller) // // At some point this may get another default and become switch-offable with -N. // // The debug['m'] flag enables diagnostic output. a single -m is useful for verifying // which calls get inlined or not, more is for debugging, and may go away at any point.
另请查看博客文章:Dave Cheney-使Go快速发展的五件事(2014-06-07),其中写了关于内联的内容(长篇文章,大约在中间,搜索“内联”词)。
关于内联改进(也许是1.9吗?)的有趣讨论:cmd / compile:改进内联成本模型#17566