重いプロセスがスワップファイルに沈むのを防ぐ
-
08-07-2019 - |
質問
私たちのサービスは、クライアントのサーバー上で夜間に眠りにつく傾向があり、その後、目覚めるのに苦労します。起こりそうなのは、プロセスヒープ(場合によっては数百MB)がスワップファイルに移動されることです。これは、サービスが使用されておらず、他のサービス(DBバックアップ、AVスキャンなど)の実行がスケジュールされている夜間に発生します。これが発生すると、非アクティブな状態が数時間続いた後、サービスへの最初の呼び出しには数分かかります(その後の呼び出しには数秒かかります)。
これは仮想メモリ管理の問題であると確信しており、OSにサービスを物理メモリに保持させるという考えは本当に嫌いです。これを行うと、サーバー上の他のプロセスが破損し、サーバー全体のスループットが低下することがわかっています。そうは言っても、私たちのクライアントは単にアプリが反応することを望んでいます。夜間の仕事に時間がかかっても気にしません。
Windowsに物理メモリ上にページを保持させる方法があることを漠然と覚えていますが、その考えは本当に嫌いです。私は、より高いレベルの機能を開始する内部または外部のウォッチドッグにもっと傾いています(すでにほとんど何もしない、違いのない内部スケジューラーがいくつかあります)。その種のサービスを提供するサードパーティ製のツールがあれば、それは同様に良かったでしょう。
この種の問題に対するコメント、推奨事項、および一般的な解決策を聞きたいです。サービスはVC2005で記述され、Windowsサーバーで実行されます。
解決
おっしゃったように、アプリをメモリにとどめることは、マシン上のリソースを共有する最良の方法ではありません。うまくいくと思われる手っ取り早い解決策は、クライアントが使用を開始する前に、毎朝特定の時間にサービスを起動するイベントをスケジュールすることです。単純なスクリプトまたはEXE呼び出しを使用して、Windowsタスクスケジューラでスケジュールすることができます。
他のヒント
これをやりたいと言っているわけではありませんし、それがベストプラクティスであると言っているわけではありませんが、あなたにとっては十分うまくいくかもしれません。求めているものと一致しているようです。
概要:プロセスのすべてのページを、一度に1ページずつ、定期的にタッチします。
バックグラウンドで実行され、N秒ごとに起動するスレッドはどうでしょう。ページが起動するたびに、アドレスXからの読み取りを試みます。この試みは、不正なアドレスを読み取った場合に備えて、例外ハンドラーで保護されています。次に、ページのサイズでXを増やします。
4GBには65536ページ、3GBには49152ページ、2GBには32768ページがあります。アイドル時間(一晩のデッドタイム)を各ページにヒットする頻度(試行)で割ります。
BYTE *ptr;
ptr = NULL;
while(TRUE)
{
__try
{
BYTE b;
b = *ptr;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// ignore, some pages won't be accessible
}
ptr += sizeofVMPage;
Sleep(N * 1000);
}
GetSystemInfo()から返された結果のdwPageSize値からsizeOfVMPage値を取得できます。
if(!IsBadReadPtr(ptr))を使用して例外ハンドラーを回避しようとしないでください。アプリの他のスレッドが同時にメモリ保護を変更している可能性があるためです。このためにスタックした場合、その理由を特定することはほとんど不可能であるため(繰り返し発生しない競合状態になる可能性が高いため)、時間を無駄にしないでください。
もちろん、日中はこのスレッドをオフにし、デッドタイム中にのみ実行したいでしょう。
3番目のアプローチは、カウンターをインクリメントしてから10秒などのかなり長い時間スリープするような些細なことを行うスレッドをサービスに実行させることです。 Thiosは他のアプリケーションには最小限の影響しか与えないはずですが、少なくとも一部のページは利用可能にしておきます。
確認する他のことは、データがローカライズされていることです。
つまり、何かをする前に、300 MiBのメモリすべてが本当に必要ですか?使用するデータ構造を再配置して、特定の要求が数メガバイトだけで満たされるようにできますか?
たとえば
-
300 MiBのヒープメモリに顔認識データが含まれている場合。男性と女性の顔データが一緒に保存されるように、データを内部的に配置できますか?または、大きな鼻は小さな鼻とは別ですか?
-
何らかの論理構造を持っている場合、ソートできますか?バイナリ検索を使用して多くのページをスキップできるようにするために
-
専用のインメモリデータベースエンジンである場合、それほど多くのメモリページヒットを必要としないように、データのインデックス/クラスター化を改善できますか?
-
画像テクスチャの場合、一般的に使用されるテクスチャを互いに近くに配置できますか?
何かをする前に、300 MiBのメモリすべてが本当に必要ですか?そのデータをメモリに戻すすべてなしではリクエストを処理できませんか?
それ以外の場合: 6 atでスケジュールされたタスクを起動します。
コストの面で、最も安価で簡単な解決策は、おそらくそのサーバー用にRAMを追加購入することです。その後、ページファイルを完全に無効にすることができます。 32ビットWindowsを実行している場合は、4GBのRAMを購入するだけです。その後、アドレス空間全体が物理メモリでバックアップされ、ページファイルは何もしません。