簡體   English   中英

靜態方法與實例方法的性能

[英]Performance of static methods vs instance methods

我的問題涉及靜態方法與實例方法的性能特征及其可伸縮性。 假設在這種情況下,所有類定義都在一個程序集中,並且需要多個離散指針類型。

考慮:

public sealed class InstanceClass
{
      public int DoOperation1(string input)
      {
          // Some operation.
      }

      public int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more instance methods.
}

public static class StaticClass
{
      public static int DoOperation1(string input)
      {
          // Some operation.
      }

      public static int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more static methods.
}

上述類表示輔助樣式模式。

在實例類中,解析實例方法需要花費一些時間來與StaticClass相反。

我的問題是:

  1. 保持狀態不是問題(不需要字段或屬性),使用靜態類總是更好嗎?

  2. 如果有相當多的靜態類定義(例如100,每個都有許多靜態方法),那么與相同數量的實例類定義相比,這會對執行性能或內存消耗產生負面影響嗎?

  3. 當調用同一實例類中的另一個方法時,實例解析是否仍然發生? 例如,在同一實例的DoOperation1中使用[this]關鍵字,如this.DoOperation2("abc")

理論上,靜態方法應該比實例方法稍好一些,所有其他條件相同,因為額外隱藏了this參數。

在實踐中,這幾乎沒有什么區別,它將隱藏在各種編譯器決策的噪音中。 (因此,兩個人可以“證明”一個人比另一個人更好,但結果不一致)。 尤其是因為this通常是在寄存器中傳遞的,並且通常在該寄存器中開始。

最后一點意味着理論上,我們應該期望一個靜態方法,它將一個對象作為一個參數,並用它做一些事情,比同等對象上的一個實例稍微好一些。 但是,差異非常小,如果你試圖測量它,你可能最終會測量其他一些編譯器的決定。 (特別是因為該參考在整個時間內在寄存器中的可能性也非常高)。

真正的性能差異將歸結為你是否人為地在內存中獲取對象來做一些自然是靜態的事情,或者你是以復雜的方式糾纏對象傳遞鏈以做自然應該實例化的事情。

因此對於數字1.當保持狀態不是一個問題時,靜態總是更好, 因為這是靜態的 這不是一個性能問題,盡管有一個整體規則可以很好地與編譯器優化相配合 - 更有可能是有人去努力優化正常使用的案例,而不是那些出現奇怪用法的案例。

2號沒有區別。 每個成員都有一定數量的每類成本,它包括有多少元數據,實際DLL或EXE文件中有多少代碼,以及有多少jitted代碼。 無論是實例還是靜態,都是一樣的。

隨着第3項, this是因為this確實。 但請注意:

  1. this參數在特定寄存器中傳遞。 當調用同一個類中的實例方法,它很可能會成為該寄存器已經(除非它被藏匿和使用某種原因寄存器),因此沒有設置必要的行動this給它需要設置什么至。 這在某種程度上適用於例如該方法的前兩個參數是它所進行的調用的前兩個參數。

  2. 由於很明顯this不是null,因此在某些情況下可以用來優化調用。

  3. 由於很明顯this不是null,這可能會使內聯方法調用再次變得更有效,因為偽造方法調用所產生的代碼可以省略它可能需要的一些空檢查。

  4. 也就是說,空檢查很便宜!

值得注意的是,作用於對象而非實例方法的通用靜態方法可以減少http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-中討論的一些成本。 相關開銷/在沒有為給定類型調用給定靜態的情況下。 正如他所說:“不過,事實證明,擴展方法是使通用抽象更加付費的好方法。”

但是,請注意,這僅涉及該方法使用的其他類型的實例化,否則不存在。 因此,它確實不適用於很多情況(某些其他實例方法使用該類型,其他一些代碼使用該類型)。

摘要:

  1. 大多數情況下,實例與靜態的性能成本低於可忽略不計。
  2. 例如,濫用靜態的地方通常會產生什么成本,反之亦然。 如果您沒有在靜態和實例之間做出決定,那么您更有可能獲得正確的結果。
  3. 在極少數情況下,另一種類型的靜態泛型方法導致創建的類型少於實例泛型方法,這使得它有時可以很少使用很少使用(並且“很少”指的是它在其中使用的類型。應用程序的生命周期,而不是它的調用頻率)。 一旦你在那篇文章中得到他正在談論的內容,你就會發現它與大多數靜態vs實例決策無關。 編輯:它主要只有ngen的成本,而不是jitted代碼。

編輯:關於如何便宜的空檢查的說明(我在上面聲稱)。 .NET中的大多數空檢查根本不檢查null,而是繼續它們將要做的假設它將起作用,並且如果發生訪問異常,它將變為NullReferenceException 因此,大多數情況下,從概念上講,C#代碼涉及進行空檢查,因為它正在訪問實例成員,如果成功則成本實際為零。 一個例外是一些內聯調用,(因為他們希望表現得好像他們調用了一個實例成員)並且他們只是按一個字段來觸發相同的行為,因此它們也非常便宜,但它們仍然經常被遺漏(例如,如果方法的第一步涉及訪問字段)。

保持狀態不是問題(不需要字段或屬性),使用靜態類總是更好嗎?

我會說,是的。 當聲明某些static你聲明了無狀態執行的意圖 (它不是強制性的,而是一種人們期望的意圖)

如果有相當多的靜態類(例如100個,每個都有許多靜態方法),與相同數量的實例類相比,這會對執行性能或內存消耗產生負面影響嗎?

不要這么認為,除非你確定靜態類真的無法進行,否則會導致很容易搞亂內存分配並導致內存泄漏。

當[this]關鍵字用於調用同一實例類中的另一個方法時,實例解析是否仍然存在?

不確定,關於一點(這是CLR的純粹實現細節),但請想一想。

靜態方法更快但是OOP更少,如果你將使用設計模式靜態方法可能是壞代碼,更好地編寫業務邏輯而不需要靜態,常見的函數如文件讀取,WebRequest等更好地實現靜態...你的問題沒有普遍性回答

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM