Rust会优化掉未使用的函数参数吗?

5

我有一个类型为

f: fn(x: SomeType, y: Arc<()>) -> ISupposeTheReturnTypeDoesNotMatter

在编译时(无论是否进行优化),y会被优化掉吗? y的意图是限制f的运行实例数量,如果引用y的次数太多,调用f的调用者将不会调用f,直到y的引用计数降低为止。
编辑:澄清我的意图
意图是控制正在运行的http请求的数量(由上述f表示),伪代码如下:
let y = Arc::new(());
let all_jobs_to_be_done = vector_of_many_jobs;
loop {
    while y.strong_count() < some_predefined_limit {
        // we have some free slots, fill them up with instances of f,
        // f is passed with a clone of y,
        // so that the running of f would increase the ref count,
        // and the death of the worker thread would decrease the ref count
        let work = all_jobs_to_be_done.pop();
        let ticket = y.clone();
        spawn_work(move || {f(work, ticket)});
    }

    sleep_for_a_few_seconds();
}

这种看似不太正常的解决方案是因为我找不到符合我的需求的库(使用有限数量的异步(tokio)工作线程消耗一个变化中的工作队列,并在作业失败时重新排队)。


听起来是一个有趣的问题,写一个小测试来调查它的行为。 - Simson
4
我更喜欢规范而非观察。在调试版本中,观察到的是它不会被优化掉,但这也可能意味着我没有满足优化器的要求,也许对于某些其他代码排列方式,它会被优化掉。 - Incömplete
除非您手动指定更高级别的优化,否则调试构建不会优化任何内容。 - Herohtar
1
由于调用方中存在所有引用计数限制逻辑,为什么要将 Arc 传递给被调用方?就像你所说,它在那里没有被使用...我不明白在函数签名中保留它的目的。 - eggyal
实际上,你可以在不将Arc传递给函数的情况下实现相同的效果,而是在函数返回后在生成的闭包中丢弃它。 - eggyal
显示剩余2条评论
1个回答

6
Rust是否会对未使用的函数参数进行优化?
是,LLVM(rustc的后端)可以在删除未使用变量时优化掉它们,前提是删除不会改变程序行为,尽管没有任何保证。rustc也有一些在LLVM之前的处理过程,但同样适用。
了解什么精确地算作程序行为是棘手的问题。然而,用于引用计数机制的多线程原语通常是那种由于充分理由不能被优化掉的东西。请参阅Rust参考资料以获取更多信息(可能有所帮助的其他资源包括nomicon、不同的GitHub存储库、Rust fora、Rust使用的C++11内存模型等)。
另一方面,如果您问的是当它遇到未使用的参数时语言的语义是什么,那么不,Rust不会忽略它们(也希望永远不会!)。
“y”是否会被优化掉?
不会,它是一个具有副作用的类型。例如,将其丢弃需要运行非平凡代码。
“y”的意图是限制运行实例“f”的数量
这种安排并不限制运行“f”的线程数,因为Arc不是互斥量,即使它是某种类型的互斥量,您也可以构造出任意数量的独立互斥量。

感谢澄清。限制是手动完成的,在调用f的地方,会有类似这样的代码 if y.strong_count() > some_number then wait_until_ref_count_lowers() else f(x, y.clone()),限制并不是硬性限制,只要在某个特定数字左右就可以了。 - Incömplete
1
不客气!如果信号量逻辑在外部,则无需将其传递给 f - Acorn
@Acorn FWIW,虽然Arc确实具有副作用,但是该函数可以内联,并且可以完全删除父级中的arc克隆。如果您删除-O,则可以在编译输出中看到对Arc::clone的调用,但是使用-O整个过程都会消失。 - Masklinn
3
@Masklinn 调用名为 clone 的函数被移除,但是 Arc 的克隆(作为概念)并没有被移除,在优化后的输出中出现了 lock addlock sub 指令。在 OP 的问题背景下,该参数由于本答案所述的原因并没有被优化掉。 - user4815162342
@Masklinn,它并没有被删除,你仍然拥有分支和锁定操作,就像user4815162342所提到的那样。这些是我在回答中提到的“用于引用计数机制的多线程原语”。你所看到的“已删除”只是内联和其他传递的结果。 - Acorn

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