MethodImpl最佳化效能

JohnYang819發表於2024-11-12

引數解釋
MethodImplOptions.AggressiveInlining:請求編譯器在可能的情況下對方法進行內聯。

MethodImpl:這是一個屬性,允許開發者為方法指定特定的實現行為,比如請求內聯、忽略棧追蹤等。

內聯的作用
內聯的主要作用是提升效能,特別是在如下情況下:

消除方法呼叫開銷:通常方法呼叫需要進行引數傳遞和棧幀管理等操作,內聯可以省去這些開銷。
減少分支跳轉:內聯將方法體直接插入到呼叫程式碼中,減少了方法呼叫產生的分支跳轉。
最佳化記憶體使用:在較小的、頻繁呼叫的方法上,內聯能降低方法呼叫對棧的負擔,進一步最佳化執行時記憶體使用。
使用內聯的典型場景
AggressiveInlining 常用在一些簡單的、頻繁呼叫的 輔助方法或屬性 上,比如:

簡單的數學運算函式
小型的幫助方法(如字串處理)
屬性 Getter 和 Setter,尤其在屬性只是簡單的欄位返回或賦值時
內聯適合的場景與限制
雖然 AggressiveInlining 可以顯著提升小型方法的效能,但編譯器可能會根據情況選擇不內聯該方法,特別是在以下情況下:

方法體較大:內聯會導致呼叫方程式碼量增大。如果一個方法程式碼體積過大,編譯器可能會忽略 AggressiveInlining 請求,以避免生成的程式碼過於龐大。
遞迴方法:對於遞迴方法,內聯並不適用,因為遞迴需要自身呼叫,無法單純地替換成一段程式碼。
異常處理:方法包含複雜的異常處理邏輯時,內聯會增加程式碼複雜度,編譯器有時會避免內聯這樣的程式碼。

  [MethodImpl(MethodImplOptions.AggressiveInlining)]
  public static int InlineAdd(int x,int y)
  {
      return x + y;
  }
  public static int NotInlineAdd(int x,int y)
  {
      return x + y;
  }
  static int TestInlineAdd()
  {
      int result = 0;
      for(int i = 0; i < 1000000000; i++)
      {
          result = InlineAdd(result,i);
      }
      return result;
  }
  static int TestNotInlineAdd()
  {
      int result = 0;
      for (int i = 0; i < 1000000000; i++)
      {
          result = NotInlineAdd(result, i);
      }
      return result;
  }

        static void Main(string[] args)
        {

            var stopwatch = Stopwatch.StartNew();
            TestInlineAdd();
            stopwatch.Stop();
            Console.WriteLine($"Inline Method Time: {stopwatch.ElapsedMilliseconds} ms");

            stopwatch.Restart();
            TestNotInlineAdd();
            stopwatch.Stop();
            Console.WriteLine($"NotInline Method Time: {stopwatch.ElapsedMilliseconds} ms");}



可以看出使用內聯的測試方法,CPU使用率相對較低。

相關文章