ฉันอ้างว่าเป็นเพื่อนร่วมงานที่if (i < input.size() - 1) print(0);จะได้รับการเพิ่มประสิทธิภาพในวงนี้เพื่อที่input.size()จะไม่ได้อ่านทุกครั้ง แต่มันกลับกลายเป็นว่านี่ไม่ใช่กรณี!
void print(int x) {
std::cout << x << std::endl;
}
void print_list(const std::vector<int>& input) {
int i = 0;
for (size_t i = 0; i < input.size(); i++) {
print(input[i]);
if (i < input.size() - 1) print(0);
}
}
ตามCompiler Explorerพร้อมตัวเลือก gcc -O3 -fno-exceptionsเรากำลังอ่านการinput.size()วนซ้ำแต่ละครั้งและใช้leaเพื่อทำการลบ!
movq 0(%rbp), %rdx
movq 8(%rbp), %rax
subq %rdx, %rax
sarq $2, %rax
leaq -1(%rax), %rcx
cmpq %rbx, %rcx
ja .L35
addq $1, %rbx
ที่น่าสนใจใน Rust การเพิ่มประสิทธิภาพนี้เกิดขึ้น ดูเหมือนว่าiจะได้รับการแทนที่ด้วยตัวแปรjที่เป็น decremented ซ้ำกันและการทดสอบจะถูกแทนที่ด้วยสิ่งที่ชอบi < input.size() - 1j > 0
fn print(x: i32) {
println!("{}", x);
}
pub fn print_list(xs: &Vec<i32>) {
for (i, x) in xs.iter().enumerate() {
print(*x);
if i < xs.len() - 1 {
print(0);
}
}
}
ในคอมไพเลอร์ Explorerแอสเซมบลีที่เกี่ยวข้องมีลักษณะดังนี้:
cmpq %r12, %rbx
jae .LBB0_4
ฉันตรวจสอบและฉันค่อนข้างแน่ใจว่าr12เป็นxs.len() - 1และrbxเป็นเคาน์เตอร์ ก่อนหน้านี้มีการaddสำหรับrbxและด้านนอกของวงเข้าmovr12
ทำไมนี้ ดูเหมือนว่าหาก GCC สามารถอินไลน์ได้size()และoperator[]อย่างที่มันทำมันควรจะรู้ว่าsize()มันไม่เปลี่ยนแปลง แต่เครื่องมือเพิ่มประสิทธิภาพของ GCC อาจตัดสินว่ามันไม่คุ้มค่าที่จะดึงมันออกมาเป็นตัวแปรหรือไม่? หรืออาจมีผลข้างเคียงอื่น ๆ ที่อาจทำให้สิ่งนี้ไม่ปลอดภัย - ไม่มีใครรู้หรือไม่?
cout.operator<<()นี่คือปัญหาการเรียกฟังก์ชั่นที่ไม่ใช่แบบอินไลน์ไป คอมไพเลอร์ไม่ทราบว่าฟังก์ชั่นกล่องดำนี้ไม่ได้รับการอ้างอิงถึงstd::vectorจากโกลบอล
printlnหรือoperator<<เป็นกุญแจ
printlnอาจจะเป็นวิธีการที่ซับซ้อนคอมไพเลอร์อาจจะมีปัญหาในการพิสูจน์ว่าprintlnไม่กลายพันธุ์เวกเตอร์