คอมไพเลอร์ C # นั้นไม่ได้เปลี่ยนแปลง IL ที่ปล่อยออกมาอย่างมากใน build build สิ่งที่น่าสังเกตคือมันไม่ปล่อย opcode ของ NOP อีกต่อไปที่ให้คุณตั้งเบรกพอยต์บนวงเล็บปีกกาแบบหยัก ตัวใหญ่คือเครื่องมือเพิ่มประสิทธิภาพที่สร้างไว้ในคอมไพเลอร์ JIT ฉันรู้ว่ามันทำให้การเพิ่มประสิทธิภาพต่อไปนี้:
วิธีการแบบอินไลน์ การเรียกเมธอดจะถูกแทนที่ด้วยการฉีดโค้ดของเมธอด นี่เป็นเรื่องใหญ่มันทำให้ผู้เข้าถึงอสังหาริมทรัพย์เป็นอิสระ
การจัดสรร CPU register ตัวแปรโลคัลและอาร์กิวเมนต์เมธอดสามารถเก็บอยู่ในการลงทะเบียน CPU โดยไม่ต้องถูกเก็บไว้ที่เฟรมสแต็ก นี่เป็นโค้ดตัวใหญ่ที่โดดเด่นในการทำการดีบักโค้ดที่ปรับให้เหมาะสมยากมาก และให้ความหมายกับคำสำคัญที่ระเหยได้
การตรวจสอบดัชนีอาร์เรย์ การปรับให้เหมาะสมที่สำคัญเมื่อทำงานกับอาร์เรย์ (คลาสคอลเลกชัน. NET ทั้งหมดใช้อาร์เรย์ภายใน) เมื่อคอมไพเลอร์ JIT สามารถตรวจสอบว่าลูปไม่เคยทำดัชนีอาร์เรย์นอกขอบเขตมันจะกำจัดการตรวจสอบดัชนี ตัวใหญ่
วนคลี่ออก ลูปที่มีร่างเล็ก ๆ ได้รับการปรับปรุงโดยทำซ้ำรหัสมากถึง 4 เท่าในร่างกายและวนซ้ำน้อยลง ลดค่าใช้จ่ายสาขาและปรับปรุงตัวเลือกการดำเนินการประมวลผลแบบสเกลาร์ขั้นสูงของโปรเซสเซอร์
การกำจัดรหัสที่ตายแล้ว คำสั่งเช่นว่า (false) {/ ... /} ได้รับการกำจัดโดยสมบูรณ์ สิ่งนี้สามารถเกิดขึ้นได้เนื่องจากการพับและอินไลน์อย่างต่อเนื่อง กรณีอื่น ๆ คือที่ที่คอมไพเลอร์ JIT สามารถระบุได้ว่าโค้ดไม่มีผลข้างเคียงที่เป็นไปได้ การเพิ่มประสิทธิภาพนี้เป็นสิ่งที่ทำให้รหัสการทำโปรไฟล์ยุ่งยากมาก
การชักรหัส โค้ดภายในลูปที่ไม่ได้รับผลกระทบจากลูปสามารถย้ายออกจากลูปได้ เครื่องมือเพิ่มประสิทธิภาพของคอมไพเลอร์ C จะใช้เวลามากขึ้นในการหาโอกาสในการยก อย่างไรก็ตามมันเป็นการเพิ่มประสิทธิภาพที่มีราคาแพงเนื่องจากการวิเคราะห์การไหลของข้อมูลที่ต้องการและกระวนกระวายใจไม่สามารถมีเวลาดังนั้นยกเฉพาะกรณีที่ชัดเจน บังคับให้โปรแกรมเมอร์. NET เขียนซอร์สโค้ดที่ดีขึ้นและยกตัวเองขึ้นมา
กำจัดการแสดงออกย่อยทั่วไป x = y + 4; z = y + 4; กลายเป็น z = x; ค่อนข้างธรรมดาในงบเช่น dest [ix + 1] = src [ix + 1]; เขียนเพื่อความสะดวกในการอ่านโดยไม่แนะนำตัวแปรตัวช่วย ไม่จำเป็นต้องประนีประนอมการอ่าน
พับอย่างต่อเนื่อง x = 1 + 2; กลายเป็น x = 3; ตัวอย่างง่ายๆนี้รวบรวมโดยผู้รวบรวมแต่ทว่าเกิดขึ้นที่ JIT เมื่อการเพิ่มประสิทธิภาพอื่นทำให้เป็นไปได้
คัดลอกการขยายพันธุ์ x = a; y = x; กลายเป็น y = a; สิ่งนี้ช่วยให้ผู้จัดสรรตัวลงทะเบียนทำการตัดสินใจได้ดีขึ้น มันเป็นเรื่องใหญ่ในกระวนกระวายใจ x86 เพราะมีการลงทะเบียนน้อยมากที่จะทำงานกับ การเลือกสิ่งที่ถูกต้องเป็นสิ่งสำคัญยิ่ง
สิ่งเหล่านี้คือการปรับแต่งที่สำคัญมากซึ่งสามารถสร้างความแตกต่างอย่างมากเมื่อคุณสร้างโปรไฟล์ Debug build ของแอพและเปรียบเทียบกับ Build build เรื่องนี้มีความสำคัญจริง ๆ เท่านั้นแม้ว่าเมื่อรหัสอยู่บนเส้นทางที่สำคัญของคุณ 5 ถึง 10% ของรหัสที่คุณเขียนนั้นจริงมีผลกระทบต่อ perf ของโปรแกรมของคุณ เครื่องมือเพิ่มประสิทธิภาพ JIT ไม่ฉลาดพอที่จะรู้ล่วงหน้าว่าอะไรสำคัญ แต่สามารถใช้การหมุน "หมุนเป็นสิบเอ็ด" สำหรับรหัสทั้งหมดเท่านั้น
ผลลัพธ์ที่มีประสิทธิภาพของการเพิ่มประสิทธิภาพเหล่านี้ในเวลาดำเนินการของโปรแกรมของคุณมักได้รับผลกระทบจากรหัสที่ทำงานที่อื่น การอ่านไฟล์การเรียกใช้งานเคียวรี dbase เป็นต้นการทำให้งานเครื่องมือเพิ่มประสิทธิภาพ JIT ไม่สามารถมองเห็นได้อย่างสมบูรณ์ ไม่เป็นไร :)
เครื่องมือเพิ่มประสิทธิภาพ JIT เป็นรหัสที่น่าเชื่อถือส่วนใหญ่เป็นเพราะได้รับการทดสอบนับล้านครั้ง มันเป็นเรื่องยากมากที่จะมีปัญหาในรุ่นที่วางจำหน่ายของโปรแกรมของคุณ มันเกิดขึ้นได้อย่างไร ทั้ง x64 และ x86 jitters มีปัญหากับ structs x86 jitter มีปัญหากับความสอดคล้องจุดลอยตัวทำให้เกิดผลลัพธ์ที่แตกต่างอย่างละเอียดเมื่อตัวกลางของการคำนวณจุดลอยตัวถูกเก็บไว้ในการลงทะเบียน FPU ที่ความแม่นยำ 80 บิตแทนที่จะถูกตัดเมื่อล้างหน่วยความจำ