130

私の質問は、静的メソッドとインスタンス メソッドのパフォーマンス特性とそのスケーラビリティに関するものです。このシナリオでは、すべてのクラス定義が 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.DoOperation2("abc")内からのように [this] キーワードを使用します。DoOperation1

4

3 に答える 3

175

理論的には、静的メソッドはインスタンスメソッドよりもわずかにパフォーマンスが優れているはずですが、他のすべての条件は同じです。これは、追加の非表示thisパラメーターがあるためです。

実際には、これはほとんど違いがないため、さまざまなコンパイラーの決定のノイズに隠されます。(したがって、2人が一方を他方よりも「証明」して、結果が一致しない可能性があります)。特に、thisは通常レジスタに渡され、そもそもそのレジスタにあることが多いためです。

この最後の点は、理論的には、オブジェクトをパラメーターとして受け取り、それを使用して何かを実行する静的メソッドが、同じオブジェクトのインスタンスとしての同等のものよりもわずかに劣ることを期待する必要があることを意味します。繰り返しになりますが、違いはごくわずかであるため、それを測定しようとすると、おそらく他のコンパイラーの決定を測定することになります。(特に、その参照が常にレジスターにある可能性が非常に高いため)。

実際のパフォーマンスの違いは、自然に静的である必要があることを行うためにオブジェクトをメモリ内に人工的に持っているか、または自然にインスタンスである必要があることを行うために複雑な方法でオブジェクトの受け渡しのチェーンを絡ませているかどうかにあります。

したがって、番号1の場合、状態を維持することが問題にならない場合は、静的であることが常に適切です。これは、静的であるためです。コンパイラの最適化をうまく処理するという全体的なルールはありますが、パフォーマンスの問題ではありません。奇妙な使用法よりも、通常の使用法で発生するケースを最適化する努力をした可能性が高くなります。

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

項目3についてthisも同様thisです。ただし、注意:

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

  2. thisnullでないことは明らかなので、場合によってはこれを使用して呼び出しを最適化することができます。

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

  4. そうは言っても、ヌルチェックは安いです!

インスタンスメソッドではなく、オブジェクトに作用するジェネリック静的メソッドが、http://joeduffyblog.com/2011/10/23/on-generics-and-some-of-で説明されているコストの一部を削減できることは注目に値します。 the-associated-overheads/指定された静的が指定されたタイプに対して呼び出されない場合。彼が述べているように、「余談ですが、拡張メソッドは、一般的な抽象化をより有料にするための優れた方法であることがわかりました。」

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

概要:

  1. ほとんどの場合、インスタンスと静的のパフォーマンスコストはごくわずかです。
  2. たとえば、静的なものを悪用したり、その逆を行ったりすると、一般的にどのようなコストが発生します。静的とインスタンスの間の決定の一部にしないと、正しい結果が得られる可能性が高くなります。
  3. 別のタイプの静的ジェネリックメソッドでは、インスタンスジェネリックメソッドよりも作成されるタイプが少なくなることがまれにあります。これにより、めったに使用されないようにすることで、わずかなメリットが得られる場合があります(「まれに」とは、アプリケーションの存続期間。呼び出される頻度ではありません)。彼がその記事で話していることを理解すると、とにかくほとんどの静的対インスタンスの決定とは100%無関係であることがわかります。編集:そして、それはほとんどの場合、jittedコードではなく、ngenでのみそのコストがかかります。

編集:ヌルチェックがどれほど安いかについてのメモ(私が上で主張した)。.NETのほとんどのnullチェックは、nullをまったくチェックしません。むしろ、nullが機能することを前提として実行を継続し、アクセス例外が発生すると、nullに変換されますNullReferenceException。そのため、ほとんどの場合、C#コードがインスタンスメンバーにアクセスしているためにnullチェックが含まれる場合、成功した場合のコストは実際にはゼロです。例外は、いくつかのインライン呼び出しであり(インスタンスメンバーを呼び出したかのように動作したいため)、フィールドにヒットして同じ動作をトリガーするだけなので、非常に安価であり、とにかく省略されることがよくあります。 (たとえば、メソッドの最初のステップでフィールドにアクセスする必要がある場合)。

于 2012-09-05T10:56:03.060 に答える
12

状態を保持する必要がない場合 (フィールドやプロパティは必要ありません)、常に静的クラスを使用する方が良いですか?

はい、そうです。何かstaticを宣言すると、ステートレス実行の意図が宣言されます (必須ではありませんが、期待される意図です)。

これらの静的クラスがかなりの数 (たとえば、それぞれに多数の静的メソッドがある 100 など) ある場合、同じ数のインスタンス クラスと比較して、実行パフォーマンスまたはメモリ消費に悪影響を及ぼしますか?

静的クラスが本当にstetless であると確信していない限り、そうは思わないでください。そうでない場合は、メモリ割り当てを簡単に台無しにして、メモリ リークが発生する可能性があります。

[this] キーワードを使用して同じインスタンス クラス内の別のメソッドを呼び出す場合、インスタンスの解決は引き続き行われますか?

この点についてはわかりませんが (これは純粋に CLR の実装の詳細です)、そう考えてください。

于 2012-09-05T10:37:43.543 に答える
-1

静的メソッドは高速ですが、OOP は少なくなります。デザイン パターンを使用する場合、静的メソッドは不適切なコードである可能性があります。ビジネス ロジックは非静的として記述した方が適切です。ファイルの読み取り、WebRequest などの一般的な機能は、静的として優れています。あなたの質問には普遍的な答えはありません。

于 2012-09-05T10:40:23.973 に答える