メモリ使用量が増える現象 (メモリリーク)

Last Update: feedback 共有

今回は Internet Explorer を利用している場合に発生するメモリ使用量が増える現象についてお話しします。
なお、本記事に掲載している内容は、Internet Explorer 以外の、例えば Microsoft Edge や Google Chrome、Firefox といったほかのブラウザーでも有効な部分があります。ぜひ参考にしてみてください。

もともと二回シリーズでの執筆を検討していましたが、記事の移動に合わせて一つの記事にまとめています。
Internet Explorer を利用しているときに「あれ?おかしいな…」と思ったら、下記手順に従い確認をしてみてください。


本記事では、Internet Explorer を利用している場合のメモリ使用量が増える現象について、まずは一般的な知識と、それを切り分ける方法についてまとめました。
Internet Explorer 上でのメモリ使用量の増加の現象は、単純な方法での調査が難しく、本記事に記載したような内容をコツコツと時間をかけて確認する必要があり非常にお時間がかかるケースが多いですが、少しでも参考になれば幸いです。

1. メモリ使用量が増えるのはなぜ?
そもそも Internet Explorer で Web ページを閲覧していると、徐々にメモリ使用量が増えていくのはなぜなのでしょうか。

この疑問に答えるには、まずブラウザーって何?という点を理解する必要があります。

ご存じのとおり、Internet Explorer をはじめとする “Web ブラウザー” は Web コンテンツ (html や CSS、JavaScript、画像、動画などなど) を表示 / 動作させるための、いわば「プラットフォーム」です。これは、Windows や Mac などのプラットフォーム (OS) 上で任意のアプリケーションを動作させるのと同じイメージです。ブラウザーというプラットフォーム上で「Web コンテンツ」というアプリケーションを動作させています。

まず、OS 上で動作するアプリケーションが利用するメモリ使用量が増加する傾向がみられる場合を考えましょう。
この場合に考えられるポイントは、「プログラム内で確保したメモリ領域がきちんと解放されていない」ことです。いわゆる、メモリリークです。

では、Web コンテンツを表示しているブラウザーのメモリ使用量に増加傾向がみられる場合には何が考えられるでしょうか。
実は、基本的には通常のアプリケーションでの状況と同様に、ブラウザーというプラットフォーム上で動作する Web コンテンツの作りに強く依存していることが多く、Web コンテンツ自体の構成やその中で行われている処理が影響してメモリ使用量が増加している可能性があります。

また、Internet Explorer の場合には、ActiveX コントロールやブラウザー ヘルパー オブジェクト (BHO)、ツール バーといったアドオンを利用することができますが、これらの中で上記に記載したような「プログラム内で確保したメモリ領域がきちんと解放されていない」現象が発生しており、これらが影響してメモリ使用量が増加している可能性もあります。これらのアドオンは、C や C++ などのネイティブ言語で作成される場合が多く、通常のアプリケーションと同様に、プログラム内で独自に、自由に、メモリ領域を確保することができます。
さらに、何らかのソフトウェアが、Internet Explorer で行われている処理を外部から参照して (場合によってはフック (本来の処理を迂回させてオレオレな処理を実行する手法) して) いることなどが影響している可能性も考えられる一つのポイントです。

2. メモリが枯渇すると何が起きる?
では、メモリ使用量が増えていくと何かが起きるのでしょうか。

端的には「メモリの枯渇」という状態に内部的に陥ります。

Internet Explorer の場合、既定の状態では OS が 64bit 環境だとしても、コンテンツを表示するプロセス (タブ プロセスもしくはコンテンツ プロセス) は 32bit プロセスとして動作します。(参考 : Internet Explorer のプロセス モデル

Windows OS の仕組み上、32bit プロセスでアプリケーションが自由に利用できるメモリ領域の上限は理論値として 2GB です。
アプリケーションは、この 2 GB のメモリ アドレス空間内で、必要なサイズのメモリ ブロックを確保します。
このメモリ ブロックの確保と解放を繰り返していると、使用済みの領域と空き領域が細かなサイズで混在し、合計では十分な空き領域があっても、まとまった大きなサイズのブロックを確保できない状態 (断片化) に陥ります。
なお、この動作は、端末上に搭載されている物理メモリ量に関係なく、また、タスク マネージャー上で確認のできるメモリの空き容量とも関係はありません。あくまでも、単一のプロセスで利用することのできるメモリ領域が対象となります。

Internet Explorer では、Web コンテンツを表示する際に内部的にメモリ領域を確保する必要がありますが、上記のように断片化が進んだ状態となっているとメモリ領域の確保に失敗する場合があり、この結果 Web コンテンツを正しく表示できない (表示が崩れる)、そもそも真っ白で何も表示されない、クラッシュしてしまう、などの影響が生じます。
このような問題が発生した場合には、タスク マネージャーなどで Internet Explorer のプロセス (iexplore.exe) の状態を確認し、メモリ使用量が 1GB – 1.5GB 以上使用している状態であれば、メモリ枯渇が原因である可能性が高いと判断ができます。

なお、64bit OS 環境下で、拡張保護モードが 64 bit で動作するよう構成している場合 には 64bit でプロセスが動作するため、上述したような 2GB という制限はありません。理論値としては 8TB (テラ バイト) です。

参考: 仮想アドレス領域
https://msdn.microsoft.com/ja-jp/library/windows/hardware/hh439648(v=vs.85).aspx


参考 : VMMap - プロセス の仮想メモリと物理メモリの割り当て状況をグラフィカルに表示してくれるツール -

Windows Sysinternals ツールの 1 つに、プロセスの仮想メモリと物理メモリの割り当て状況をグラフィカルに表示してくれるツールとして VMMap というものがありますので紹介します。

https://docs.microsoft.com/en-us/sysinternals/downloads/vmmap

vmmmap.exe を起動し、確認したいプロセスを選びます。

VMMap1

このようにメモリの使用状況について詳細を把握することができます。
VMMap2

メニューの View - Fragmentation View を選択します。
VMMap3

以下のようにメモリの割り当て状況をグラフィカルに表示してくれますので、未使用を示す “白色の領域” が充分にあるかどうか確認ができます。
VMMap4

このツールを使えば、上述の断片化状態かどうかも視覚的に把握することができますので、ぜひご利用ください。


重要 : メモリ使用量の見方について

プロセスで実際にメモリ不足の問題が発生するかどうかは、「ワーキング セット」ではなく、「コミット サイズ」に着目することが重要です。
「ワーキング セット」とは、プロセスが利用しているメモリ領域のうち「物理メモリ上に展開されている部分」を指すものであり、「プロセスが使用しているメモリ全体のサイズ」はわかりません。
「プロセスが使用しているメモリ全体のサイズ」を示しているのは「コミット サイズ」です。

実際の例をみてみましょう。
タスク マネージャーでは既定では「メモリ (アクティブなプライベート ワーキング セット)」という項目が表示されています。
TaskMgr1

ここで問題です。このふたつのプログラムのうち、どちらがメモリを多く使用しているでしょうか?

上述のことを思い出してください。「コミット サイズ」を見なければ答えられません。
それではタスク マネージャーの表示項目にコミット サイズを追加してみましょう。
TaskMgr2

結果はこの通りです。片方はコミット サイズが 800MB ほどなのに対して、もう片方は 1MB ほどであることがわかります。
TaskMgr3

「プロセスが使用しているメモリ全体のサイズ」を示しているのは「コミット サイズ」なので、「PID:17652 の方が多くのメモリを使用している」が答えになります。


3. メモリリークなのか?
タスク マネージャーなどで、メモリの使用量が多いことがわかったとしても、メモリリークが発生しているとは一概には言えません。
右肩上がりにメモリ使用量が増えるのか、ある一定の使用量を上限に横ばいとなるのか確認しましょう。
ある一定の使用量を上限に横ばいとなる場合には、Web コンテンツ上の構成が非常に大量のメモリを必要とするものの、コンテンツとしても、Internet Explorer の動作としても問題ない動作であると判断ができます。

Internet Explorer では、Web コンテンツを表示 / 動作させるためにメモリ領域を確保する動作となるため、一定量増えることは Web コンテンツを表示 / 動作させるうえでの想定動作となります。ページ遷移などに伴い、不要となったメモリ領域については “ガベージ コレクション” という仕組みの下で一定時間後に自動的に解放される動作となります。

ここで一つ例を挙げます。
ある Web アプリケーションで使い始めは以下のように 130 MB ほどのメモリが使用されていました。
TaskMgr4

アプリケーションを操作していると、いつのまにか 1GB 近くまでメモリ使用量が増えてしまいました。
TaskMgr5

もう少し操作をしていると、ブラウザーが応答しなくなり、数秒後に以下の通知バーが表示されました。
NotificationBar

何が起きたのでしょう?イベント ログをみてみると、iexplore.exe がクラッシュ (異常終了) してしまったことがわかります。
EventLog

※ この例では例外コード 0x8007000e (E_OUTOFMEMORY) というメモリ不足を示すものでしたが、別の例外コードが記録されることもあります。

これはメモリリークが起きたことで、メモリ不足に陥ってクラッシュしてしまったのでしょうか?
もちろんそういう場合もありますが、この例では、多少はメモリリークしている状況ではあったものの、それが一番の理由ではありませんでした。
どのようにしてみていけばよいのでしょうか?

ポイントは繰り返しになりますが「右肩上がりにメモリ使用量が増えるのか、ある一定の使用量を上限に横ばいとなるのか」です。
先ほどは 32bit プロセスではメモリ不足の状態に陥ってしまいましたが、IE のプロセスを 64bit で動作させて 同じ Web アプリケーションでメモリ使用量の上がり具合をみていきます。

初めは 170MB くらいです。
TaskMgr6

しばらく操作をしていると 1.3GB ほどまで増えました。
32bit プロセスであれば、表示が崩れたり、クラッシュしてしまうなどの異常がいつ発生してもおかしくない状況です。
今回は 64bit プロセスなので問題なく動作しつづけます。
TaskMgr7

さらに操作をすると一時的に 2GB ほどまで上昇することがありました。
TaskMgr8

しかし、その直後に以下のように 1.5GB ほどまで下がり、このあとは、操作を繰り返しても、1.5 GB ~ 2 GB あたりを行き来するようになりました。
TaskMgr9

つまり、「右肩上がりにメモリ使用量が増える」状況ではないことが明らかになりました。

ここでのポイントは、いったんは上昇したメモリ使用量が下がった、つまり、不要となったメモリ領域を解放する “ガベージ コレクション” が実行されたことです。
もし、ガベージ コレクションで解放されないような参照状態をもつオブジェクトが存在した場合には、そのオブジェクトに紐づくメモリ領域は解放できないまま残り続けますので、メモリ使用量は右肩上がりになります。
今回は、ガベージ コレクションが有効に働き、ある一定の使用量を上限に横ばいとなりました。
つまり、Web アプリケーションの構造上非常に大量のメモリを必要とするものの、コンテンツとしても、Internet Explorer の動作としても問題ない動作であると言えます。


参考 : ガベージ コレクションについて
Internet Explorer の JavaScript のガベージ コレクションの動作は非常に保守的であり、積極的にオブジェクトを回収する動きにはならないことが挙げられます。
たとえば、32bit プロセスの Internet Explorer が 800 MB ほどメモリを使用している状況で、ある処理を実行するために一時的に 300 MB ほどの大きなメモリ領域が必要になる場合を考えてみます。
このとき、上述の Internet Explorer のガベージ コレクションの性質上、事前にガベージ コレクションを実行して可能な限り不要なメモリ領域を解放してから、新たなメモリ領域を確保するような動作とはなりませんので、大きなサイズのメモリ確保が必要なときに、メモリの断片化が進んだ状態だと、まとまったメモリの確保が行えず、処理に失敗してしまいます。
その結果、描画の処理が適切に実行できなかったり、致命的なエラーでアプリケーションがクラッシュしたりします。

なお、基本的にはページの遷移 (再読み込み、ナビゲート) によって、ページに紐づくオブジェクトはガベージ コレクションの対象となり解放されます。
一方で、ページ遷移をせずに、スクリプトにより画面の一部や全体を動的に書き換える動作を繰り返す SPA (Single Page Application) では、メモリの確保と破棄が頻繁に行われ、再利用され得るオブジェクトがメモリに残存しやすいことも影響し、プロセスを長時間動作させていると、プロセス内の空きメモリが断片化する状況が発生します。

即時的な解決方法としては、起動中の Internet Explorer をすべて終了し再起動しなおすこと、になりますが、本格的に調査を進める場合には、後述の点を少しずつ切り分けていく必要があります。

なお、SPA のようにリッチな UI をもつモダンな Web アプリケーションは、Internet Explorer では快適な動作が難しいケースも多くみられますので、コンテンツにみあったブラウザー (Microsoft Edge などのモダン ブラウザー) で閲覧することをおすすめします。


4. どうやって切り分けができるか?

このような状況となる原因を特定するために、何を確認すれば良いでしょうか。
私たちサポート チームにお問い合わせをいただいた際には、お客様に対してまずは以下の点の確認を依頼させていただくことが多いです。

お問い合わせをご検討される際には、下記の確認結果や作成いただいたサンプル プログラムとともに弊社までご連絡いただけるとスムーズに調査を開始することができます。なお、お問い合わせの際には「プレミア サポート」をご利用いただいたほうが詳細なデバッグ調査を含めた本格的な支援をさせていただくことが可能です。

• メモリの増え方を確認する
• ドキュメント モードを変更してみる
• 環境ごとに差異がないか確認する
• 最新の更新プログラムを適用する
• アドオン無効を試す
• サードパーティー製ソフトウェアをアンインストールする
• クリーンな環境で試す
• コンテンツを切り分ける

一つずつ見ていきましょう。

メモリの増え方を確認する
先ほど説明したように、まずは、右肩上がりにメモリ使用量が増えるのか、ある一定の使用量を上限に横ばいとなるのか確認しましょう。
ある一定の使用量を上限に横ばいとなる場合には、Web コンテンツ上の構成が非常に大量のメモリを必要とするものの、コンテンツとしても、Internet Explorer の動作としても問題ない動作であると判断ができます。
右肩上がりにメモリ使用量が増え続けるようであれば、その原因調査を進めるために、以下を確認していきましょう。

ドキュメント モードを変更してみる
Internet Explorer には過去のバージョンとの互換性を維持するために「ドキュメント モード」という機能が搭載されています。
この「ドキュメント モード」を変更することで現象に差異が生じるかどうか確認しましょう。

ドキュメント モードの変更には下記のいずれかが利用できます。
なお、<meta> による定義を行う場合には、現象に関連するすべての html ファイルに含める必要があるため、検証目的の場合には HTTP 応答ヘッダーに含める方が容易かと思います。

<meta> による定義 : 以下の定義を <head> 要素の先頭に追記します
<meta http-equiv="X-UA-Compatible" content="IE=xxx" />

HTTP 応答ヘッダーによる定義 : 以下のヘッダーを HTTP 応答ヘッダーに含めるようにします
X-UA-Compatible: IE=xxx

※ IE=xxx の “xxx” 部分には 11/10/9/8/7/5 のいずれかを設定します

環境ごとに差異がないか確認する
一部の環境だけで発生するのか、すべての環境で発生するのか確認しましょう。
また、異なる OS 上の同一バージョンの Internet Explorer を利用した場合に動作に差異が出ないか確認しましょう。

一部の環境でのみ発生する現象の場合、当該の環境にのみインストールされている何らかのアドオンやソフトウェアの影響が推測されます。次項以降のアドオンの無効やサードパーティー製のソフトウェアのアンインストールなどを試してみましょう。

最新の更新プログラムを適用する
残念ながら、製品自体の動作が起因してメモリ使用量が増える場合もあります。
毎月公開されている Internet Explorer や Microsoft Edge 向けの更新プログラムを提供することで現象に差異が生じるかどうか確認しましょう。

なお、Windows 7 / 8.1 の環境では、Internet Explorer 向けの更新プログラムが個別に提供されていますが、Windows 10 においては Internet Explorer / Microsoft Edge ともに OS の更新プログラム (ロールアップ) に含まれています。

アドオン無効を試す
Web コンテンツ上で ActiveX コントロールを利用している場合にはその使用をやめてみる、BHO やツール バーなどが導入されている場合にはそれらのアドオンをアンインストールしてみる、ことにより現象が改善するかどうか確認しましょう。

アドオン無効により劇的に状況が改善する場合には、アドオンの動作が影響していると判断することができます。
この状況の場合には、アドオン内の処理において問題となる点がないかどうか確認してください。また、サードパーティー製のアドオンである場合には、開発元にお問い合わせしてみてください。

なお、下記の方法で一時的なアドオンの無効化を試すことも可能です。

方法 1)
Windows キー + R キーで起動する “ファイル名を指定して実行” で、下記を実行することでアドオン無効モードで Internet Explorer を起動することができます。

iexplore.exe -extoff

このような画面で Internet Explorer が起動します。
extoff

方法 2)
Internet Explorer を起動し、[ツール] メニューの [アドオンの管理] 画面で、個別にアドオンを無効にすることができます。
addon
左ペインで [ツール バーと拡張機能] を選択し、”表示” 欄で [すべてのアドオン] を選択します。
その後、右ペインで無効にしたいアドオンを選択し、画面右下に表示されている [無効にする] ボタンをクリックすることでアドオンを無効とすることができます。
無効にした後、Internet Explorer を再起動します。

サードパーティー製ソフトウェアをアンインストールする
Windows OS 上に、サードパーティー製のソフトウェアが導入されている場合、製品を一つずつアンインストールしていき、いずれかのソフトウェアの動作が影響していないかどうか確認しましょう。

なお、一部のソフトウェアでは、ソフトウェアが動作しないように “無効” とする設定がありますが、当該ソフトウェアが動作していない状態でも Internet Explorer が起動する際に自動的に読み込まれてしまうような DLL もあるため、可能な限りアンインストールを試してください。

サードパーティー製のソフトウェアをアンインストールして改善する場合には、当該のソフトウェアの動作が影響していると判断することができます。
この状況の場合には、ソフトウェアの開発元にお問い合わせしてみてください。

クリーンな環境で試す
アドオンやサードパーティー製のソフトウェアが多数あり、アンインストールでの切り分けが難しい場合、クリーンな環境を用意して試してみる、という方法もあります。

ここでいう「クリーンな環境」とは、Windows OS のインストール ディスクを利用して OS をインストールしただけの状態、もしくはその状態で Windows Update のみを実行した状態、です。
上述しているような、アドオンやサードパーティー製のソフトウェアが一切インストールされていない環境です。

クリーンな環境では現象が発生しない場合には、問題の発生する環境に導入しているアドオンやソフトウェアを一つずつインストールしていき、現象の変化ポイントを特定してください。

なお、有効期限付きですが、下記のサイトより Hyper-V や VMWare などの仮想環境上で利用可能な仮想 PC をダウンロードすることができます。
クリーンな環境のご用意が難しい場合には是非有効活用ください。

Download virtual machines
https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/

コンテンツを切り分ける
問題の発生する Web コンテンツの編集が可能である場合、現象の再現に必要な部分のみを抽出することができないか確認してください。
具体的には、現象の再現に必要のない下記のような要素を少しずつ削除する作業を繰り返します。

a) html ドキュメント内のタグを減らす
b) 画像や動画、音声ファイルを削除する
c) スタイルを外す (外部ファイルとしているスタイルシート、およびコンテンツ内で直接指定しているスタイル)
d) スクリプトを外す (外部ファイルとしている JavaScript や VBScript、およびコンテンツ内に直接記載しているスクリプト)

特に jQuery などのライブラリを利用している場合、当該ライブラリを読み込むだけでメモリ使用量が増加するため (ライブラリ内の処理が非常に複雑であることに起因します)、ライブラリを利用しない構成でも再現するかどうかご確認ください。

問題の発生ポイントが特定できた場合、どのようにコンテンツを改修するのかという調査を進めることになります。

こちらも併せてご確認ください。

今日からできる!再現サンプルを作成しよう!
https://social.msdn.microsoft.com/Forums/ja-JP/d8f42bcc-ac3a-4978-ab19-10b0ea118067?forum=edgeiesupportteamja

少しでも問題解決のお役に立ちましたら幸いです。

なお、本ブログは弊社の公式見解ではなく、予告なく変更される場合があります。
もし公式な見解が必要な場合は、弊社ドキュメント (https://docs.microsoft.com/ や https://support.microsoft.com) をご参照いただく、もしくは私共サポートまでお問い合わせください。