一、JIT編譯器可以通過將方法內聯展開(Method Inline Expansion)來提升效率,類似C++中的內聯函數(Inline Function),與C++的內聯函數不同的是,C#並不支持內聯函數,而是由JIT編譯器在運行時自動進行;
1.對於虛方法,如果JIT編譯器可以確認調用該方法時變量的運行時類型,支持方法內聯;如果不可以確認變量的運行時類型,則不支持方法內聯;對於調用空虛方法,與支持方法內聯相比,不支持內聯用時約長5倍;
※包括虛屬性、虛索引器、虛事件都不支持方法內聯;
※抽象方法與虛方法在方法內聯方面基本一致;
2.對於接口方法,如果使用該類型的變量調用,支持方法內聯;如果使用接口類型的變量調用,則不支持方法內聯;對於調用空接口方法,與使用類型的變量調用,使用接口的變量調用用時長約8倍:
public class MyBaseClass { public virtual void MyFunc() { } } public interface IMyInterface { void MyFunc(); } public class MyClass : MyBaseClass, IMyInterface { public override void MyFunc() { } } //使用時: MyClass myClass = new MyClass(); MyBaseClass myBaseClass = new myBaseClass(); IMyInterface myInterface = myClass; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); for (int i = 0; i < 1000000000; i++) { myClass.MyFunc(); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds); //320 myBaseClass = myClass; //多次賦值以使JIT編譯器無法確認該變量的運行時類型 stopwatch.Restart(); for (int i = 0; i < 1000000000; i++) { myBaseClass.MyFunc(); } Console.WriteLine(stopwatch.ElapsedMilliseconds); //1600 stopwatch.Restart(); for (int i = 0; i < 1000000000; i++) { myInterface.MyFunc(); } Console.WriteLine(stopwatch.ElapsedMilliseconds); //2560
二、其它不會內聯的情況:
1.遞歸方法;
2.包含循環語句的方法;
3.包含異常處理的方法;
4.方法體的IL代碼長度超過32字節的方法;
※可以通過在方法聲明中加入命名空間System.Runtime.CompilerServices中的特性MethodImpl來忽略這個條件:
[MethodImpl(MethodImplOptions.AggressiveInlining)] public void MyFunc() { //do… }
如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的認可是我寫作的最大動力!
作者:Minotauros
出處:https://www.cnblogs.com/minotauros/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。