メモリその3

GUIを前提としたWindowsの場合、原則として全てのProcessがWindowを持つことになる(*1)。そうなると、「全てのWindowに対してEventを送る」といった作業を行った場合、そのプロセスがSWAP Outしていると、そのProcessを一度In Swapするまでイベントが完了しないことになる。もっと面倒なのは、Window Applicationの場合である。例えばあるWindow Applicationを開いたまま放置した場合を考えよう。まったく動きがなければ、そのProcessはSwap outすることが望ましい。が、Windowを残したままProcessをSwap outしたら、例えばマウスポインタが通過しただけでSwap inの操作を行わねばならず、非現実的である。

では、最小化したWindowのProcessだけを対象にするか、というとこれまた難しい。最小化されてタスクバーに残っただけの状態でクリックされたら、すぐさまSwap inする必要があり、この間画面の更新が止まることになる。ではいっそタスクバーから消したら...というと、今度はSwap inする方法がなくなってしまう。要するにInteractive UIを前提とした環境では、Swap in/outの様に負荷が大きな作業は不向きという事だ。このあたりが、根本的にSwap in/outをシステムから省いてしまった理由ではないかと筆者は考えている。

ただ潜在的には、Swapの仕組みはアプリケーションの起動には効果的である。最近だとWindows VistaのReadyDriveなどが、よく使うアプリケーションをFlash Memoryにキャッシュすることで、HDDから読み出すよりも高速に起動できるようになる、なんて話があったが、これはあくまでもアプリケーションをFile Imageの形でキャッシングするだけだから、毎回起動時にはProcess生成 → ProcessのMemory確保 → File Imageをロード → File Imageを展開 → StackやらHeapやらを設定といった作業を伴う事になる。

これをもっと高速化しよう、ということでEmacsを初めとするUNIX系アプリケーションで見かける技が、Memory Dumpである。Emacsの場合、インストールの過程で強制的にMemory Dumpを取る(*2)。これはどういう仕組みかというと、要は素のEmacsの場合、立ち上げ時にLispファイル群を大量に読み込む必要があり、これを毎回やっていると無駄にCPUやHDDのアクセスコストを費やすことになる。そこで一度Emacsを立ち上げ、Lispファイル群を読み込み終わった直後に、そのProcessを強制的にCore Dumpしてしまう。するとEmacs本体+Lispファイル群を読み込んだイメージがDumpファイルの中に展開されているわけで、以後はこれを直接読み込んでMemoryに展開してしまうことで、高速に立ち上げが出来るという方法だ。これを使うと原理的にEmacsそのものよりもファイルサイズは肥大化する(Memory Imageをそのまま展開する形になるから当然だろう)

さて話をSwapに戻すが、Swap outというのはこの場合、Emacsの初期化でProcessの持つMemory Imageをそのままファイルに展開することと全く同じだし、Swap inは逆にファイルからProcessのMemory Imageを読み込んで展開するわけで、うまく使うと高速起動に役に立ちそうな仕組みである事はご理解いただけよう。「だったら初めからProcess Imageを展開するようなLoadable File Formatを作ればいいじゃないか」と言われればその通りだが、512MBメモリの環境でWindows Vistaをかつかつで使っているユーザーと、4GB Memoryを積んでWindows XPなり2000なりを使っているユーザーで、同じようなProcess Imageを展開するというのは実際には無理に近い(*3)。実際にどういうProcess Imageになるのかというのはそれこそユーザー毎、もっと言えば時間毎にすら異なる。当初は512MB Memoryで使っていたが、やっぱり不自由なのでMemoryを1GBなり2GBに増設しました、となるとその前後でProcessがMappingできる物理メモリの量は変わってくるし、その場合はやっぱりMemory Imageを作り直すのが現実的だからだ。そこで、Swapの様に動的にMemory ImageのLoad/Saveを行える仕組みがあれば、確実に有用と言える。

ただ、これは本来のSWAPの使い方からやや外れる上、「一度Swap inしたものは、もうSwapfileには残らない」というあたりがキャッシュの効果を削いでいる訳で、逆に「Swap inした後でもProcessのImageがSwapfileに残る」なんてインプリメントをしたら、これは既にSwapでは無い。そんなあたりで、Swapそのものは外すという決断になったのは不思議ではない。Memory Imageのロードについては、特にMicrosoftがPC98に向けてOn Nowを提唱していた頃は色々検討していたようだが、最終的に入らなかったのは、当時のPCのリソースでこれを実現するのには無駄が多すぎるという判断だったのではないか、と筆者は考えている。

(*1) 勿論ServiceとかWin32 Console Applicationでは「見かけ上」Windowは持たない。ただそのままだとEventとかの取り扱いが不便(Win32環境では、原則として全てのEventなりMessageなりはWindowに対して行われる)なので、Window Handleを取り扱えるようにすることが可能になっている。

(*2) 後でDumpを取り直すこともできる。このために、dump-emacsというFunctionも用意されている。

(*3) 余程小さなMemoryしか使わないProgramであれば可能かもしれないが、この場合は普通にProgram Imageを展開するのとMemory Imageを展開するのでさして差はないだろう。