ユーザープロセスが利用可能な仮想メモリ空間を通常の2GBから4GBに拡張する起動オプション、「/3GB」について、実際にその効果がどういう風に現れるのかをしらべることに。残念ながら、詳しいメモリマップとかを読み取る能力は無いので、実際に大量にメモリを確保しそうな簡単アプリを作り、どこまで確保できるかで競ってみることにした。
具体的な設定方法等については、以下のKBが役に立つと思います。
- 4 GB RAM チューニング機能と物理アドレス拡張のスイッチの説明
- http://support.microsoft.com/kb/291988/ja
テストに使ったアプリは、入力されたサイズのInteger配列を確保すると言うだけのもの。本当は動かしながらいろいろ調整出来るようにしようかと思って、実際の確保処理を別のスレッドで行い、外側から制御、とか思ったけれど、面倒なので作りっぱなし、確保しっぱなしということで。設定して確保してみてエラーがでたらNGというアホみたいなアプリ。その後、さすがに不便だったので強制的にガベージコレクトさせるボタンを作って連続検証が出来るようにしましたが、それでもメモリ解放に若干時間がかかるので、連打とかやられたらアウトです。
で、物理メモリ6GBを搭載した、Windows Server 2003 R2 Enterprise SP2(32bit)を用意し、実際にテストアプリを実行、確保サイズを変えながら上限値を調べたところ、配列サイズが289,405,938のポイントが限界だった。次に、このアプリに下記エントリーで書いた/LARGEADDRESSAWARE フラグを EDITBINで設定したものを用意...ってこれVB.NETとかで普通に作ったアプリはダメ??
一応、一応サーバーの起動オプションを以下のように変更、再起動して再度試してみる。
[boot loader] timeout=30 default=multi(0)disk(0)rdisk(0)partition(2)\WINDOWS [operating systems] multi(0)disk(0)rdisk(0)partition(2)\WINDOWS="Windows Server 2003, Enterprise" /noexecute=optout /fastdetect /3GB
ダメだ。同じサイズでエラーが出る。
/LARGEADDRESSAWARE フラグが設定できていないか出来ないものなのかと調べてみたら、基本はVC++などのリンク時に行う処理で、VC++の場合はVisual Studioから設定可能らしい。だけどC#とかではEditbin.exeによる「post-build」ステップで処置するしかないという記述が下記ページにあった。
- Setting LARGEADRESSAWARE with macro
- http://www.msnewsgroups.net/group/microsoft.public.dotnet.languages.csharp/topic1221.aspx
加えて、この記述がもしかして今回の「あほなテストアプリ」でダメだった理由だろうか?
Another anoying thing with the 4Gb Ram tuning is that you never get a larger chunk than what you get without the 4Gb.
要するに、フラグメンテーション(分断化)が発生するので、巨大なメモリ領域の固まりを確保しようとするならば、4GT設定を行っても意味無いよ、と。であればバラバラならOKか?
というわけで、またしてもアホみたいなテストアプリを改造し、指定された数を3分割して、3つのInteger配列を作るようにしてみたところ、3GBのメモリを積んだWindowsXPマシンで、改造前は最大配列サイズが「178,256,882」だったのが、詳細はまだ分からないけれどとりあえず「195,000,000」までは作れるようになった。これで改めて試してみようか。
...うまくいった。こんなの知ってる人にはアホみたいな内容かもしれないけれど、一応まとめておこうか。
- 1アプリが利用できるメモリの領域は、Windowsの起動オプションに/3GBを付けることで通常の2GBから3GBに拡張できる。
- この拡張を利用するには、アプリが/LARGEADDRESSAWAREフラグを設定した状態でリンクされている必要がある。
- C#やVB.NETの場合、/LARGEADDRESSAWAREフラグはEditbin.exeを使って後付けで設定可能。
- /3GBオプションで利用可能領域を3GBまで増やしたとしても、1つの大きな固まりとして3GBのデータを保持できるわけではない。実際には分断されたりして確保できない(プロセストータルとして使える領域であって、1つのデータや論理的な塊の上限サイズではない)。
- /PAEオプションで16GB以上の物理メモリを使おうとする場合は、システム用に仮想アドレス空間が2GB必要になるため、/3GBオプションを外さないといけない(Windows Server 2003 Enterprise/DatacenterのService Pack 2ではこの制限は無い)。
最後の件についてはコメントでの指摘ありがとうございます(修正: '08-12-10)。詳細は http://msdn.microsoft.com/en-us/library/aa366778(VS.85).aspx にある「Physical Memory Limits: Windows Server 2003」に記載があります。
面白いことに、何もしない場合のInteger配列のサイズは約289万が上限。/3GBオプション+/LARGEADDRESSAWAREで拡張した場合は約427万が上限で、だいたい1.5倍になっていた。確かに利用可能領域はメモリサイズに比例して増えているようだ。
ってなわけで。次は/PAEオプションを使ってAWEを使って見る実験かな。これは出来ないかもしれない。