เมธอดเสมือนถูกนำมาใช้โดยทั่วไปผ่านทางเมธอดเสมือนที่เรียกว่าตาราง (vtable สำหรับช่วงสั้น ๆ ) ซึ่งตัวชี้ฟังก์ชันจะถูกเก็บไว้ สิ่งนี้จะเพิ่มทางอ้อมให้กับการโทรจริง (ต้องดึงที่อยู่ของฟังก์ชั่นที่จะโทรจาก vtable จากนั้นเรียกมันว่า - ตรงข้ามกับการโทรไปข้างหน้าทันที) แน่นอนว่าต้องใช้เวลาพอสมควรและต้องใช้รหัสมากขึ้น
อย่างไรก็ตามไม่จำเป็นต้องเป็นสาเหตุหลักของความช้า ปัญหาที่แท้จริงคือคอมไพเลอร์ (โดยทั่วไป / ปกติ) ไม่สามารถรู้ได้ว่าจะเรียกใช้ฟังก์ชันใด ดังนั้นจึงไม่สามารถอินไลน์หรือดำเนินการเพิ่มประสิทธิภาพอื่น ๆ ได้ เพียงอย่างเดียวนี้อาจเพิ่มคำแนะนำที่ไม่มีจุดหมายโหล (เตรียมลงทะเบียนโทรแล้วเรียกคืนสถานะในภายหลัง) และอาจยับยั้งการเพิ่มประสิทธิภาพอื่น ๆ ที่ดูเหมือนไม่เกี่ยวข้อง ยิ่งไปกว่านั้นถ้าคุณแยกสาขาอย่างบ้าคลั่งด้วยการเรียกใช้แอพพลิเคชั่นที่แตกต่างกันคุณจะได้รับความนิยมเช่นเดียวกันกับการแตกแขนงอย่างบ้าคลั่งด้วยวิธีอื่น: แคชและตัวทำนายสาขาจะไม่ช่วยคุณสาขาจะใช้เวลานานกว่า สาขา.
ใหญ่ แต่ : ความนิยมในการแสดงเหล่านี้มักน้อยเกินไปสำหรับเรื่อง สิ่งเหล่านี้ควรพิจารณาหากคุณต้องการสร้างรหัสประสิทธิภาพสูงและพิจารณาเพิ่มฟังก์ชั่นเสมือนที่จะถูกเรียกใช้ที่ความถี่ที่น่าตกใจ แต่ยังเก็บไว้ในใจว่าเปลี่ยนสายงานเสมือนกับวิธีการอื่น ๆ ของการแยก ( if .. else
, switch
ตัวชี้ฟังก์ชั่นอื่น ๆ ) จะไม่แก้ปัญหาพื้นฐาน - มันเป็นอย่างดีอาจจะช้า ปัญหา (ถ้ามีอยู่เลย) ไม่ใช่ฟังก์ชั่นเสมือน แต่ใช้ทางอ้อม (ไม่จำเป็น)
แก้ไข: ความแตกต่างในคำแนะนำการโทรอธิบายไว้ในคำตอบอื่น ๆ โดยทั่วไปโค้ดสำหรับการโทรแบบสแตติก ("ปกติ") คือ:
- คัดลอกรีจิสเตอร์บางตัวบนสแต็กเพื่ออนุญาตให้ฟังก์ชันที่เรียกใช้ใช้รีจิสเตอร์เหล่านั้น
- คัดลอกอาร์กิวเมนต์ไปยังตำแหน่งที่กำหนดไว้ล่วงหน้าเพื่อให้ฟังก์ชันที่เรียกสามารถค้นหาได้โดยไม่คำนึงถึงตำแหน่งที่เรียกใช้
- กดที่อยู่ผู้ส่ง
- Branch / ข้ามไปยังโค้ดของฟังก์ชันซึ่งเป็นแอดเดรสคอมไพล์และด้วยเหตุนี้ฮาร์ดโค้ดในไบนารี่โดยคอมไพเลอร์ / ลิงเกอร์
- รับค่าส่งคืนจากตำแหน่งที่กำหนดไว้ล่วงหน้าและคืนค่าการลงทะเบียนที่เราต้องการใช้
การเรียกเสมือนทำสิ่งเดียวกันทุกประการยกเว้นว่าไม่ทราบที่อยู่ฟังก์ชัน ณ เวลารวบรวม คำแนะนำสองสามข้อ ...
- รับตัวชี้ vtable ซึ่งชี้ไปยังอาร์เรย์ของตัวชี้ฟังก์ชัน (ที่อยู่ฟังก์ชัน) หนึ่งตัวสำหรับแต่ละฟังก์ชันเสมือนจากวัตถุ
- รับฟังก์ชั่นที่อยู่ที่ถูกต้องจาก vtable เข้าสู่รีจิสเตอร์ (ดัชนีที่จัดเก็บฟังก์ชันที่ถูกต้องถูกตัดสินใจ ณ เวลารวบรวม)
- ข้ามไปยังที่อยู่ในการลงทะเบียนนั้นแทนที่จะข้ามไปยังที่อยู่ฮาร์ดโค้ด
สำหรับสาขา: สาขาคือสิ่งที่ข้ามไปยังคำสั่งอื่นแทนที่จะปล่อยให้คำสั่งถัดไปดำเนินการ ซึ่งรวมถึงif
,, switch
ชิ้นส่วนของลูปต่างๆ, การเรียกใช้ฟังก์ชั่น, ฯลฯ และบางครั้งคอมไพเลอร์ใช้สิ่งที่ดูเหมือนจะไม่แตกกิ่งก้านสาขาในแบบที่ต้องการสาขาภายใต้ประทุน ดูเหตุใดการประมวลผลอาร์เรย์ที่เรียงลำดับจึงเร็วกว่าอาร์เรย์ที่ไม่เรียงลำดับ เพราะเหตุใดสิ่งนี้จึงอาจช้าสิ่งที่ซีพียูทำเพื่อต่อต้านการชะลอตัวนี้และวิธีนี้ไม่ใช่วิธีแก้ทั้งหมด