38

さまざまなエンティティを表すデータクラスがいくつかあります。

ジェネリックとインターフェイスを使用してジェネリッククラスを作成する(たとえば、XMLを印刷または出力する)か、各データクラスを処理するために個別のクラスを作成するか。

パフォーマンス上の利点またはその他の利点はありますか(個別のクラスを作成する時間を節約する以外に)?

4

12 に答える 12

60

ジェネリックスを使用することには、パフォーマンス上の大きなメリットがあります。ボクシングとアンボクシングを廃止します。独自のクラスを開発する場合と比較すると、コイントスです(コインの片側がもう一方よりも重くなります)。フレームワークの作成者をしのぐことができると思う場合にのみ、自分でロールしてください。

于 2008-09-22T19:33:42.090 に答える
22

はいだけでなく、HECKYES。彼らがどれほど大きな違いを生むことができるか、私は信じていませんでした。ArrayListsとHashTablesを使用するコアコードのごく一部をジェネリックスに書き直した後、VistaDBでテストを行いました。250%以上は速度の向上でした。

ジェネリックと弱い型のコレクションで行ったテストについての私のブログを読んでください。結果は私たちの心を吹き飛ばしました。

弱い型のコレクションを使用していた多くの古いコードを強い型のコレクションに書き直し始めました。ADO.NETインターフェイスに関する私の最大の不満の1つは、データを出し入れするためのより強く型付けされた方法を公開していないことです。オブジェクトからのキャスト時間とその逆のキャスト時間は、大量のアプリケーションでは絶対的なキラーです。

強い型付けのもう1つの副作用は、コード内で弱い型付けされた参照の問題が頻繁に発生することです。GCに圧力をかけないように構造体を実装することで、コードをさらに高速化できることがわかりました。これを強く入力することと組み合わせて、最高の速度向上を実現します。

ドットネットランタイム内で弱い型のインターフェイスを使用しなければならない場合があります。可能な限り、強くタイプされたままでいる方法を探してください。それは、重要なアプリケーションのパフォーマンスに大きな違いをもたらします。

于 2008-09-23T03:16:02.633 に答える
15

C#のジェネリックは、CLRの観点からは真にジェネリック型です。ジェネリッククラスとまったく同じことを行う特定のクラスのパフォーマンスに根本的な違いがあってはなりません。これは、必要に応じて自動化された型キャストや、コンパイル時に拡張されるC++テンプレートであるJavaGenericsとは異なります。

これは、基本的な設計を説明する、やや古い良い論文 です。「。 NET共通言語ランタイムのジェネリックスの設計と実装」

特定のタスクのクラスを手書きする場合は、ジェネリック型のインターフェースを介して追加の迂回が必要になるいくつかの側面を最適化できます。

要約すると、パフォーマンス上の利点があるかもしれませんが、最初に一般的なソリューションをお勧めし、次に必要に応じて最適化します。これは、ジェネリックを多くの異なるタイプでインスタンス化することを期待している場合に特に当てはまります。

于 2008-09-22T19:46:45.833 に答える
8

別の質問に対して、ArrayListとGeneric Listの簡単なベンチマークを行いました。GenericsとArrayListsでは、マイレージは異なりますが、GenericListはArrayListより4.7倍高速でした。

そうです、あなたがたくさんの操作をしているなら、ボクシング/アンボクシングは重要です。単純なCRUDを実行している場合は、心配する必要はありません。

于 2008-09-22T19:39:01.500 に答える
6

ジェネリックスは、コードをパラメーター化し、繰り返しを回避する方法の1つです。プログラムの説明と、すべてのデータオブジェクトを処理するための個別のクラスを作成するという考えを見ると、ジェネリックに傾倒します。同じことを行う多くのクラスではなく、単一のクラスで多くのデータオブジェクトを処理することで、パフォーマンスが向上します。そしてもちろん、コードを変更する能力で測定されるパフォーマンスは、通常、コンピューターのパフォーマンスよりも重要です。:-)

于 2008-09-22T19:44:23.017 に答える
4

Microsoft によると、ジェネリックはキャスト (ボックス化/ボックス化解除プリミティブ) よりも高速です。これは trueです。彼らはまた、ジェネリックが参照型間のキャストよりも優れたパフォーマンスを提供すると主張していますが、これは真実ではないようです(誰もそれを完全に証明することはできません)。

Tony Northrup - MCTS 70-536: Application Development Foundation の共著者 - 同じ本で次のように述べています。

ジェネリックのパフォーマンス上の利点を再現できていません。ただし、Microsoft によると、ジェネリックはキャストを使用するよりも高速です。実際には、キャストはジェネリックを使用するよりも数倍高速であることが証明されました。ただし、アプリケーションのパフォーマンスの違いに気付くことはないでしょう。(100,000 回以上の反復を行った私のテストでは、ほんの数秒しかかかりませんでした。) したがって、ジェネリックはタイプ セーフであるため、引き続き使用する必要があります。

参照型間のキャストと比較して、ジェネリックを使用してそのようなパフォーマンス上の利点を再現することはできませんでした.

于 2008-09-22T20:17:04.700 に答える
3

たとえば、一般的なリストを使用するタイプの特定のリストと比較すると、違いは最小限に抑えられ、JITコンパイラの結果はほとんど同じになります。

ジェネリックリストをオブジェクトのリストと比較すると、ジェネリックリストには大きな利点があります。値型のボックス化/ボックス化解除や参照型の型チェックがありません。

また、.netライブラリのジェネリックコレクションクラスは大幅に最適化されており、自分で改善することはほとんどありません。

于 2008-09-22T19:40:15.257 に答える
3

ジェネリックの方が早い!

また、Tony Northrup が彼の本でジェネリックと非ジェネリックのパフォーマンスについて間違ったことを書いていることも発見しました。

これについてはブログに書きました: http://andriybuday.blogspot.com/2010/01/generics-performance-vs-non-generics.html

これは、著者がジェネリックと非ジェネリックのパフォーマンスを比較する素晴らしい記事です。

nayyeri.net/use-generics-to-improve-performance

于 2010-01-23T20:38:41.720 に答える
2

あるインターフェースのメソッドを呼び出してその作業を行うジェネリッククラスを考えている場合、インターフェースメソッドの呼び出しは(非仮想)関数呼び出しよりも遅いため、既知の型を使用する特定のクラスよりも遅くなります。

もちろん、コードがパフォーマンスが重要なプロセスの遅い部分でない限り、明確さを重視する必要があります。

于 2008-09-22T19:44:10.630 に答える
2

MSDN の Rico Mariani のブログも参照してください。

http://blogs.msdn.com/ricom/archive/2005/08/26/456879.aspx

Q1: どちらが速いですか?

Generics バージョンはかなり高速です。以下を参照してください。

記事は少し古いですが、詳細を説明します。

于 2008-09-23T22:54:18.153 に答える
2

ジェネリック コレクションとボクシングなどの場合、ArrayList のような古いコレクションでは、ジェネリックの方がパフォーマンスに優れています。しかし、ほとんどの場合、これはジェネリックの最も重要な利点ではありません。私は、次の 2 つの点がより大きな利点であると考えています。

  1. タイプセーフティ。
  2. 自己文書化別名より読みやすい。

ジェネリックは型の安全性を促進し、より均一なコレクションを強制します。int を期待しているときに、文字列に出くわすことを想像してみてください。ああ。

ジェネリック コレクションは、自己文書化にも優れています。以下の 2 つのコレクションを考えてみましょう。

ArrayList listOfNames = new ArrayList();
List<NameType> listOfNames = new List<NameType>();

最初の行を読むと、listOfNames は文字列のリストだと思うかもしれません。違う!実際には NameType 型のオブジェクトを格納しています。2 番目の例は、型が NameType (または子孫) でなければならないことを強制するだけでなく、コードがより読みやすくなります。コードを見ただけで TypeName を見つけてその使用方法を学ぶ必要があることがすぐにわかります。

StackOverflow で、「x は y よりもパフォーマンスが高いか」という質問をたくさん見てきました。ここでの質問は非常に公正であり、猫の皮を剥ぐ方法でジェネリックが勝つことが判明した. しかし、最終的に重要なのは、ユーザーに何か役立つものを提供することです。もちろん、アプリケーションは実行できる必要がありますが、クラッシュしないことも必要であり、バグや機能のリクエストに迅速に対応できる必要があります。これらの最後の 2 つのポイントが、ジェネリック コレクションの型の安全性とコードの読みやすさとどのように結びついているかがわかると思います。逆の場合、つまり ArrayList が List<> より優れていたとしても、パフォーマンスの差が大きくない限り、おそらく List<> の実装を採用するでしょう。

パフォーマンスに関する限り(一般的に)、あなたのキャリアの過程で、これらの分野でパフォーマンスのボトルネックの大部分が見つかると確信しています。

  1. データベースまたはデータベース クエリの設計が不十分 (インデックス作成などを含む)、
  2. 貧弱なメモリ管理 (dispose を呼び出すのを忘れる、深いスタック、オブジェクトを保持しすぎるなど)、
  3. 不適切なスレッド管理 (スレッドが多すぎる、デスクトップ アプリのバックグラウンド スレッドで IO を呼び出さないなど)、
  4. 貧弱な IO 設計。

これらはどれも、単一行のソリューションでは修正されません。私たちプログラマー、エンジニア、およびギークは、すべてのクールで小さなパフォーマンス トリックを知りたいと思っています。しかし、ボールから目を離さないことが重要です。上記の 4 つの領域で優れた設計とプログラミングの実践に焦点を当てることで、わずかなパフォーマンスの向上を心配するよりもはるかに多くのことを引き起こすと私は信じています。

于 2008-09-22T23:00:43.403 に答える
0

ボックス化をなくすことができるだけでなく、基になる実装の変更により、ジェネリック実装は参照型を持つ非ジェネリック対応のものよりもいくらか高速です。

オリジナルは、特定の拡張モデルを念頭に置いて設計されました。このモデルは実際に使用されることはありませんでした (とにかく悪い考えでした) が、設計上の決定により、いくつかのメソッドが仮想化され、したがってインライン化できなくなりました (この点に関する現在および過去の JIT 最適化に基づく)。

この決定は新しいクラスで修正されましたが、古いクラスでは変更できません。これは、潜在的なバイナリ互換性を破る変更になります。

さらに、(IList<> ではなく) List<> での foreach による反復は、ArrayList の Enumerator がヒープ割り当てを必要とするため、より高速です。確かに、これはあいまいなバグにつながりました

于 2009-01-27T00:54:46.423 に答える