0

ジェネリック インスタンスごとに非ジェネリック型を生成するようにコンパイラに指示した場合、アセンブリを書き換えているときに、アプリケーションのコードが大きくなるだけで、パフォーマンスは同じになるでしょうか?

4

5 に答える 5

2

コンパイル済みコードのサイズを JIT の前または後に変更すると、パフォーマンスに影響を与える可能性があります。

たとえば、実行可能コードの量を増やすと、余分なキャッシュ ミスが発生したり、より多くの仮想メモリを使用したりする可能性があります。どちらの場合も、プログラムの実行が遅くなる可能性があります。

また、アセンブリに存在する名前付き型の数を増やすと、ランタイムが遅くなる可能性があります。型名を解決するためにランタイムがより大きなデータ構造を調べる必要がある場合、型名の解決と JIT コンパイルの実行に時間がかかることがあります。

最後に、それらの型が JIT に対してより多くの型である場合、CLR はコードの生成に多くの時間を費やすことになる可能性があります。

確実にするためにテストを実行する必要がありますが、私の推測では、あなたが話していることを行うと、正味のマイナス効果があると思います.

ただし、CLR は、それが生成する汎用コードに関して非常に優れています。ジェネリック メソッドのさまざまな参照型の設定は、型トークンの読み込みが必要な部分を除いて、同じネイティブ メソッド本体のほとんどを使用することになります。ただし、値型のインスタンス化は、独自の固有のメソッド本体を取得することになります。

これにより、通常は良好なパフォーマンスが得られます。これにより、コードの肥大化によるパフォーマンスへの影響と、余分なボクシングによるパフォーマンスへの影響のバランスが取れます。

CLR 設計が最適でないパフォーマンスにつながるワークロードを構築することは確かに可能です。しかし、これらのケースは私にはかなり病的であるように思えます。ほとんどの実際のコードでは、CLR ジェネリックを直接使用するだけでパフォーマンスが向上すると確信しています。

于 2009-11-05T06:57:52.143 に答える
1

いいえ、コードとパフォーマンスは実質的に同じです。

コンパイラはすでに特定のクラスを生成しています。言語コンパイラーと JIT コンパイラーがどの程度の作業を行っているかはわかりませんが、最終的な結果は実質的に同じになります。

于 2009-10-08T19:45:34.027 に答える
0

質問は理にかなっています。

保証されている唯一の利点は、ランタイムによるメタデータまたは解析の減少、そして明らかにキーボード入力の減少と DRY の増加です。しかし、このケースは、廃止された C++ コンパイラの場合と非常によく似ており、Bjarne が何年にもわたって不満を述べてきたことです。ポインターのコンテナーなどの膨張を生成する必要はまったくありません..

いずれにせよ、C# ジェネリックは言語とランタイムの機能が非常に貧弱であり、多くの頭痛の種を引き起こす可能性があり、インターフェイスがないとほとんど役に立たない.翻訳単位全体での使用 (typedef なし) など。

于 2009-10-08T21:34:31.423 に答える
0

ジェネリックは、メソッド本体で発生するキャストとオートボクシング (それぞれ参照型と値型の場合) 操作の数を減らすことで、ある程度のパフォーマンスを得ることができます。

ジェネリックに関する MSDN の記事

JIT が特定のユース ケースの生成を処理し、それらを積極的にキャッシュするため、「ジェネリックのない」メソッドの実装ではパフォーマンスが向上することはありません。

于 2009-10-08T19:47:57.063 に答える
0

ジェネリックは、非ジェネリックの同等物よりもパフォーマンスと実行時メモリの利点を提供します。たとえば、以下を比較してください。

ArrayList arrayList = new ArrayList(new Byte[] { 1, 2, 3, 4, 5, 6, 7, 8} );

List<Byte> byteList = new List<Byte> { 1, 2, 3, 4, 5, 6, 7, 8 };

ArrayList には、各要素がバイトを指す object[] の内部ストレージが含まれます。したがって、32 ビット ポインターを持つリストのこの部分の理想的なメモリは、8 * 4 + 8 = 40 バイトです。ボックス化されたバイトには追加のオーバーヘッドがあるため、実際にはさらに悪いため、理想的と言いましたが、正確な量はわかりません.

List 実装には代わりに byte[] が含まれます。これは、配列への 1 つのポインターと 8 バイトだけを必要とし、ボクシングのオーバーヘッドなしで合計 12 バイトのメモリを必要とします。

メモリの違いに加えて、値のボックス化/ボックス化解除のパフォーマンス コストもあります。

参照型の場合はその差は小さくなりますが、非ジェネリック型からデータを取り出すときに絶えずキャストするとコストがかかります。

これらの違いは現実のものですが、ほとんどのアプリケーションに計り知れない影響を与えます。ジェネリックの真の利点は、コンパイル時の検証の信頼性が高くなり、型付きの値を使用することでコードが単純になることです。

私の意見では、適切かつ可能な限りジェネリックを使用するのが最善です。

サム

于 2009-10-08T19:50:48.430 に答える