必要最小ワーキングセット

あるプロセスの物理メモリ最大使用量を測定するというお話.『Cozy Ozy』より.

GetProcessMemoryInfoというAPIはどうかと思い、このようなコードを書いてみた。

最大の問題は,消費メモリ量をどう定義するか,ということかもしれません.
例えば 16*1024*1024 個の整数配列をソートすることを考えてみましょう.この作業,一見 64 MB 近い物理メモリが必要な気がしますが,実際にはデータを 64 MB のファイルに書き出して,それをちまちま読み書きしながらソートすればもっと少ないメモリで完走できそうです.
Windows 環境に限定して考えると,これは別にファイル I/O API を使う必要すらありません.64 MB のファイルをメモリ空間にマップして,必要な箇所だけ物理メモリを割り当てていけば,元のソートアルゴリズムをあまり変更せずに済みそうです.
さらに言えば,VirtualAlloc でメモリを確保するということはページファイルの一部をメモリマップすることに他なりませんから,自分でファイルを作る必要もありません.VirtualAlloc でメモリを確保する一方で,ソートアルゴリズムのあちこちに SetProcessWorkingSetSize API を仕込んでワーキングセットの縮小を行えば,あからさまに怪しいデータファイルとメモリマップ API をも排除することができます.
結局,VirtualAlloc と SetProcessWorkingSetSize だけで,「ファイルにデータを書き出して,それをちまちま読み書きしながらソートする」ことを実現することができます.
さらにさらに,SetProcessWorkingSetSize は別プロセスに対してもワーキングセットの縮小を指定することができますので,ソートを行うプロセスから切り出してしまうことができます.別プロセスからこっそりワーキングセットの縮小を指示するような共犯者を作ってしまえば,元のソースコードだけを見て「必要最小物理メモリ」を判断するのはほとんど不可能,というか行為そのものの意味が消失しかねないでしょう.
というわけで試してみましたが(ただし別プロセスから SetProcessWorkingSetSize を呼ぶというのは面倒なのでパス),ファイル I/O を一切使うことなく,16*1024*1024 個の整数配列を 1 MB ちょっとの PeakWorkingSetSize でソートできました.まあ実際には物理メモリは余りまくっているので,ページファイルに書き出されることなくスタンバイリストとワーキングセットを行ったり来たりしているだけでしょう.それでも原理上は 1 MB ちょっとの物理メモリしか余っていない環境でも動いてくれるんじゃないでしょうかね.
へう゛ぉいコードですが,一応このあたりに置いておきます.
http://www.dwahan.net/nyaruru/hatena/QSMem.zip



となると「 (タスクマネージャの) 仮想メモリ サイズ」を監視しよう,ということになりそうですが,アレはアレでページファイルじゃなくて通常のファイルをメモリマップした場合には増えないので,自前で 400 MB ぐらいのファイルを作ってメモリマップすれば,こんどは「省仮想メモリサイズ プログラミング」なんてのが可能です.id:NyaRuRu:20051022#p7 の Process Explorer に表示されている「Private Bytes」がタスクマネージャの「仮想メモリ サイズ」に相当します.

ウィンドウ最小化時のワーキングセット縮小 : Vista 編

先日某烏丸オフィスで遊んでいるときに気づいたのですが,Windows Vista ではウィンドウ最小化時のワーキングセット縮小動作に変更が行われたようです.
関連話題.

環境や該当アプリケーションのアクセスパターンなどで変化する可能性があることは注意しておいて欲しいわけですが (つまり、ワーキングセット縮小が行われなくなったと思いこむのも危険) 少なくとも手元の環境では,ワーキングセットの縮小はほとんど行われないかごくわずかでした.
せっかくなので,config.trim_on_minimize = true の Firefox 1.5.0.4 Windows 版で実験してみたものです.

初期状態 ワーキングセット 70 MB
最小化後 ワーキングセット 69 MB

とまあほとんど減りません.
みんなだいすき「FirefoxやThunderbirdのメモリ消費量を劇的に減らす方法」Vista では使えなくなってしまいそうです.
http://b.hatena.ne.jp/entry/http://gigazine.net/index.php?/news/comments/20060415_firefoxthunderbird/:image:large
というのは冗談としても,久しぶりのクライアント向け OS メジャーアップデートで,メモリやディスク I/O まわりのアルゴリズムが,ちゃんと今風の数字にチューンされていると感じられるのは嬉しいですね.



おまけ.
そんなに減らしたいなら外から SetProcessWorkingSetSize 呼んでやりましょうと.以下 C# で作ってみた使い捨てアプリにて SetProcessWorkingSetSize を呼んでみるの図.

初期状態 ワーキングセット 70 MB
Start Trimming 押下直後 400 KB*1

ソースはこちら.
http://www.dwahan.net/nyaruru/hatena/MyTrimmer.zip

*1:実際には Update するともう少し増えている

.NET&Windows Vistaへ広がるDirectXの世界 〜 第1回 DirectXの真実

"@IT .NET&Windows Vistaへ広がるDirectXの世界 〜 第1回 DirectXの真実"
http://www.atmarkit.co.jp/fdotnet/directxworld/directxworld01/directxworld01_01.html:image:large
色々ご迷惑をおかけしつつ何とか公開.
何か書いては消し書いては消しでこの 5 倍ぐらい文章書いていた気がします.
他にも記事を書くにあたって,全然知らなかった実行バッファ時代が気になって,実際に DirectX 2 でポリゴン描画させてみたらちゃんと動いて感動した,とか.