1. ホーム
  2. c#

[解決済み] 静的メソッドとインスタンスメソッドの性能比較

2022-07-14 08:34:22

質問

私の質問は、静的メソッドとインスタンスメソッドのパフォーマンス特性およびそれらのスケーラビリティに関連しています。このシナリオでは、すべてのクラス定義が 1 つのアセンブリにあり、複数の個別のポインター タイプが必要であると仮定します。

を考慮します。

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. 同じインスタンスクラス内の別のメソッドが呼び出されたとき、インスタンスの解決はまだ行われますか?例えば、[this]キーワードを使用して this.DoOperation2("abc") の中から DoOperation1 の中で、同じインスタンスの

どのように解決するのですか?

理論的には、静的メソッドはインスタンスメソッドよりも若干パフォーマンスが良くなるはずです(他のすべての条件が同じ場合)。 this パラメータがあるためです。

実際には、これは非常に小さな違いであり、さまざまなコンパイラの決定のノイズに隠れるでしょう。(したがって、2 人の人が不一致の結果で 1 つが他より優れていることを "prove" することができます)。特に this は通常レジスタで渡され、そもそもそのレジスタにあることが多いからです。

この最後のポイントは、理論的には、オブジェクトをパラメータとして取り、それを使って何かを行う静的メソッドは、その同じオブジェクトのインスタンスとして同等のものよりもわずかに劣ることを期待すべきであることを意味します。しかし、この差は非常に小さいので、測定しようとすると、おそらく他のコンパイラの決定を測定することになるでしょう。(特に、その参照がずっとレジスタにある可能性は非常に高いので)。

本当のパフォーマンスの違いは、自然に静的であるべきことを行うために人為的にメモリ内にオブジェクトを持つか、自然にインスタンスであるべきことを行うために複雑な方法でオブジェクト渡しのチェーンを絡めているかどうかに帰着します。

というわけで、その1。状態を維持することが問題でない場合、常に静的である方が良いのです。 なぜならそのために静的があるのだから . コンパイラの最適化でうまくやるという全体的なルールはありますが、パフォーマンスの懸念ではありません。

2 番。違いはありません。メタデータの量、実際の DLL または EXE ファイルに含まれるコードの量、および結合されたコードの量の両方について、各メンバーに一定のクラスごとのコストがあります。これは、インスタンスであるか静的であるかにかかわらず同じです。

項目 3 で thisthis と同じです。しかし、注意してください。

  1. this パラメータは特定のレジスタで渡されます。同じクラス内のインスタンスメソッドを呼び出すときは、おそらくすでにそのレジスタにあるため (何らかの理由でレジスタが使用された場合を除く)、 パラメータを設定するためのアクションは必要ありません。 this を設定するためのアクションは必要ありません。これは、たとえば、メソッドへの最初の 2 つのパラメーターが、メソッドが行う呼び出しの最初の 2 つのパラメーターである場合にもある程度当てはまります。

  2. というのは明らかでしょうから this がヌルでないことは明らかなので、これは場合によっては呼び出しを最適化するために使われるかもしれません。

  3. というのは明らかでしょうから this が null でないことは明らかなので、メソッド呼び出しを偽装するために生成されたコードがとにかく必要かもしれないいくつかの null チェックを省略できるので、これはインラインのメソッド呼び出しを再びより効率的にする可能性があります。

  4. とはいえ、ヌルチェックは安い!

インスタンスメソッドではなく、オブジェクトに作用する一般的な静的メソッドは、で説明したコストのいくつかを削減できることは注目に値します。 http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-the-associated-overheads/ で議論されているいくつかのコストを削減することができます。彼が言うように、余談ですが、拡張メソッドは汎用抽象化をよりペイ フォア プレイにする素晴らしい方法であることがわかりました。

しかし、これはメソッドによって使用される他の型のインスタンス化にのみ関係し、他の方法では存在しないことに注意してください。そのため、多くの場合 (その型を使用する他のインスタンス メソッド、その型を使用するどこか他のコード) には適用されません。

要約です。

Visual Studio 2012 で MSI またはセットアッププロジェクトを作成する