我对我的库进行了过度微优化,我正在查看生成的 ASM。我注意到调用 Arc<T> where T : MyTrait
的方法产生一些我认为正在对齐存储在 ArcInner
中的指针的东西到 0x10。
我用这段代码复制了它:
#![feature(test)]
extern crate test;
use std::sync::Arc;
struct DA;
trait Drain {
fn log(&self, &DA);
}
struct BlackBoxDrain;
impl Drain for BlackBoxDrain {
fn log(&self, da: &DA) {
test::black_box::<&DA>(da);
}
}
fn f(d: Arc<Drain>) {
d.log(&DA)
}
fn main() {
let arc_d = Arc::new(BlackBoxDrain);
f(arc_d);
}
Rust playground (设置Nightly + Release 点击ASM)
有问题的 ASM 代码是:
movq 16(%r15), %rdi
leaq 15(%rdi), %rax
negq %rdi
andq %rax, %rdi
addq %r14, %rdi
重要的是这个操作要尽可能快。由于 ASM 取消引用是 5 条指令,其中 3 条似乎可能是不必要的,所以我想了解为什么会发生这种情况以及是否可以提供帮助。也许我只是不明白这里的汇编指令。
编辑:我的最小示例并不完全相同,因为它看起来需要 crate 边界来防止编译器/链接器优化该序列。但在我的例子中,顺序完全相同,在一个紧密的(rust bench)循环中,没有涉及析构函数:只有一个方法调用 Arc<TraitObject>
.
最佳答案
感谢 Chris Emerson 的回答,我意识到它与 vtable 和对齐规则有关。然后我在 Mozilla 的 Rust IRC channel 上四处询问,aatch 和 talchas 弄明白了:
rustc
将始终计算存储在 T
中的数据( ArcInner<T>
)的对齐偏移量- 因为每个 struct
可能不同实现 T
.这没什么大不了的 - 因为这些指令非常快,并且会受到良好指令级 CPU 并行化的影响。
关于assembly - 为什么取消引用 `Arc<T> where T : MyTrait` 对齐到 0x10?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42332615/