当前位置: 首页 > 知识库问答 >
问题:

刺激代码内联

曹光霁
2023-03-14

与C++这样的语言不同,在C++中,您可以显式地声明inline,而在Go中,编译器动态地检测作为内联候选的函数(C++也可以这样做,但Go不能同时这样做)。还有一个debug选项来查看可能发生的内联,但是很少有在线文档说明go编译器(一个或多个)执行此操作的确切逻辑。

假设我需要每隔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,我需要为编译器考虑什么逻辑?

我从C++中了解到,通过引用传递将增加自动内联的可能性,而不需要显式的inline关键字,但是要理解编译器到底做了什么来确定选择内联还是不在Go中的决定并不是很容易。例如,如果您使用常量addsomething($a,$b)执行循环,就会遭受巨大的痛苦,在此对十亿个循环进行基准测试时,它的成本与$a+$b(内联)相比几乎是荒谬的。

共有1个答案

邓毅
2023-03-14

引用联危特派团(于2013-01-31):

默认情况下,内联程序将尝试内联叶函数(不调用其他函数/方法/接口),这些函数不调用panic、recover、select、switch或创建closure或Go/Defer函数(参见下面的示例),并且在表示时少于40个节点(大致对应于40个简单操作)。但请注意,这只是描述了gc编译器的当前现状,以后肯定会有所改进。因此,请尽量不要依赖这一点。

在您出现性能问题之前,您不应该在意。无论是否内联,它都将执行相同的操作。

这些规则可以在$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-Five things that make Go fast(2014-06-07),这篇文章是关于内联的(很长的文章,大概在中间,搜索“内联”这个词)。

还有关于内联改进的有趣讨论(也许Go 1.9?):cmd/compile:improve inlining cost model#17566

 类似资料:
  • 问题内容: 与像C 这样的语言(可以在其中明确声明状态)不同 ,在Go中,编译器动态地检测可以进行内联的候选函数(C 可以做到,但Go不能同时做到)。另外,还有一个调试选项可以查看可能的内联事件,但在线上很少有关于go编译器执行此操作的确切逻辑的文档。 假设我需要在每个n周期内对一组数据重新运行一些大循环; 例如,为了正确地内联,对于编译器,我需要考虑什么逻辑? 我从C ++知道,通过引用传递将在

  • 本文向大家介绍Markdown 内联代码,包括了Markdown 内联代码的使用技巧和注意事项,需要的朋友参考一下 示例 Markdown支持添加内联代码like this,该代码是通过将文本包装在反引号中获得的: `code here` 或者,您可以将内联代码放在<code>和</code>HTML标记之间。 考虑以下降价代码: 这将产生以下输出: This是内联代码块!This也是一个! 如果

  • 我在webpack(刺激框架)中使用数据表。 我使用YARN安装jQuery和Datatables: 现在我在刺激中创建了一个控制器: 在控制台中打开页面时显示错误: 如何修复此问题?

  • 基于 netty 实现的高性能内网穿透,支持所有 tcp 上层协议的转发。 软件结构

  • 在电子论坛对付刺儿头并不比在现实中容易。这里“刺”不是“无礼”。无礼的人很讨厌,但不一定难对付。本书已经介绍了如何处理他们:在第一时间回复无礼行为,之后,选择忽略他们或者同其他人一样对待他们。如果他们继续无礼,他们会让自己更加不受欢迎,并在项目中毫无影响力,所以这是他们自己的问题。 真正的问题不是完全无礼的人,而是那些操弄或滥用项目进程,消耗他人时间和能量,而不会为项目带来任何利益的人。这些人经常

  • 我有一个用于报表设计器的组件,并将方法分配给事件,但在该方法中,我的组件memeber是 这是错误: 无法设置未定义的属性(设置'body')类型错误:无法将未定义的属性(设置'body')设置在$.onReportSave[as onSaveReport](http://localhost:4200/features-expressionsoft-report-expressionsoft-re