英文:
Exceeding inline budget
问题
你好!根据你的描述,你想知道如何强制Golang编译器内联函数,如果函数没有被内联的唯一原因是超过了内联预算。你想知道是否可以将预算从80增加到160,或者是否有任何模式可以帮助你进行函数拆分。
对于你的问题,Golang编译器目前没有提供直接控制内联预算的选项。内联预算是编译器的内部机制,用于控制函数内联的条件。如果函数的复杂度超过了预算,编译器将不会将其内联。
如果你想尝试优化函数的性能,你可以考虑以下几点:
-
简化函数逻辑:尽量减少函数的复杂度,使其适应内联预算。
-
使用内联注释:在函数声明前添加
//go:inline
注释,提示编译器尝试内联该函数。但是,请注意这只是一个提示,编译器仍然会根据内联预算和其他条件来决定是否内联函数。 -
考虑手动内联:如果你确定函数的内联可以提高性能,你可以手动将函数的代码复制到调用处,以实现内联。但是请注意,手动内联可能会导致代码冗余和可读性下降,所以请谨慎使用。
希望这些信息对你有帮助!如果你有其他问题,请随时提问。
英文:
Can you force Golang compiler to inline function if the only reason why the function is not being inlined is exceeding inline budget? There is no defer nor any other statements that prevent compiler to inline function - only budget limit. Or if you can't, is it possible to change the budget from 80 to let's say 160? Or maybe do you know any patterns that may help me to split it somehow.
I've got function like this:
func New() *Foo{
f := &Foo{}
f.Init()
return f
}
It's a little more complicated so it exceeds 80 budget - and because of that, it is 10x slower than it could be. It should be inlined, but not manually so the compiler can also apply some optimizations.
答案1
得分: 3
正如你所了解的,简短的答案是“不行,除非修改编译器”,但这可能会在未来发生变化。Uber一直在进行与配置引导优化相关的工作,并且今天发布了包含该工作的拉取请求。这需要一些时间来消化(我在编译器上工作,我们正在为1.18版本发布做准备,这是一个重要版本,因为它包含了泛型),但可以肯定的是我们对此很感兴趣。最早出现这个功能的可能是在1.19版本中,该版本计划在大约8个月后发布。
根据你的减速原因,将f.Init()
标记为//go:noinline
可能是有益的,这样可以使你的示例中的New
函数内联。如果在调用者中没有将该分配泄漏到堆中,那么将其内联(而不是内联f.Init()
)将暴露出进行堆栈分配的能力,从而可以节省一些时间。确保用注释标记“noinline”,解释为什么这样做
你也可以调整编译器,但这不是我告诉你的(对于针对调整后的编译器报告的任何错误,默认会受到怀疑的眼光)。
英文:
As you figured out, the short answer is "no, not without modifying the compiler", but this is likely to change in the future. Uber has been doing work with profile-guided optimization, and today published a pull request containing that work. This will take a little time to digest (I work on the compiler, we're trying to get all our ducks in a row for the 1.18 release, which is big because it contains generics) but it is safe to say that we're interested. The soonest this could appear is in 1.19, which is scheduled for 8ish months from now.
Depending on the cause of your slowdown, it might be profitable to mark f.Init()
//go:noinline
, which then allows New
in your example to be inlined. If that allocation is not leaked to the heap in the caller, then doing that inline (instead of inlining f.Init()
) exposes the ability to do a stack allocation, and you can save some time that way. Be sure to mark the "noinline" with a comment explaining why you did it :-).
You can also tinker with the compiler, but you didn't hear that from me (and any bugs that you report against a tinkered compiler by default get the stink-eye).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论