Я по-микро-оптимизации моей библиотеки, и я смотрел на созданную ASM. Я заметил, что вызов метода Arc<T> where T : MyTrait
вызывает то, что, по моему мнению, выравнивает указатель, хранящийся в ArcInner
, до 0x10.Почему происходит разыменование `Arc <T>, где T: MyTrait` выровнены с 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 (Set Nightly + Release и нажмите ASM)
Код ASM в вопросе:
movq 16(%r15), %rdi
leaq 15(%rdi), %rax
negq %rdi
andq %rax, %rdi
addq %r14, %rdi
Это важно что эта операция должна быть как можно быстрее. Поскольку разыменование ASM - это 5 инструкций, и 3 из них кажутся потенциально ненужными, я хотел бы понять, почему это происходит, и если я могу помочь. Возможно, я просто не понимаю инструкции ассемблера.
Редактировать: Мой минимальный пример не совсем то же самое, поскольку он выглядит так, что граница ящика необходима, чтобы предотвратить компилятор/компоновщик для оптимизации этой последовательности. Но последовательность точно такая же в моем случае, в жесткой петле (ржавчины), нет деструкторов: только вызов метода на Arc<TraitObject>
.
Поскольку вы оптимизируете, вы знаете, что количество инструкций не обязательно соответствует скорости программы?Например, переход к векторизованным инструкциям может потребовать больше инструкций и все же обрабатывать больше байтов за цикл. –