C#效率優化(2)-- 方法內聯

weixin_30639719發表於2019-01-31

  一、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/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

轉載於:https://www.cnblogs.com/minotauros/p/10341386.html

相關文章