Hukuman kinerja menggunakan clone_from_slice () daripada copy_from_slice ()?
Di Rust, ada dua metode untuk memperbarui konten suatu potongan dari potongan lain: clone_from_slice()dan copy_from_slice(). Perilaku kedua fungsi ini tidak mengejutkan - yang pertama melakukan klon dan mengharapkan tipe untuk diimplementasikan Clone, sementara yang kedua melakukan salinan dan mengharapkan tipe untuk diimplementasikan Copy.
Namun, saya terkejut bahwa dokumentasi untuk clone_from_slicemengatakan ini: "Jika Tdiimplementasikan Copy, dapat lebih efektif untuk digunakan copy_from_slice." Mengejutkan bahwa seharusnya ada perbedaan kinerja di sini. Jika Tmengimplementasikan Copy, maka .clone()diperlukan setara dengan menyalin bit; namun karena kompilator mengetahui jenisnya T, ia harus dapat mengetahui apakah ia dapat melakukan penyalinan bitwise bahkan jika saya menggunakannya clone_from_slice.
Jadi darimana timbulnya inefisiensi kinerja?
Jawaban
TL; DR Silakan periksa sumber clone_from_slice , itu mengunjungi semua elemen slice dan memanggil clonemasing-masing, sementara copy_from_slice langsung menyalin semua bit dengan memcpy.
Jika T mengimplementasikan
Copy, maka.clone()diperlukan setara dengan menyalin bit
Bahkan jika setiap Copytipe akan diimplementasikan Clonesecara default di mana clonesecara langsung menggunakancopy ; clone_from_sliceakan tetap melintasi irisan dan melakukan penyalinan saat melintasi.
Tetapi tidak ada proposisi ini yang benar untuk kaum primitif tetapi tidak benar untuk kasus-kasus seperti di bawah ini :
#[derive(Copy)]
struct X;
impl Clone for X {
fn clone(&self) -> Self {
//do some heavy operation or light(depends on the logic)
X
}
}
Sementara Clonedapat diimplementasikan oleh semua Copyjenis logika hanya akan menyalin bit ketika menduplikasi suatu objek.
Jika T mengimplementasikan
Copy, itu bisa lebih berkinerja untuk digunakancopy_from_slice
Yang penting di sini, dokumentasinya mengatakan " bisa jadi " bukan " akan jadi ", ini membawa kemungkinan seperti
Cloneimplementasi bisa langsung menggunakanCopyimplementasi. Untuk tipe dasar seperti primitif, pengoptimal dapat langsung menggunakanmemcpyalih-alih melintasi, maka kami mungkin menerima proposisi ini sebagai salah karena satu tidak akan berkinerja kemudian yang lain.Cloneimplementasi bisa langsung menggunakanCopyimplementasi. Untuk tipe kompleks (masalah traverse di atas) membuat proposisi ini benar. (Saya telah mengedit contoh dari @kmdreko dengan struktur yang sedikit lebih kompleks, silakan periksa hasil dari godbolt )CloneImplementasinya adalah kustom dan itu adalahCopytipe, yang satu ini akan membuat proposisi ini benar meskipun implementasi kustom tidak mahal makacopyuntuk penggunaan irisan besarmemcpymungkin lebih bermanfaat.