9

大量のユーザーデータをメモリに保持するアプリを作成していますが、ほとんどの場合、すべてを List<T> 構造 (およびルックアップが必要な場合は一部の Dictionary<T,T>) に保持しています。

そして、私は疑問に思っています...

リストはどのくらい効率的ですか? それぞれのメモリ オーバーヘッドはどれくらいですか? (つまり、それらに含まれるオブジェクトに加えて、メモリ スペースが必要です) 新しいオブジェクトをインスタンス化するたびに、どのくらいのペナルティを支払う必要がありますか?

より効率的な方法はありますか?

辞書は単なるハッシュテーブルですよね? それとも、効率の悪いデータ構造ですか?

配列を使用したいのですが、常に配列に追加したり削除したりするという典型的な問題があるため、それらを拡大/縮小するのは面倒です。

アイデア/提案はありますか?


編集: 基本的なデータ構造 101 と、追加/削除にはリンク リストの方が優れており、ランダム アクセスには HashTable の方が優れている理由を知っています。

私は主に.Netの特異性について心配しています。たとえば、これらの構造のそれぞれがどれだけのメモリを浪費するか。そして、それらの初期化/強制終了に時間が費やされました。

たとえば、リストのインスタンス化/GC に時間がかかるが、クリアするのにそれほど時間がかからない場合は、リストの小さなプールを待機させておき、それらをクリアしてプールに送り返す必要があるかもしれません。単に逆参照するのではなく、完了したら。

または、Hashtables の方がアクセスは高速ですが、多くのメモリを浪費する場合は、Lists を使用して、項目数が少ない場合はリストをトラバースすることをお勧めします。

また、私のアプリは非常にメモリを集中的に使用するため (memcached のように考えてください)、メモリ使用量にも注目したいと思います...そのような情報をどこで見つけることができるか知っている人はいますか?

4

10 に答える 10

4

メモリに保持する必要があるデータが大量にある場合は、ある種のインメモリ データベースの使用を検討する必要があります。

于 2008-08-28T21:14:49.630 に答える
2

リストはその下の配列であるため、アイテムを追加することによるパフォーマンスへの影響は、最後にない限り、非常にコストがかかります。

それ以外の場合は、基本的に配列と同じくらい高速になります。

于 2008-08-28T21:08:51.907 に答える
2

List は内部的に配列を使用し、Dictionary はハッシュ テーブルを使用します。

これらは、古い非ジェネリック クラス ArrayList および HashTable よりも高速です。オブジェクトとの間ですべてを変換するコスト (ボックス化、ボックス化解除、および型チェック) がなく、MS が古いクラスよりも優れた最適化を行っているためです。

于 2008-08-28T21:14:11.863 に答える
2

リスト内のランダムな場所に効率的に挿入または削除する必要がある場合は、LinkedList データ構造があります。詳細については、MSDN の記事を参照してください。リンクされたリストのランダムアクセスであることは明らかに効率的ではありません。

于 2008-08-28T21:18:20.810 に答える
2

List<> と Dictionary<,> がどのように実装されているかの詳細をすべて確認したい場合は、非常に便利な.NET Reflectorを使用してください。

優れたC5 Generic Collection Libraryのドキュメントも参照してください。これには、BCL にない多くのコレクション タイプの非常に優れた実装があります。

于 2008-08-31T02:42:20.267 に答える
2

LinkedList オブジェクトは、リンクされたリストの性質により、追加および削除にかかる時間が短くなります。要素を追加するとき、通常のリストのように配列のサイズを変更する必要はありません。その改善を除けば、LinkedList は通常の List とほぼ同じように機能すると思います。

ウィキペディアでこれを参照してください: Linked Lists vs. Arrays

于 2008-08-28T21:29:49.017 に答える
1

メモリの使用量が気になる場合は、アレイをディスクに保存し、その時点で必要な部分だけをメモリにマップすることが重要です。

重要なのは、FILE_FLAG_NO_BUFFERING を使用し、常に正確に 1 セクター分のデータを読み書きすることです。

于 2008-08-28T21:39:56.047 に答える
1

2 プロセスというのはやり過ぎかもしれません。さらに、プロセス間通信が多少遅くなる可能性があります (ただし、私はそのようなことを試したことがないので、私の意見は塩の粒として考えてください)。私は、各データ ユニットが小さいデータ ドリブン アプリケーションに取り組んでいますが、常に 10 億以上のデータ ユニットが存在する可能性があります。私たちが使用する方法は基本的に次のとおりです。

  • 何があっても、すべてがディスク上にある
  • データは「チャンク」にブロックされます。各チャンクは最後にいつアクセスされたかを知っています
  • チャンクは、必要なときにディスクからメモリにドラッグされます
  • 優先度の低いスレッドがメモリ使用量を監視し、最近使用されていないものを削除します

言い換えれば、これは自作のキャッシング方式です。利点は、メモリ内のデータを正確に制御できることですが、OS のページング スキームに依存している場合は制御できません。よく使用される変数がページ上のデータと混ざってしまうと、そのページは繰り返しヒットし、ディスクに移動できなくなります。一部のデータ要求が他のデータ要求よりも長くかかるようにアプリケーションを設計する場合、これは非常にうまく機能します。特に、必要なチャンクが事前にわかっている場合は特にそうです (わかりません)。

.NET アプリのすべてが 2 GB のメモリ内に収まる必要があることに注意してください。GC の動作方法とアプリのオーバーヘッドのために、実際にはそれよりもいくらか少ない量しか使用できません。

ヒープがどのように見えるか、誰が割り当てているかを正確に調べるには、CLR プロファイラーを使用します

于 2008-08-28T22:18:58.400 に答える
0

パフォーマンスの問題が発生し、プロファイラーが問題があることを示すまで、指を動かしませんでした。そうすれば、解決すべき決定的な問題が発生し、はるかに簡単になります。

于 2009-06-03T05:55:37.680 に答える
0

.Net List はリンク リストを使用しません。これは配列で、デフォルトでは 4 つの位置から始まり、追加するとサイズが 2 倍になると思います。そのため、使用方法によってパフォーマンスが多少異なる場合があります。


VS 2008 を使用している場合は、このネズミの穴に深く入り込む前にプロファイラーを実行してください。どこで時間を失っているかを実際に調べ始めたとき、リンクされたリストの細かい点について議論することは実際には問題ではないことを理解するのにそれほど時間はかかりませんでした。

于 2008-08-28T21:46:07.777 に答える