【问题标题】:Will Rust optimize away unused function arguments?Rust 会优化掉未使用的函数参数吗?
【发布时间】:2020-09-02 01:14:23
【问题描述】:

我有一个类型的函数

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();
}

这个看似 hacky 的解决方法的原因是我找不到满足我需求的库(使用有限数量的异步 (tokio) 工作者使用不断变化的工作队列,并在作业失败时重新排队工作)

【问题讨论】:

  • 听起来是个有趣的问题,写一个小测试来调查它的行为
  • 我更喜欢规范而不是观察。对于调试构建,观察是它不会被优化掉,但这也可能意味着我没有满足优化器的要求,也许对于其他一些代码安排,它会被优化掉。
  • 调试版本不会优化任何东西,除非您手动指定更高级别的优化。
  • 既然调用者中的所有引用计数限制逻辑,为什么将Arc 传递给被调用者?正如你所说,它在那里没有使用......我不明白将它保留在函数签名中的目的。
  • @eggyal 要利用移动语义和变量生存期,请参阅我的编辑。

标签: rust compiler-optimization


【解决方案1】:

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

是的,LLVM(rustc 的后端)能够在删除未使用的变量时优化掉它们并不会改变程序的行为,尽管没有任何保证它会这样做。 rustc 在 LLVM 之前也有一些通过,但同样适用。

了解究竟什么才是程序行为是一件棘手的事情。但是,引用计数机制中使用的多线程原语通常是无法出于充分理由优化掉的东西。有关更多信息,请参阅 Rust 参考(其他可能有帮助的资源是 nomicon、不同的 GitHub 存储库、Rust 论坛、Rust 使用的 C++11 内存模型等)。

另一方面,如果你问的是语言在遇到未使用的参数时的语义是什么,那么不,Rust 不会忽略它们(希望永远不会!)。

y 会被优化掉吗?

不,是有副作用的类型。例如,删除它需要运行重要的代码。

y的目的是限制f的运行实例数

这样的安排不会限制运行f 的线程数,因为Arc 不是互斥体,即使它是某种互斥体,您也可以构建任意数量的独立线程。

【讨论】:

  • 感谢您的澄清。限制是手动完成的,f的调用者之一,有这样的if y.strong_count() &gt; some_number then wait_until_ref_count_lowers() else f(x, y.clone()),限制不是硬限制,只要在一定数量左右就可以了。
  • 不客气!如果信号量逻辑在外面,则无需传递给f
  • @Acorn FWIW 而 Arc 确实有副作用,the function could be inlined and arc-cloning in the parent removed entirely。如果您删除 -O,您可以在编译后的输出中看到对 Arc::clone 的调用,但使用 -O,整个事情就消失了。
  • @Masklinn 删除了对名为 clone 的函数的调用,但删除了 Arc 的克隆(作为一个概念),lock addlock sub 指令存在于优化的输出中。在 OP 的问题的上下文中,由于此答案中解释的原因,该论点没有被优化掉。
  • @Masklinn 它没有被删除,你仍然有 user4815162342 提到的分支和锁定操作。这些就是我在“多线程原语用于引用机制”的答案中所指的那种东西。您所看到的“已删除”只是内联和其他传递的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-26
  • 2010-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-23
  • 2021-02-13
相关资源
最近更新 更多