โทษประสิทธิภาพของการใช้ clone_from_slice () แทน copy_from_slice ()?
ใน Rust มีสองวิธีการในการปรับปรุงเนื้อหาของชิ้นจากชิ้นอื่นนี้และclone_from_slice() copy_from_slice()พฤติกรรมของทั้งสองฟังก์ชั่นที่มีความแปลกใจเลย - ครั้งแรกที่ไม่โคลนและคาดว่าประเภทที่จะดำเนินการในขณะที่สองไม่สำเนาและคาดว่าประเภทที่จะดำเนินการCloneCopy
อย่างไรก็ตามฉันประหลาดใจที่เอกสารประกอบclone_from_sliceระบุว่า: "หากมีTการใช้งานCopyก็สามารถใช้งานได้copy_from_sliceดีกว่า" เป็นที่น่าแปลกใจที่ควรมีความแตกต่างด้านประสิทธิภาพที่นี่ หากTดำเนินการCopyแล้ว.clone()จะต้องเทียบเท่ากับการคัดลอกบิต; อย่างไรก็ตามเนื่องจากคอมไพเลอร์รู้ว่าประเภทTใดจึงควรจะสามารถทราบได้ว่าสามารถทำสำเนาบิตได้หรือไม่แม้ว่าฉันจะใช้clone_from_slice.
แล้วความไม่มีประสิทธิภาพเกิดขึ้นจากไหน?
คำตอบ
TL; DRโปรดตรวจสอบแหล่งที่มาของclone_from_sliceก็จะเข้ามาเยี่ยมชมทุกองค์ประกอบของชิ้นและเรียกcloneสำหรับแต่ละขณะcopy_from_slicememcpyสำเนาโดยตรงบิตทั้งหมดที่มี
ถ้า T ดำเนินการ
Copyแล้ว.clone()จะต้องเทียบเท่ากับบิตการคัดลอก
แม้ว่าทุกCopyประเภทจะใช้งานCloneตามค่าเริ่มต้นโดยcloneใช้ปุ่มcopy ; clone_from_sliceจะยังคงสำรวจชิ้นส่วนและทำสำเนาในขณะที่ข้ามผ่าน
แต่ไม่มีข้อเสนอนี้ถูกต้องสำหรับสิ่งดั้งเดิม แต่ไม่ถูกต้องสำหรับกรณีต่อไปนี้ :
#[derive(Copy)]
struct X;
impl Clone for X {
fn clone(&self) -> Self {
//do some heavy operation or light(depends on the logic)
X
}
}
ในขณะที่Cloneสามารถใช้งานได้โดยตรรกะทุกCopyประเภทจะคัดลอกบิตเมื่อทำซ้ำวัตถุ
หากใช้ T
Copyก็สามารถใช้งานได้ดีขึ้นcopy_from_slice
สิ่งสำคัญอยู่ที่นี่เอกสารระบุว่า " มันสามารถ " ไม่ " มันจะเป็น " ซึ่งนำมาซึ่งความเป็นไปได้เช่น
Cloneการนำไปใช้โดยตรงสามารถใช้Copyการนำไปใช้งานได้ สำหรับประเภทพื้นฐานเช่น primitives เครื่องมือเพิ่มประสิทธิภาพอาจใช้memcpyแทนการข้ามผ่านโดยตรงจากนั้นเราอาจยอมรับว่าข้อเสนอนี้ผิดเพราะจะไม่มีประสิทธิภาพCloneการนำไปใช้โดยตรงสามารถใช้Copyการนำไปใช้งานได้ สำหรับประเภทที่ซับซ้อน (ปัญหาการข้ามผ่านด้านบน) ทำให้ประพจน์นี้ถูกต้อง (ฉันแก้ไขตัวอย่างจาก @kmdreko ด้วยโครงสร้างที่ซับซ้อนขึ้นเล็กน้อยโปรดตรวจสอบผลลัพธ์จาก godbolt )Cloneการใช้งานเป็นแบบกำหนดเองและเป็นCopyประเภทข้อนี้จะทำให้ข้อเสนอนี้ถูกต้องแม้การใช้งานแบบกำหนดเองจะมีราคาไม่แพงcopyสำหรับชิ้นส่วนขนาดใหญ่ที่ใช้memcpyอาจมีประโยชน์มากกว่า