Loosely-Coupled IE (LCIE)とTabProcGrowthとセッションについて

IE8ではLCIEという機能があります。
要はタブごとプロセスを分けることでプラグインの影響を最小限にします。ただし分けすぎてもメモリを食うので分けすぎないように動いてくれます。

IE8 と Loosely-Coupled IE (LCIE)
Opening a New Tab may launch a New Process with Internet Explorer 8.0
Clicking on the blue “e” in taskbar does not launch a new process in IE8

MSDNの記事はIEで保持しているオブジェクトがどーなっているかの図があって、
IEBlog/AskIE!の記事はレジストリ設定によってタブプロセス、フレームプロセスがどのような規則で別になるのかが書かれてあります。


InternetExplorerはLCIE導入によるデメリットを最小限にする努力はされていますが、問題点も発生しています。
・VisualStudioのブレークポイントが効かない。
・いくつかのプラグインが動作しない(IE7Pro等)。
・window.focus()がSetForegroundWindowの制限に引っ掛かることがある。


これらはレジストリTabProcGrowthを設定することで解除可能です。


が、


これからもお世話になるかもしれない機能であるため、もう少し掘り下げてみました。

タブプロセスとは、フレームプロセスとは

まず、「タブ」「タブプロセス」「フレーム」「フレームプロセス」を分けて考えることが必要です。
「タブ」と「フレーム」は見た目の部分、「タブプロセス」「フレームプロセス」とはWindowsでいうプロセスのこと。
どれがフレームプロセスか、どれがタブプロセスかを再整理をするために、ProcessExplorerSpy++で見ていきます。
※一律保護モードOFF(というかXPなので)


まずは、IEを全て閉じた状態で1つだけ新たなブラウザを立ち上げると以下のように出ます。


iexplore.exeが2つ存在し、親になっているのがフレームプロセスです。
WindowsというOSはあまりプロセスの親子関係は気にしないのですが、
IE8はコマンドライン引数を見る限りなにやら気にするようです。(詳細はこちら

起動済みのInternetExplorerのJavaScriptプログラムにブレークポイントをかけたい場合は、タブプロセス側にアタッチする必要があります(開発者ツールならその必要性はありませんが)。



フレームプロセス、タブプロセスのウィンドウとの関係はココにも書いてありますが、



となっていました。
「お気に入り(FavoritesBar)」「コマンドバー(CommandBar)」はフレームプロセスですが、「メニューバー」「Googleツールバー」はタブプロセスになっていました。
タブプロセスの吹き出しの部分は、タブが異なるとプロセスが異なることがあります。
もちろん、フレームプロセスとタブプロセスは別プロセスです。
タブごとにプロセスが異なっていたとしても、実際はツールバーJavaScriptオブジェクトは1つしかいません。


この状態のウィンドウハンドルの階層とプロセスの関係をSpy++で確認した所、以下のようになっていました。


次に、タブを増やしていくと以下のようになりました。


真ん中の3つがタブプロセスです。
タブプロセスが分かれる規則は、
Opening a New Tab may launch a New Process with Internet Explorer 8.0
にあるように空きメモリや現在のタブの数、整合性レベル、明示的に別セッション(Cookieの方)にしたいかで変わります。
私の環境の場合は、タブ3つだとタブプロセスが3つ。タブ4つ目はタブプロセスは増えない(1つ目のものを使いまわし)。以降緩やかにプロセス増加はしにくくなる。という動作でした。時によっても変わるでしょう。
なお、色が茶色いのは、Windowsの「ジョブ」と呼ばれるOSの機能の1つで、複数プロセスをグルーピングして一元管理したり相互通信するのに使用する機能です。タブプロセス同士がグループ化されてることが見て取れます。



次は、ウィンドウです。
一度IEをすべて閉じて、デスクトップのIEアイコンにて、IEを”2つ”起動します。ウィンドウが2つ表示されます。

先ほどと異なるのは、タブを増やしたのではなく、ウィンドウを増やしました。
にもかかわらず、タブプロセスしか増えませんでした。
これはフレーム結合(FrameMerging)が行われたためです。そのためフレームプロセスが1つのままになっています。
この場合、セッションCookieは共有されます。
メニューバーからの「新規ウィンドウ(CTRL+N)」や「window.open」でも同様です。



今度は、セッションを2つの場合を確認です。
一度IEをすべて閉じて、IEを1つ起動後に、「新規セッション」でIEをさらにもう1つ起動します。

先ほどと異なるのは、起動の仕方の違いです。ウィンドウの数は同じく2つです。
フレームプロセスが2つ、タブプロセス2つあります。吹き出しコメントが「新規セッション」で増えたプロセスです。
フレームプロセスか、タブプロセスかはコマンドライン引数を見れば分かります。
後で増やしたウィンドウは-noframemerging、-sessionmergingオプションが付与された状態で起動されています。
この場合、セッションCookieは共有されません。


セッションについて

IE8でセッション引き継ぎ条件も変わりました。
というより、フレームプロセスのマージ有無が変わったため条件が変わったように見えるだけのようですが。
画面UI上のどのボタンを押したらセッションはどうなるのかがあまり語られていない気がしたので、
まとめてみました(机上確認も含んじゃっていますが)。
注意したいのは、ウィンドウの起動の仕方によってセッションが共有されるかどうかが変わります(IE6,7でも同様ですが)。
例えば、Aタグのtarget=_blankのときと、デスクトップのIEアイコンをクリックでは異なる場合があります。

セッションを実現するにあたり、各種方法がありますが、ここではセッションCookieとsessionStorageに話を絞ります。セッションCookieとはexpires指定なし、永続Cookieとはexpires指定ありのCookieです。

空白は未調査。
レジストリ設定(TabProcGrowth)はデフォルト状態の定義なし状態で確認しています(つまりContext-based)。

操作内容 新規ウィンドウは起動元ウィンドウとは別のフレームプロセスか? 新規タブは起動元タブとは別のタブプロセスか?(可能性があるか?) セッションCookieは起動元ウィンドウ/タブとは別か? sessionStorageは起動元ウィンドウ/タブとは別か? 永続Cookie・localStorageは起動元ウィンドウ/タブとは別か?
新しいタブ(CTRL+T)
タブを複製(CTRL+K)
- 同じ 同じ
AタグをCTRL+クリック - 同じ コピーされた別もの(※2) 同じ
新規ウィンドウ(CTRL+N) 同じ - 同じ 同じ
新規セッション - 同じ
デスクトップのIEアイコンで起動
スタートメニューのIEアイコンで起動
ファイル名を指定して実行で「iexplore」
同じ(※1) - 同じ(※1) 同じ
window.open()
Aタグのtarget=_blank
SHIFT+クリック
同じ - 同じ コピーされた別もの(※2) 同じ
showModalDialog()
showModelessDialog()
  - 同じ 同じ 同じ
iframe/frameset/frame 同じ - 同じ 同じ 同じ
WSHからCreateObject("InternetExplorer") -    
ファイルエクスプローラーからのURL投入   -    


※1:VSのブレークポイントを有効にするために、TabProcGrowthを0にしていると、IE7と同じくセッションは共有されなくなります(また、フレームプロセスとタブプロセスは1つのプロセスになります)。
なお、TabProcGrowthを設定していなくても、セッションが共有されないことがあります(後述)。

※2:http://d.hatena.ne.jp/Syunpei/20090804/1249375857
   IE8 の セッション Cookie と sessionStorage



上記表のとおり、「タブを複製」は手元のマシンでは、セッションCookieは起動元ウィンドウと共有されますが、sessionStorageは起動元タブから引き継がれず新規タブでは空の状態となっていました(コピーもされない)。
このケースは、個人的には、消えるのではなく起動元タブからコピーされた別ものでもよいとも思っています。HTML5での指摘内容には該当しないと考えているためです(複製の意味をユーザがどのように捉えるのか次第かなと)
「window.open」の場合ですと、セッションCookieは同じく共有されますが、sessionStorageは値のコピーが行われ起動元ウィンドウとは別となっていました。



TabProcGrowth設定は、セッションへの影響もあります。値の意味はココにある通りですが、セッションについて補足すると、

0
タブプロセスとフレームプロセスが1つのプロセスになる。タブが増えてもタブプロセスが増えない。また、上に書いたように「デスクトップのIEアイコンで起動」時にセッション(Cookeie)が分かれるようになります。また、frames are not unified across MIC levels.です。
1
タブプロセスとフレームプロセスが1つづつになる(合計2つ)。タブが増えてもタブプロセスが増えない。「デスクトップのIEアイコンで起動」時にセッション(Cookie)は分かれない。all tabs for a given frame process run in a single tab process for a given MIC level.

上でTabProcGrowthを設定していなくても、セッションが共有されずに、別になってしまうことがあると書きました。フレームプロセスが別プロセスになってしまうためのようです。
なることが確認出来ているのは現在2つ。
IE起動→「新規セッション」→起動元ウィンドウを閉じる→IE起動
IE起動→ファイルエクスプローラーからIE起動

起動元プロセス単位でフレームプロセスをマージしているのでしょうか?
このことは、頭に留めておくとよいかもと思っています。

レジストリFrameMergingとSessionMergingについて

FrameMergingとは何と何をどのようなタイミングでマージするのかがIE8 の "フレーム結合" を抑止するを見てもいまひとつ分からなかったため、調査しました。


FrameMergingはデフォルト1(有効)。
デスクトップのIEボタンをクリックして立ち上げたときに、別ウィンドウになりますが、そのウィンドウと既存のウィンドウを結合するかどうかという指定。
結合した場合、フレームプロセスが共有されるが、セッションも共有される。
フレームプロセスとタブプロセスは別プロセスのままです(なので、VSのブレークポイントを有効にするための対策にはならないハズ)。
たとえ1(有効)であっても、メニューの「新規セッション」を選択などで、明示的に別セッションで立ち上げる場合は、フレームプロセスは別になり、セッションも別になります。
値を0(無効)にした場合、ウィンドウごとに別プロセス(ウィンドウ単位でフレームプロセス+タブプロセスが出来る)になる。

「新規ウィンドウ」やwindow.open時はこの設定には影響しない。
つまりマージしない設定(0)にしてもマージされるままです。
http://mp.i-revo.jp/user.php/hcflzamg/entry/1952.html
セッションCookieが共有される単位は、フレームプロセス単位であることはこのレジストリを弄っても変わらないし、IE7から変わっていないと考えています。


(SessionMergingはおいおい調査)