如何确保没有副作用的功能被执行并且在稳定的Rust中没有被优化?
我可以使用属性组合,还是必须调用另一个带副作用的函数?在需要函数调用的情况下,Rust标准库是否提供了保证不被优化的廉价函数?
答案 0 :(得分:3)
#[no_mangle]
目前会执行此操作,但may change。
#[no_mangle]
pub fn do_what_i_say_dammit(x: i64) -> i64 { x*x }
澄清(从那篇文章):
我的心理模型是默认情况下符号由rustc拥有(例如, 如果符号是私有的,则rustc可以发出不同类型的符号 "精氨酸 - 促进"符号而不是预期的符号,只要它 处理它正确),
#[no_mangle]
转移所有权 程序员的象征。现在,因为所有权转移给了程序员,所以 不能使用未指定的符号修改方案,因此符号为 留下了无耻的。
拥有一个没有咒骂的rustc拥有的符号几乎没有任何意义(你 实际上不能使用它,因为编译器拥有它) - 所以
#[no_mangle]
暗示#[linker_owned]
。没有松散#[linker_owned]
因为 没有人实现它。
答案 1 :(得分:1)
test::black_box()
(链接到旧文档)仍然不稳定(整个test
包)。此函数采用任意类型的值并再次返回相同的值。所以它基本上是身份功能。 "哦,好吧,现在非常有用,isn't it?"你可能会讽刺地问。
但是有一些特别之处:传递的值是从LLVM中隐藏的(现在几乎所有优化都在Rust中)!它真的是一个黑盒子,因为LLVM对一段代码一无所知。并且在不知道任何事情的情况下,LLVM无法证明优化不会改变程序的行为。因此:没有优化。
它是如何做到的?让我们来看看定义:
pub fn black_box<T>(dummy: T) -> T {
// we need to "use" the argument in some way LLVM can't
// introspect.
unsafe { asm!("" : : "r"(&dummy)) }
dummy
}
如果我假装我完全理解这段代码,我会撒谎,但它就是这样的:我们插入空的内联汇编(不是单个指令),但告诉Rust(告诉LLVM)这段程序集使用变量dummy
。这使得优化器无法推断变量。 Stupid compiler,很容易欺骗,muhahahaha!如果你想要另一个解释,Chandler Carruth explained the dark magic参加CppCon 2015。
那么你现在如何使用它?只需将它用于某种价值......需要计算经过black_box()
的任何事情。这样的事情怎么样?
black_box(my_function());
需要计算my_function()
的返回值,因为编译器无法证明它是无用的!因此函数调用不会被删除。但请注意,您必须使用不稳定的功能(test
crate或inline asm自行编写函数)或使用FFI。我当然不会在生产库中发布这种代码,但它对于测试目的肯定有用!