Rust中的空函数是否会被优化掉?

6
我希望在我的代码中将一些影响性能的函数调用放入功能门后。如果该功能未启用,我想只需实现一个空实现的函数即可。这样,希望 Rust 编译器可以完全从函数中删除它。
类似这样:
// Included if feature is enabled
fn foo() {
    // ...
}

// Included if the feature is disabled
fn foo() {}

// Performance critical code
for i in 1..1000000000 {
    // ...
    foo();
}

如果foo()函数为空,那么这个调用会被优化掉吗?

2个回答

11

在令人惊叹的编译器探索器中尝试一下吧 :)

您的示例的结果汇编代码为:

example::main:
    push    rbp
    mov     rbp, rsp
    mov     eax, 1
.LBB0_1:
    xor     ecx, ecx
    cmp     eax, 1000000000
    setl    cl
    add     ecx, eax
    cmp     eax, 1000000000
    mov     eax, ecx
    jl      .LBB0_1
    pop     rbp
    ret

如您所见,这里没有call指令,并且foo()根本没有被调用。 但是,您可能会想知道为什么循环不会被删除,因为它对外部世界没有影响。 我可以假设有时这些循环实际上是用来浪费时间的。 如果将计数器减少到100,则循环完全被删除。

总之:是的,优化器会删除空函数!


我在想为什么循环本身没有被删除,感谢您提到了它;也许有人可以解释这种行为。 - ljedrz
2
这个循环的行为真的很奇怪(特别是100的阈值)。当使用Clang时,这些循环会被完全删除,所以我认为LLVM也能够用Rust做到这一点,但我似乎无法触发它 :x - Matthieu M.
我相信这只是Compiler Explorer没有进行所有优化的问题。在我的电脑上,我得到的示例汇编代码与“fn main() {}”完全相同。 - paholg
1
您可以传递 -C remark=all 以查看优化备注。循环无法进行优化,因为“无法确定循环迭代次数”@paholg @MatthieuM - kennytm
1
刚刚在 https://github.com/rust-lang/rust/issues/41097 提交了一个关于循环优化记录的问题。 - kennytm
显示剩余3条评论

1
根据我在当前稳定版本的 Rust 上使用发布模式进行检查,以下代码如下:
fn foo() {}


fn main() {
    for _ in 1..1000000000 {
        foo();
    }

    println!(); // a side effect so that the whole program is not optimized away
}

编译后的汇编代码与循环为空时相同:

for _ in 1..1000000000 {}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接