38

XNA を調べていたところ、XNA 内のVector3クラスがプロパティではなくパブリック フィールドを使用していることがわかりました。簡単なベンチマークを試してみたところ、structその違いは非常に劇的であることがわかりました (2 つのベクトルを 1 億回追加すると、プロパティで 2.0 秒、フィールドで 1.4 秒かかりました)。参照型の場合、違いはそれほど大きくないように見えますが、そこにあります。

では、それはなぜでしょうか。プロパティがメソッドにコンパイルされ、メソッド呼び出しのオーバーヘッドが発生することはわかっていget_Xますset_X。しかし、これらの単純な getter/setterは常にJIT によってインライン化されませんか? JIT が決定したことを保証できないことは承知していますが、確かにこれは確率のリストでかなり高いですか? マシン レベルでパブリック フィールドをプロパティから分離するものは他にあるでしょうか?

そして、私が疑問に思っていることの 1 つは、自動実装されたプロパティ ( public int Foo { get; set; }) が public フィールドよりも「優れた」OO 設計である理由は何ですか? または、より適切に言えば、これら 2 つの違いは何ですか? リフレクションを使用するとプロパティにする方が簡単であることは知っていますが、他に何かありますか? 両方の質問に対する答えは同じだと思います。

ところで:私は.NET 3.5 SP1を使用しています.NET 3.5 SP1は、構造体を含むメソッド(または構造体のメソッド、よくわかりません)がインライン化されていない問題を修正したと信じています。少なくとも使用していると思います。確かにインストールされていますが、DX10.1を持っていないことを除いて、DX10.1が必要なSP1でVista 64ビットを使用しています..

また、ええ、私はリリースビルドを実行しています:)

編集:クイックアンサーに感謝しますが、プロパティアクセスがメソッド呼び出しであることは知っていますが、おそらくインラインメソッドが直接フィールドアクセスよりも遅い理由がわからないことを示しました

EDIT 2 :したがってstruct、明示的な GetX() メソッドを使用する別のメソッドを作成し(Javaの日々をまったく見逃さない方法)、インライン化を無効にしたかどうかに関係なく(を介して)同じように実行した[MethodImplAttribute(MethodImplOptions.NoInlining)]ため、結論:非静的メソッドは、構造体であってもインライン化されないようです。

JITが仮想メソッド呼び出しを最適化できる例外があると思いました。継承を認識していない構造体でこれが発生しないのはなぜですか。したがって、メソッド呼び出しは可能なメソッドを 1 つしか指すことができません。それとも、インターフェースを実装できるからですか?

パフォーマンスが重要な要素にプロパティを使用することについて本当に考えさせられるので、これはちょっと残念ですが、フィールドを使用すると汚く感じるので、自分が行っていることを C で記述したほうがよいでしょう。

EDIT 3 :まったく同じ件名に関するこの投稿を見つけました。彼の最終的な結論は、プロパティ呼び出しが最適化されてしまったということです。callvirtまた、IL にいるにもかかわらず、単純なゲッター/セッター プロパティがインライン化されることを何度も読んだと断言できます。それで私は気が狂うのですか?

EDIT 4 : Reed Copsey が以下のコメントに回答を投稿しました。

Re: Edit3 - 私の更新されたコメントを参照してください: これは x86 JIT と x64 JIT の問題だと思います。x64 の JIT はそれほど成熟していません。より多くの 64 ビット システムが毎日オンラインになるため、MS がこれを迅速に改善することを期待しています。– リード・コプシー

そして彼の答えに対する私の答え:

ありがとう、これが答えです!x86 ビルドを強制しようとしましたが、すべてのメソッドが同等に高速で、x64 よりもはるかに高速です。これは実際には非常に衝撃的です.64ビットOSで石器時代に住んでいたとは思いもしませんでした..あなたのコメントを回答に含めて、より目立つようにします. – ジュリアンR

みんな、ありがとう!

4

5 に答える 5

15

編集2:

ここで別の潜在的な考えがありました:

x64で実行していると述べました。この同じ問題を x86 でテストしたところ、自動プロパティとフィールドを使用したときに同じパフォーマンスが見られました。ただし、Connect およびメーリング リスト/フォーラムの投稿を見回すと、x64 CLR の JIT は別のコード ベースであり、x86 JIT とはパフォーマンス特性が大きく異なるという事実について、オンラインで多くの参照があります。私の推測では、これは x64 がまだ遅れをとっている場所の 1 つです。

また、参考までに、.net 3.5sp1 で修正された struct/method/etc は x86 側にあり、.net3.5sp1 より前の x86 では、パラメーターとして構造体を使用するメソッド呼び出しが決してインライン化されないという事実でした。これは、システムに関するこの議論とはほとんど関係ありません。


編集3:

別のこと: XNA がフィールドを使用する理由について。私は実際、彼らが XNA を発表した Game Fest にいました。Rico Mariani は、彼のブログにあるのと同じポイントの多くを取り上げた講演を行いました。XNA 関係者は、いくつかのコア オブジェクトを開発したときに、同様のアイデアを持っていたようです。見る:

http://blogs.msdn.com/ricom/archive/2006/09/07/745085.aspx

特に、ポイント 2 を確認してください。


自動プロパティがパブリック フィールドよりも優れている理由については、次のとおりです。

クラスの v2 での実装を変更し、必要に応じてプロパティの get/set ルーチンにロジックを追加できます。エンド ユーザーへのインターフェイスを変更する必要はありません。これは、ライブラリとコードを長期間維持する能力に大きな影響を与える可能性があります。

----元の投稿から-しかし、これが問題ではないことを発見--------

VS の外部でリリース ビルドを実行していましたか? これは、物事が最適化されていない理由の 1 つの説明になる可能性があります。多くの場合、VS で実行している場合、最適化されたリリース ビルドであっても、VS ホスト プロセスは JIT の多くの機能を無効にします。これにより、パフォーマンス ベンチマークが変化する可能性があります。

于 2009-03-11T00:26:57.337 に答える
5

Vance によるこの記事を読む必要があります。メソッドが JIT'er によって常にインライン展開されるとは限らない理由について詳しく説明します。

http://blogs.msdn.com/vancem/archive/2008/08/19/to-inline-or-not-to-inline-that-is-the-question.aspx

于 2009-03-11T00:27:56.523 に答える
3

XNA は XBox 360 をターゲットにする必要があり、.NET Compact Framework の JIT はデスクトップ版ほど洗練されていません。.NET CF JIT'er は、プロパティ メソッドをインライン化しません。

于 2009-03-11T00:30:36.067 に答える
3

フィールドへのアクセスは単なるメモリ参照ですが、プロパティの使用は実際にはメソッドの呼び出しであり、関数呼び出しのオーバーヘッドが含まれます。フィールドではなくプロパティを使用する理由は、コードを変更から隔離し、アクセスの粒度を向上させるためです。フィールドを直接公開しないことで、アクセス方法をより細かく制御できます。自動フィールドを使用すると、通常のゲッター/セッターの動作を得ることができますが、コードの他の部分に後で変更を伝達する必要なく、これを変更する機能が組み込まれています。

たとえば、フィールドへのアクセスが現在のユーザーのロールによって制御されるようにコードを変更するとします。フィールドを公に公開した場合、それにアクセスするコードのすべての部分に手を加える必要があります。プロパティを介して公開すると、プロパティ コードを変更して新しい要件を追加できますが、プロパティにアクセスするコードに不要な変更を加えることはありません

于 2009-03-11T00:31:25.017 に答える
3
  • パブリック フィールドは直接代入です
  • プロパティはメソッドであり、その後にコードが追加され、重要ではありませんが、さらに追加されます。
于 2009-03-11T00:25:32.317 に答える