1

環境: Windows 8 64 ビット、Windows 2008 サーバー 64 ビット Visual Studio (プロフェッショナル) 2012 64 ビット

リストL; //私のプログラムには何千もの大きな CMyObject がキャッシュされており、これは Windows サービス プログラムのさまざまなスレッドによって共有されています。

当社の SaaS ミドルウェア製品では、何千もの大きな C++ オブジェクト (読み取り専用の const オブジェクト、それぞれのサイズは約 4MB) をメモリにキャッシュし、システムのメモリを使い果たします。ディスク ファイル (または OS が管理するその他の永続的なメカニズム) を C++ オブジェクトに関連付けることはできますか? 共有/プロセス間通信の必要はありません。

ディスク ファイルは、プロセス (Windows サービス プログラム) の実行中に機能する場合は十分です。読み取り専用の const C++ オブジェクトは、同じ Windows サービス内の異なるスレッドによって共有されます。

オブジェクト データベース (mongoDB など) を使用してオブジェクトを格納することも検討していました。オブジェクトは、使用するたびにロード/アンロードされます。シリアル化されたファイルを読み取るよりも高速ですが (うまくいけば)、パフォーマンスは低下します。

目的は、パフォーマンス上の理由から C++ オブジェクトのキャッシュを保持し、シリアル化された C++ オブジェクトを毎回ロード/アンロードする必要がないようにすることです。このディスク ファイルが OS で管理され、コードの微調整が最小限で済むようになれば素晴らしいと思います。

ご回答ありがとうございます。

4

3 に答える 3

0

したがって、何千もの巨大なオブジェクトには、コンストラクタ、デストラクタ、仮想関数、およびポインタがありますこれは、それらを簡単にページアウトできないことを意味します。ただし、OS が代わりに行うことができるため、最も実用的なアプローチは、物理メモリ (場合によっては SSD スワップ ボリューム) を追加し、その 64 ビット アドレス空間を使用することです。(あなたのOSで実際にどれだけアドレス指定できるかはわかりませんが、おそらく4Gのオブジェクトに収まるのに十分です)。

2 番目のオプションは、メモリを節約する方法を見つけることです。これは、特殊なアロケーターを使用してスラックを減らしたり、間接的なレイヤーを削除したりする可能性があります。これについて具体的な提案を行うには、データに関する十分な情報が提供されていません。

3 番目のオプションは、プログラムをメモリに収めることができると仮定して、逆シリアル化を高速化することです。より効率的に解析できる形式に変更できますか? どうにかしてオブジェクトをオンデマンドですばやくデシリアライズできますか?

最後のオプションであり、最も手間がかかるのは、スワップファイルを手動で管理することです。大規模なポリモーフィック クラスを 2 つに分割することは、最初のステップとして賢明です。ポリモーフィック フライウェイト (具体的なサブタイプごとに 1 つのインスタンス) と、平坦化された集約コンテキスト構造です。この集合体は、アドレス空間から安全にスワップ インおよびスワップ アウトできる部分です。

ここで必要なのは、メモリ マップされたページング メカニズム、現在マップされているページを追跡するある種のキャッシュ、おそらく未加工のポインターをオンデマンドでデータをマップできるページ + オフセットに置き換えるスマート ポインターなどです。より詳細な提案を行うには、データ構造とアクセス パターンに関する十分な情報が提供されていません。

于 2013-07-24T07:44:07.503 に答える
0

もちろん、解決策の 1 つは、すべてのオブジェクトを単純にロードし、必要に応じて OS にディスクから/へのスワップを処理させることです。(または、動的にロードしますが、オブジェクトが完全に破棄されない限り破棄しないでください)。このアプローチは、他のオブジェクトよりも頻繁に使用されるオブジェクトが多数ある場合にうまく機能します。そして、スワップスペースからのロードは、あなたが書くことができるものよりもほぼ確実に高速です。これに対する例外は、どのオブジェクトが次に使用される可能性が高いか、または低いかを事前に知っていて、メモリ不足の場合に適切なオブジェクトを「捨てる」ことができる場合です。

もちろん、メモリ マップされたファイルを使用することもできます。これにより、ファイルをメモリであるかのように読み書きできます (メモリが使用可能になると、OS は内容を RAM にキャッシュします)。Windows では、CreateFileMappingまたはを使用してファイル マッピングOpenFileMappingを作成または開き、MapViewOfFileファイルをメモリにマップします。終了したら、 を使用UnmapViewOfFileしてメモリを「マップ解除」しCloseHandle、FileMapping を閉じます。

ファイルマッピングに関する唯一の懸念は、次回はメモリ内の同じアドレスに表示されない可能性があることです。そのため、ファイルマッピング内にポインターを保持して、次回同じデータをバイナリとしてロードすることはできません。もちろん、毎回新しいファイルマッピングを作成しても問題ありません。

于 2013-07-23T11:34:42.517 に答える
0

あなたが説明した方法でOSが管理する唯一のものは、スワップファイルです。すべてのオブジェクトをメモリにロードしてリクエストを待機する別のアプリケーション (「キャッシュ ヘルパー」と呼びます) を作成できます。メモリページを使用しないため、OS は最終的にページをスワップファイルに移動し、必要な場合にのみ呼び出します。アプリケーションとの通信は、名前付きパイプまたはソケットを介して行うことができます。

このようなアプローチの欠点は、そのようなキャッシュのパフォーマンスが非常に不安定になり、サーバー全体のパフォーマンスが低下する可能性があることです。

後でそのプロパティを調整する必要があるかもしれないので、独自のキャッシング アルゴリズム/アプリケーションを作成することをお勧めします。

于 2013-07-23T10:51:13.857 に答える