Windows のキャッシュエラーを診断し、データ損失を防ぐ

最終更新: 07/01/2026
  • メモリカウンタを監視し、RAMMap、VMMap、WPR、WPAなどのツールを使用すると、異常なキャッシュ増加やメモリリークを検出できます。 Windows.
  • RemoteFileDirtyPageThreshold などのパラメータを調整し、FILE_FLAG_RANDOM_ACCESS の誤用を避けることで、システム キャッシュを抑制し、リモート書き込みのタイムアウトを防ぐことができます。
  • リークが仮想割り当てに影響するのか、ヒープに影響するのかを識別することが、原因となっているプロセスを追跡し、関連するソフトウェアを修正する鍵となります。
  • 適切な TTL、容量の増加、適切な置換ポリシーを通じて Web アプリケーション レベルでキャッシュを最適化すると、キャッシュ ミスが削減され、パフォーマンスが向上します。

Windows のキャッシュおよび HMB エラーの診断

Windowsの動作が遅くなったり、アプリケーションの起動に時間がかかったり、突然メモリ不足になったりする場合、その原因は多くの場合、システムがキャッシュ(ファイルとメモリの両方)をどのように管理しているか、そして特定のアプリケーションがそのメモリをどのように使用しているかにあります。システム内部で何が起こっているかを理解することは、クラッシュやパフォーマンスの低下、さらには特定のワークロードにおけるデータ損失のリスクを防ぐ上で非常に重要です。

幸いなことに、Windowsにはパフォーマンスカウンター、診断ツール、および特定の設定が含まれており、これらを使用することで、キャッシュの異常な動作を検出したり、メモリリークを特定したり、リモート書き込みのページ停止しきい値などの重要なパラメータを微調整したりできます。適切な方法とユーティリティを使用すれば、どのコンポーネントが最も多くのメモリを消費しているかを特定し、予防措置を講じることが可能です。

Windows のキャッシュとは何ですか? また、なぜ問題が発生するのでしょうか?

キャッシュとは、ハードウェアとソフトウェアの両方において、基本的にデータを一時的に保存して後続のアクセスを高速化する高速ストレージ領域のことです。プロセッサやメモリでは、L1、L2、L3キャッシュと呼ばれます。Windowsなどのオペレーティングシステムでは、システムファイルキャッシュが、繰り返し読み込まれる可能性のあるディスクデータを保存し、物理ストレージへの低速なアクセスを軽減します。

Windowsの場合、システムのファイルキャッシュはキャッシュマネージャによって管理され、どのページをメモリに保持し、どのページを破棄し、いつメモリを解放するかを決定します。特定のワークロード(数百万のファイル、頻繁なランダムアクセス、非常に高速なリモートクライアントを備えたサーバーなど)では、このキャッシュが大きくなりすぎて、システムが事実上メモリを利用できなくなる可能性があります。

キャッシュが物理RAMの大部分を占有し、適切なタイミングで解放されない場合、コンピュータの動作が遅くなり、プロセスの応答が遅くなるだけでなく、極端な場合には仮想メモリ不足によるエラーが発生することもあります。これはパフォーマンスだけでなく、ストレージの速度が遅く、キャッシュへの書き込み待ちが大量にある場合、リモート接続でタイムアウトが発生したり、ディスクへのデータ書き込みに大幅な遅延が生じたりする可能性もあります。

その他のシナリオでは、問題はシステムのファイルキャッシュではなく、特定のプロセスにおけるメモリリークです。これらのリークは、プロセスが仮想メモリ(コミットサイズ)を解放することなく、増大し続ける形で現れ、最終的にシステムリソースを枯渇させ、リソース枯渇検出器識別子2004などの警告イベントを引き起こします。

ウェブレベルでは、キャッシュミスという概念もあります。これは、アプリケーション(例えば、キャッシュプラグインを使用しているWordPressサイト)がキャッシュに存在しないデータを要求し、データベースやソースからデータを取得する必要がある場合に発生します。キャッシュミスが発生すると、レイテンシが増加し、ページの表示速度が低下します。また、頻繁に発生すると、キャッシュの多くの利点が失われてしまいます。

Windowsのキャッシュによるパフォーマンスの問題

Windows のファイルキャッシュを監視するためのキーカウンター

Windows Server 2012より前は、ファイルキャッシュが制御不能なほど増大し、利用可能なメモリをほぼ使い果たしてしまうという、2つの一般的な問題がありました。最近のバージョンではアーキテクチャが改善されていますが、同様の状況を検出するためにどのカウンターを監視すべきかを知っておくことは依然として役立ちます。

これらのシナリオを監視する上で最も重要なパフォーマンスカウンターは以下のとおりです

  • メモリ\長期平均スタンバイキャッシュ寿命(秒): スタンバイメモリの平均長期寿命。この値が1800秒(30分)未満の場合、システムのメモリ不足によりスタンバイページが急速にリサイクルされていることを示します。
  • メモリ\使用可能量(バイト / キロバイト / メガバイト)これはシステムで利用可能なメモリ量を反映しています。値が継続的に低く、システムキャッシュの使用率が高い場合は、通常、警告サインです。
  • メモリ\システムキャッシュ常駐バイトこれは、システムファイルキャッシュによって使用されている物理メモリの量を示します。この値がRAM全体の非常に大きな割合を占め、使用可能なメモリが少ない場合、キャッシュのサイズが大きすぎる可能性があります。

メモリの空き容量が少なく、同時にメモリのシステムキャッシュの常駐バイト数がRAMのかなりの部分を占めていることに気づいた場合は、そのキャッシュが何に使われているのかを正確に把握する必要があります。そのための重要なツールがRAMMapです。

RAMMapを使用してファイルキャッシュを埋めているものを特定する

RAMMapは、Sysinternalsが提供するユーティリティで、物理メモリの使用状況を詳細なグラフィカル表示で確認できます。特に、NTFSメタファイル、マップされたファイル、システムキャッシュなどに割り当てられているページ数を確認できます。

高負荷サーバーにおける過去の課題の一つは、NTFSメタファイルページがキャッシュに大量に蓄積されることでした。これは主に、数百万ものファイルが存在し、アクセス頻度が高いシステムで発生しました。メタファイルデータ(ファイルシステムの構造情報であり、ファイルの内容そのものではない)がキャッシュから適切に解放されず、リソース消費量の急増を引き起こしていたのです。

RAMMapの出力では、このシナリオはアクティブなメタファイルページの数が非常に多いことで検出されます。視覚的に見ても、このカテゴリがメモリの不均衡な割合を消費していることは明らかです。従来、この問題はDynCacheなどのツールによって緩和されていました。DynCacheはシステムキャッシュの制限を調整することで、この問題を抑制していました。

Windows Server 2012以降、キャッシュ管理の内部アーキテクチャは、このようなメタファイルの制御不能な増加を防ぐために再設計されたため、最新のシステムでは発生しないはずです。ただし、同様の動作を診断するために、症状を知っておくことは依然として役立ちます。

  Keypirinha とは何ですか? 他の Windows ランチャーと比べてどうですか?

RAMMapが明らかにするもう一つのシナリオは、システムのファイルキャッシュに大量のファイルがメモリに割り当てられている場合です。このツールは、多数のアクティブなマップ済みファイルページを表示します。これは多くの場合、多数の大きなファイルを開くアプリケーションに関連しています。

FILE_FLAG_RANDOM_ACCESSの影響とアプリケーションのベストプラクティス

Windows のキャッシュとメモリ管理

ファイルキャッシュのサイズが大きくなる典型的なパターンは、アプリケーションが FILE_FLAG_RANDOM_ACCESS フラグを指定して CreateFile を使用して多数の大きなファイルを開く場合に発生します。このフラグは基本的にキャッシュマネージャへの指示であり、データへのアクセスが非常にランダムになることが予想されるため、マップされたビューをできるだけ長くメモリに保持するように指示します。

FILE_FLAG_RANDOM_ACCESSを設定すると、キャッシュマネージャはメモリマネージャがメモリ不足状態を宣言するまでデータをメモリに保持しようとします。さらに、この設定はファイルデータのプリフェッチを無効にします。これは、理論的にはアクセスが連続したパターンに従わないためです。

この動作は、大きなファイルを頻繁に開いたり、完全にランダムなアクセスを繰り返したりすると、システムキャッシュが過剰に肥大化する可能性があります。Windows Server 2012以降のバージョンではワークスペースのトリミング機能が改善されていますが、この問題の最終的な解決責任はアプリケーションベンダーにあります。

開発者への強い推奨事項は、どうしても必要な場合を除き、FILE_FLAG_RANDOM_ACCESSの使用を避けることです。あるいは、メモリ優先度を低く設定してファイルにアクセスすることで、他のプロセスでメモリが必要になった際に、使用済みのページをワークスペースからより積極的に解放することができます。

この低いメモリ優先度は、SetThreadInformation API を使用して設定できます。この API を使用すると、ディスクアクセスを実行するスレッドのメモリ優先度を低く設定でき、システム全体のワーキングセットに対するスレッドのアクティビティの影響を軽減できます。

Windows Server 2016 では、キャッシュ マネージャーはさらに一歩進んで、トリミング時に FILE_FLAG_RANDOM_ACCESS の提案を無視し、これらのファイルを他のファイルと同様にキャッシュ トリミングします (ただし、フラグが示すようにプリフェッチは無効になります)。これにより問題は部分的に軽減されますが、アプリケーションがこのフラグを持つ多数のファイルを開き続け、アクセスが非常に分散している場合、キャッシュ サイズが不均衡になるリスクは完全には解消されません。

リモート ファイルの古いページしきい値とタイムアウトのリスク

リモート接続のパフォーマンスと安定性の両方に影響を与える可能性のあるもう1つの具体的な問題は、システムがリモートクライアントから比較的低速な宛先ストレージに対して非常に高速な書き込みを受信する場合に発生します。

Windows Server 2016より前のバージョンでは、リモートファイルのキャッシュされた「ダーティページ」のしきい値に達すると、追加の書き込みは同時書き込みとして処理されていました。これにより、大量のデータがディスクにフラッシュされ、ストレージ容量が不足している場合は、著しい遅延やネットワーク接続のタイムアウトが発生する可能性がありました。

この問題を解決するため、Windows Server 2016 ではリモート書き込み用のページ鮮度しきい値が別途導入されました。このしきい値を超えると、システムはオンラインディスクフラッシュを実行し、ストレージサブシステムに過負荷をかける可能性のある大きなスパイクを回避するために、データを徐々に書き込みます。

この仕組みは、書き込み処理が非常に集中している期間に時折処理速度の低下を引き起こす可能性がありますが、その代わりに、書き込み待ちデータが多すぎるためにリモートクライアントがタイムアウトする可能性を大幅に低減します。

このリモートしきい値のデフォルト値は、ファイルあたり5GBです。ハードウェア構成やワークロードによっては、この値を調整することをお勧めします。環境によっては、より高い制限値の方が良好な結果が得られる場合もあれば、デフォルト値を維持する方が望ましい場合もあります。

レジストリでRemoteFileDirtyPageThresholdを調整する方法

5GBの制限ではニーズを満たせない場合は、Windowsレジストリを使用してリモートページの陳腐化しきい値を変更できます。この設定は、RemoteFileDirtyPageThresholdの値によって制御されます。

  • キーパス: HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management
  • ティポ: DWORD
  • 値の名前: RemoteFileDirtyPageThreshold
  • データ: ページ数。各ページはキャッシュ マネージャーによって管理されるページ サイズ (通常は 4096 バイト) に相当します。

正しい値を計算するには、必要なバイト数をページ数に変換する必要があります。たとえば、しきい値を 10 GiB に設定したい場合は、まず 10,737,418,240 バイト / 4096 = 2,621,440 ページを計算します。これが、DWORD に入力する必要のある 10 進数値です。

一般的な推奨事項としては、使用可能なメモリの50%(ページ単位)から128MBまでの安全な範囲内で動作させることが推奨されます。理想的には、最適なバランスが見つかるまで、256MBずつ制限を増やし、変更ごとにパフォーマンスを測定する必要があります。

RemoteFileDirtyPageThreshold の値を変更した場合、新しい値を有効にするにはシステムの再起動が必要です。再起動を行わない場合、システムは以前に有効だったしきい値を引き続き使用します。

値を -1 に設定することでこのしきい値を完全に無効にすることも可能ですが、これは推奨されません。そうすると、大量のリモート書き込みによってキャッシュが古いページでいっぱいになり、クライアントのタイムアウトや接続問題が発生するリスクが高まるためです。

Windows のメモリ不足検出と 2004 イベント

キャッシュ機構に加えて、Windowsには仮想メモリの使用状況を監視するリソース枯渇検出機能があります。仮想メモリが不足した状態になると、システムログにイベントID 2004が記録され、最も多くのメモリを消費しているプロセスに関する詳細情報が提供されます。

イベント2004(Microsoft-Windows-Resource-Exhaustion-Detector)の典型的な例としては、 Windowsが仮想メモリ不足の状態を正常に診断したことを示すメッセージと、その時点で最も多くのメモリを消費したプログラムのリスト(実行ファイル名、PID、コミットされたバイト数を含む)が表示されます。

  WindowsにおけるCredential GuardおよびDevice Guardの設定に関する完全ガイド

多くのタスクマネージャーのビューでデフォルトで表示されるメモリ列は、この種の診断において最も重要な情報ではないことを理解しておくことが重要です。通常、これはRAMによってバックアップされたプライベートメモリ(ワーキングセット)を反映していますが、ここで重要なのは、システムが各プロセスに割り当てた仮想メモリの総使用量です。

このような場合に監視すべき指標はコミットサイズです。これは、物理RAMかページファイルかに関わらず、Windowsがプロセスに割り当てる仮想メモリを表します。システム全体のコミットサイズが制限値に近づくと、2004イベントがトリガーされます。

この現象は、Microsoft のプロセスとサードパーティ製アプリケーションの両方で発生する可能性があります。プラットフォーム固有のプロセスの場合、通常は詳細な分析を可能にする公開シンボルが存在します。一方、サードパーティ製ソフトウェアの場合は、コールスタックに明確な名前の関数が表示されない場合、ベンダーに問い合わせて追加情報を入手する必要がある場合が多くあります。

VMMapを使用してリークされているメモリの種類を分類する

メモリリークが疑われる場合、最初のステップは、どの種類のメモリが制御不能に増加しているかを特定することです。VMMapは、プロセスのメモリ使用量をプライベートデータ、ヒープ、イメージ、スタックなどのカテゴリに分類してくれるため、この目的に非常に役立つツールです。

汎用仮想割り当てメモリでメモリリークが発生した場合、VMMap ではプライベートデータカテゴリの継続的な増加として表示されます。このメモリは管理ヒープに直接関連付けられているのではなく、プロセスが解放しないアドレス空間の予約とコミットメントに関連しています。

プロセスメモリダンプが利用可能な場合、WinDbgを使用して`!address -summary`コマンドを実行できます。サマリーでは、問題のある仮想割り当てメモリは通常`<unknown>`カテゴリの下に表示され、これは総メモリ空間のかなりの部分を占める、分類されていない大きなメモリ領域を示しています。

メモリリークがプロセスのヒープに関連している場合、VMMap のヒープカテゴリに反映されます。ヒープメモリの使用量は時間とともに着実に増加し、目立った改善は見られません。

繰り返しになりますが、WinDbgでダンプと`!address -summary`コマンドを使用すると、これらのケースでは、プロセスアーキテクチャに応じて、非常に高い割合がHeap32またはHeap64として分類されます。残りのカテゴリ(イメージ、スタック、その他)は、総使用量のごく一部を占めるにすぎません。

仮想メモリ割り当ての問題なのか、ヒープリークの問題なのかを正しく特定することは非常に重要です。なぜなら、それによって次にどのような監視を有効にすべきか、また、どのツールが問題の原因となっているコンポーネントを見つけるのに役立つかが決まるからです。

仮想割り当てメモリのWPRによるトレース収集

仮想メモリの割り当てリークが発生していることが明らかになったら、次のステップは、誰がその割り当てを行っているかを明らかにする再現可能なデータを収集することです。Windows 10およびWindows Server 2016に標準搭載されているWindows Performance Recorder(WPR)は、この目的に使用できます。

基本的な手順としては、仮想メモリ割り当てに焦点を当てたトレースセッションを開始し、メモリ使用量が増加する間、プロセスが自然に動作するのを待ち、割り当てに関する十分な情報が蓄積された時点でトレースを停止する。

C:\>wpr -start VirtualAllocation

トレースが実行されている間は、タスクマネージャ、リソースモニタ、または同様のツールを使用してプロセスのコミットサイズを追跡することで、メモリ消費量の増加を監視します。このWPRプロファイルの利点は、仮想割り当てのみに焦点を当てているため、生成される.etlファイルが通常それほど大きくならず、数分間アクティブな状態を維持できることです。

C:\>wpr -stop virtalloc.etl

virtualloc.etl ファイルには仮想メモリ割り当てイベントが含まれており、それらは Windows Performance Analyzer (WPA) で分析されます。これにより、解放されていないメモリ予約の背後にある関数やモジュールを確認できます。

WPRでヒープメモリのトレースを収集する

プロセスヒープに関連するメモリリークが発生した場合、次のステップは特定のヒープトレースを収集することです。これを行うには、WPRを構成して、ターゲット実行ファイルからのヒープイベントをログに記録します。これは通常、トレースを有効にするレジストリエントリを介して行われます。

レジストリを手動で変更するか、WPRを使用してターゲットバイナリを構成できます。たとえば、VirtMemTest32.exeのヒープトレースを有効にするには、管理者権限でコマンドプロンプトから起動します。

C:\>wpr -heaptracingconfig VirtMemTest32.exe enable

このコマンドは、以下の設定キーを作成します。 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\VirtMemTest32.exe、Tracing Flags と呼ばれる DWORD 値は通常 1 に設定され、その実行可能ファイルのヒープ トレースが有効になります。

診断フェーズが終わったら、不要な実行時オーバーヘッドを避けるため、キーを削除するか、トレースフラグの値を0に設定して、トレースを再度無効にすることが重要です。

適用された構成では、ヒープトレースは以下のように取得されます

C:\>wpr -start Heap

仮想メモリ割り当てと同様に、コミットサイズを監視する間、プロセスは数分間実行されます。ログに記録されるのはヒープイベントのみであるため、ほとんどのシナリオでトレースサイズは管理可能な範囲内です。

C:\>wpr -stop Heap.etl

その結果、ヒープの割り当てと解放イベントを含む Heap.etl ファイルが生成され、これを WPA で解析して、メモリリークの原因となっているコールスタックを特定します。

Windows パフォーマンス アナライザー (WPA) によるトレース分析

診断プロセスの最終ステップは、Windows Performance Toolkit に含まれるツールである Windows Performance Analyzer を使用して .etl トレースを開くことです。Windows Performance Toolkit は、ADK (Assessment and Deployment Kit) の一部です。

  Windowsメンテナンスツールを使ってWindowsを簡単に修復、クリーニング、メンテナンスする方法

データの調査を開始する前に、コールスタックが人間が読みやすい関数名に解決されるように、シンボルパスを正しく構成することが不可欠です。WPAでは、これは「トレース」>「シンボルパスの構成」メニューから、次のようなパスを追加することで行います。

srv*C:\LocalPubSymbols*https://msdl.microsoft.com/download/symbols

シンボルが設定されたら、シンボルメニューからシンボルを読み込み、対応する.etlファイルを開きます。仮想メモリ割り当てリークが発生した場合は、問題のあるプロセスを中心としたビューを再現し、コミットスタック列が金色または黄色のグリッド線の左側にあることを確認してください。

コミットスタックを展開すると、解放されていない仮想メモリ割り当てを発生させている関数が特定されます。スタック上で割り当て関数のすぐ上に表示されるモジュールが、通常、メモリを繰り返し要求している論理的な犯人です。

ヒープリークの場合も同様のアプローチですが、ビューには区切り線の左側に「ハンドル」や「スタック」などの列を含める必要があります。これらのスタックを調べると、対応する解放を行わずにヒープに対して予約呼び出しを行っている関数が明らかになります。

どちらの場合も、関係するモジュールと関数が特定されたら、次のステップは通常、ソフトウェアのアップデートや既知のパッチを確認するか、カスタムアプリケーションの場合は、デバッグして割り当てパターンを修正し、メモリリークを解消することです。

Webアプリケーションのキャッシュ障害とその軽減方法

オペレーティングシステム以外にも、キャッシュミスという概念はWordPressのようなWebアプリケーションにおいて非常に重要です。キャッシュミスとは、システムやアプリケーションが要求したデータがキャッシュに存在せず、データベースやソースから取得する必要がある場合に発生します。

一方、キャッシュヒットとは、コンテンツがメモリ、ディスク、またはサーバーレベルのキャッシュから直接取得された場合に発生します。キャッシュヒットが多いほど応答速度は速くなり、キャッシュミスが多いほどレイテンシが高くなり、サーバーとデータベースへの負荷が大きくなります。

キャッシュ障害の典型的な原因としては、そもそも保存されなかったデータ、容量不足のために削除されたデータ、手動または自動でキャッシュから削除されたデータ、あるいは有効期限(TTL)ポリシーが切れたデータなどが挙げられます。

キャッシュミスが発生した場合、システムは通常、データソースに対して2回目のアクセスを試みます。要求されたリソースが存在する場合は、データベースまたはメインストレージから読み取られ、クライアントに返されます。そしてほとんどの場合、今後のリクエストを高速化するために、リソースは再びキャッシュされます。

問題は、階層構造に沿ってデータ転送が行われるたびに(L1キャッシュからL2キャッシュへ、L2キャッシュからメインメモリへ、メモリからディスクへなど)、データ損失によるペナルティが発生することです。非常に混雑した環境では、このようなデータ転送の損失が過剰になると、応答時間が著しく低下します。

ウェブ環境でのキャッシュ障害を減らすための実践的な戦略

ウェブサイトのキャッシュ障害の頻度を減らすには、パフォーマンスとコンテンツの鮮度を常にバランスさせながら、関連データをできるだけ長くキャッシュに保持することが目標となります。

基本的な対策としては、適切なキャッシュ有効期間(TTL)を設定することが挙げられます。キャッシュがクリアされるたびに、次のリクエストの前にデータを再計算して書き込む必要があり、その結果、初期ミスが発生します。コンテンツが頻繁に変更されない場合にTTLを延長することで、無効化を減らし、結果としてミスを減らすことができます。

マネージドホスティングプロバイダーでは、関連する変更が検出された場合にのみ、キャッシュの特定の部分のみをクリアするのが一般的です。例えば、一部の専門ホスティングプロバイダーが使用するプラグインは、サーバー全体のキャッシュを消去するのではなく、変更された投稿やサイトの特定の部分のキャッシュのみをクリアします。

キャッシュミスを減らすもう一つの方法は、キャッシュ自体のサイズ、または使用可能なRAMを増やすことです。容量が大きくなれば、使用頻度の低いオブジェクトを削除することなく、より多くのオブジェクトを同時に保存できるため、強制削除の回数を減らすことができます。

これにはコストがかかります。RAMを増設したり、拡張性の高いホスティングプランに加入したりすると追加費用が発生するからです。しかし、トラフィック量の多いプロジェクトにおいては、パフォーマンスと安定性の面で最も費用対効果の高い最適化の一つとなり得ます。

最後に、アプリケーションのアクセスパターンに合ったキャッシュ置換ポリシーを選択することは非常に有効です。最も一般的なものとしては、FIFO(先入れ先出し)、LIFO(後入れ先出し)、LRU(最近使用頻度の低いものから順に使用)、MRU(最近使用頻度の高いものから順に使用)があり、それぞれ負荷の種類に応じて長所と短所があります。

これらのポリシーを賢く組み合わせることで、空き容量を確保する必要がある場合にどのキャッシュオブジェクトを最初に削除するかを制御でき、キャッシュサイズを増やし続けることが現実的でない場合でも、最も価値のあるオブジェクトや最も頻繁に使用されるオブジェクトをメモリに保持することができます。

実際には、特に多くのキャッシュ設定がサーバーレベルで行われるマネージド環境においては、ホスティングプロバイダーと連携してサイトのキャッシュ設定を調整するのが、TTL、ポリシー、容量を調整する最善の方法となることが多い。

Windowsがキャッシュとメモリをどのように管理しているか、メモリリークや問題のあるしきい値をどのように診断するか、WordPressなどのアプリケーションでキャッシュの使用を最適化する方法を理解することで、ボトルネックを回避し、レイテンシを削減し、ローカルサーバーと要求の厳しいWeb環境の両方でデータ損失やタイムアウトのリスクを最小限に抑えることができます。