54

メモリと時間の観点から、メソッドを静的にした方が良いですか?

4

7 に答える 7

104

通常はそうです、「this」参照を渡す必要はありません。その参照はECXレジスタに渡されるため、追加のスタックスペースは必要ありません。同じクラスのインスタンスメソッドから呼び出しを行う場合、レジスタはすでに設定されているため、節約はまったくありません。ただし、メソッドが別のクラスにある場合、x86 CPUコアへのプレッシャーを軽減するのに役立ちます。つまり、x86には多くのレジスタがありません。測定可能なパフォーマンスの向上が見られることは非常にまれです。

私は、インスタンスメンバーを静的として使用しないクラスのメソッドを宗教的にマークします。staticキーワードによって提供される固有のコントラクトを評価します:「このメソッドはオブジェクトの状態を変更しません」。

于 2010-01-26T19:44:42.443 に答える
58

メソッドが含まれているクラスからの状態情報を必要としない場合は、メソッドを静的にする必要があります。

ポリモーフィズムを気にしない場合は、クラスインスタンスメンバーを取得して引数としてメソッドに渡すかどうかを決定するだけで、インスタンスまたは静的のいずれかとして任意のメソッドを記述できます。考慮すべきことは、構文が自然であるかどうか、コードが理解しやすく意味があるかどうかなどです。

インスタンスと静的メソッドのパフォーマンスのオーバーヘッドはごくわずかであるため、このレベルでの最適化について心配する必要はありません。はい、タイプのディスパッチテーブルで使用されるスペースがあります(メソッドが仮想の場合)-しかし、それは小さな一定のオーバーヘッドです。はい、インスタンスメソッドと静的メソッドの呼び出しには小さなオーバーヘッドもありますが、これも小さなオーバーヘッドです。

これは、マイクロ最適化のレベルのように思われます。実際にプログラムのパフォーマンスに影響を与えていると信じる測定可能で具体的な証拠がない限り、避ける必要があります。実際、間違ったことをするthisと、タイプの非表示の参照を介してアクセスするのではなく、追加のパラメーターを渡す(スタックにコピーするなど)コストがかかると、パフォーマンスが低下する可能性があります。

メソッドのセマンティクスを分析し、それに基づいて静的/インスタンスの決定を行う方が適切です。

于 2010-01-26T19:45:50.510 に答える
10

とにかくインスタンスを渡す場合(SomeStaticMethod(obj, "abc", 123);)、実際にはそうではありません。ポリモーフィズムのないシナリオでのみ静的メソッドを有効に使用できます。そのような場合、プロパティなどの単純なものはとにかくインライン化されている可能性が高くなります。

オブジェクトを「自然に」使用します(obj.SomeMethod("abc",123);)-コードをシンプルに保ち、パフォーマンスの問題を見つけるためにプロファイルを作成します-非常タイトなループを実行していない限り、インスタンスと静的の違いが生じる可能性はほとんどありません。それが問題になるかもしれないいくつかのシナリオがありますが、それらはかなり専門的です。

于 2010-01-26T19:45:17.107 に答える
7

静的メソッドと非仮想インスタンス メソッドの違いはほとんどありません。後者は、thisprointer/reference を「隠し」引数として持っているだけです。生成されたマシン コードでは、両方の種類の呼び出しが非常によく似ています。

オブジェクトに依存/変更しない場合、メソッドは静的である必要があります。

一方、仮想メソッド (オーバーライド可能) では、呼び出し元がいわゆるvtableで正確な実装を検索する必要があります。コンパイラが非常に小さなメソッドをインライン化するのを防ぐだけでなく (単純なプロパティ アクセサーは頻繁にインライン化されます)、ルックアップに数サイクルかかります。

それでも、仮想メソッドは、C#/CLR で利用できる最も高速な種類の動的ディスパッチです。デリゲートやリフレクションよりもはるかに高速です。

于 2010-01-26T21:24:17.057 に答える
4

この種の質問はたくさんあります。静的メソッドは高速/低速ですか?仮想関数は高速/低速ですか?i++は++iより速い/遅いですか?for(;;)はwhile(true)よりも速い/遅いですか?

いくつかのソフトウェアを入手して調整することは価値があります。これにより、実際にソフトウェアのパフォーマンスに実際に影響を与える種類のことをよく理解できます。

次に、そのような質問への答えは(ほとんどの場合)それが重要ではないことがわかります。

一般化できれば、私の経験では、ソフトウェアを遅くするのは、無害に見えるが、その時間の消費が想像よりも桁違いに大きくなる可能性があるコード行の使用です。それらは無実に見えるため、コードを見ても確実に見つけることはできません。例:大きなデータ構造が存在することを確認するために、それらのデータ構造の割り当て、初期化、および割り当て解除を繰り返します。する必要のない文字列を国際化する。プロパティの単純な設定を、大規模なデータ構造全体でのメソッド呼び出しの大規模なカスケードに変えることができる通知スタイルのプログラミング。nが大きくなることを除いて問題になることのない単純なO(n ^ 2)操作。(a <b)は、aとbがintであろうと大きなクラスであろうと、ほぼ同じ時間かかると考えます。この「無邪気に見えることによる時間の掛け算」

于 2010-01-26T20:51:06.797 に答える
2

ほとんどの場合、違いは無視できますが、静的の方が効率的です。

静的メソッド呼び出しでは、次の手順が回避されます。

  1. オブジェクト参照 (this) が null でないことを確認しています。
  2. 仮想ディスパッチ テーブルで正しいメソッドを見つける。
  3. オブジェクト参照をスタックに配置します。
于 2010-01-26T19:49:40.120 に答える
0

特定のクラス内で作成する多くのユーティリティメソッドは、クラス内の少数のデータメンバーのみを必要とするか、まったく必要ないことがわかりました。このような場合、私はこれらのメソッドを(スタンドアロンの)静的メソッドとして記述し、必要ないくつかのデータ項目を直接渡す傾向があります。

それらが特に一般的で、他のクラスにとって十分に役立つ場合は、それらを公開することもできます。

于 2010-01-26T20:25:06.297 に答える