« 正確なタイミングでバウンダリスキャン | トップページ | ネットの商売にはいろんな思いがあるようだ »

2010.03.31

Windowsの物理メモリの使用状況

Windowsの物理メモリがどのように使われているかを調べてみました。
(本当に正しいかどうか怪しいですけど・・)

検証に使ったマシンは、メインメモリ2GBで、OSはWindowsXPです。

次の図は、OSが起動してからあまり時間が経っていないときに、mallocして確保したメモリが、物理メモリ上でどのアドレス(物理ページ)に配置されるかを図にしてみたものです。

16MBytesの領域をmallocで確保して物理ページを調べ、その後freeし、再びmallocして調べ・・ということを延々と繰り返しています。

なお、画面上の1ドットが1物理ページ(=4096バイト)に対応しています。一度使った点を消していないので、物理アドレス上のどの領域がどんなふうに使われていくかがわかります。

Pmem0_thumb
(クリックでアニメーションします。アニメーションGIFのサイズ3882kB)

Windowsが起動後間もないので、比較的連続して固まった領域を確保できています。

次は、起動してから少しだけ時間が経ったときの物理メモリ使用状況です。
Pmem1_thumb
(クリックでアニメーションします。アニメーションGIFのサイズ5054kB)

確保できている領域が少しだけばらけてきました。

最後に、起動してから十分に時間が経ったときのようすです。
mallocで取った16MBytesのメモリ領域は、物理メモリ上ではかなり断片化されて広大な範囲に確保されていることがわかります。
Pmem3_thumb
(クリックでアニメーションします。アニメーションGIFのサイズ6424kB)

まぁ、物理メモリ上でいくら断片化していようとも、アプリケーションから仮想メモリでアクセスする分にはTLB(PTE)が自動変換してくれるから、全く気にしなくてもいいんですけど、DMAをするには大事なことなので、調べてみました。

わかってきたのは、
・Windowsが起動してから時間が経つと、mallocで確保された領域はどんどんばらける傾向にある。
・mallocとfreeを繰り返すと、物理アドレスが大きくなる方向に確保されていく。
・物理アドレス0番地から、普通に使われている。
・mallocとfreeを繰り返すと、物理メモリのほとんどの領域は満遍なく使われるが、物理メモリ上で決して使われない領域がある。おそらく、非ページメモリに割り当てられた領域か、他のプログラムが使っていて開放していない領域と思われる。(32~160MBytes付近、512MBytes付近、最後の32MBytes付近)
・連続した領域が確保されやすい場所(最初の512MBytesあたりまで)と、確保されにくい場所(後半)といった傾向はある
・大きなサイズの連続した非ページ領域を確保するのって、結構大変なことなのかも。

ということでした。

このツールを作ってみたきっかけは、DMA用のデバイスドライバを作るために、MapTransferとかで苦労してスキャッタギャザリストを取得してみたら、MDLの中身と同じだったということで、図示してみたくなったということです。

Windowsのプログラミングでは、物理メモリは秘められた世界です。カーネルモードのプログラムでさえもメモリの物理アドレスを直接扱う機会はありません。そういうところを調べるのが好きです。

|

« 正確なタイミングでバウンダリスキャン | トップページ | ネットの商売にはいろんな思いがあるようだ »

コメント

興味深いデータありがとうございました。やはりというデータだと思います。
やはり、ページごとにピンダウンしてDMAでしょうか?
4Kbyte(64bitデータ幅で512個)バースト出来れば、かなり効率は良いのではないかと思います。

投稿: marsee | 2010.04.02 16:53

ピンダウンというのは、ページアウトできないようにロックする、という意味でしょうか?

DeviceIoControlでカーネルモードに移行する際に、DirectIoに指定したバッファは、IOマネージャによって自動的にロックされます。

ページごとに行なう(スキャッタギャザー)は、半分ソフトウェアでエミュレートする方式(ページ転送のたびに割り込みをかける)では、かなり遅くなると思います。

>ページごとにピンダウンしてDMAでしょうか?
比較してみないとわかりませんが、それよりも、共有バッファのほうがよさそうな感じです。

投稿: なひたふ | 2010.04.02 17:12

>ピンダウンというのは、ページアウトできないようにロックする、という意味でしょうか?
はい。それと、MMUの仮想アドレスと物理アドレスの対応を変えられないようにするのと、キャッシュをインバリデートすることだと思っています。

>ページごとに行なう(スキャッタギャザー)は、半分ソフトウェアでエミュレートする方式(ページ転送のたびに割り込みをかける)では、かなり遅くなると思います。
割り込みで終了を検知するのでは、遅くなりそうですね。うちでは、ポーリングで終了条件を見ていますが、別の解決策としては、(ご存知だとは思いますが)DMAコマンドをキューにしておいて、ページごとのDMAコマンドを溜め込んで置いて、全部終わったら割り込みをかけるという方法があると思います。

投稿: marsee | 2010.04.02 17:57

>キャッシュをインバリデートすることだと思っています。
x86 + Windowsの環境では、キャッシュは常に有効になっていて無効にすることができません。ただし、常にコヒーレンシが保たれるように動作するらしく、逆に不一致させるようにできないようなのです。
x86以外のアーキテクチャでは、DMA前にはキャッシュのフラッシュをしなければなりませんが、x86ではその関数は無効になっています。なので、x86+Windows環境でのキャッシュは気にしなくてもいいようです。

>ポーリングで終了条件を見ていますが、
ポーリングだと、CPUの処理時間を犠牲にしてしまいますが、場合によっては良い解決策かもしれませんね。
キューにためるのは回路が複雑になるのとのトレードオフなので、選択できるようにしたいですね。


投稿: なひたふ | 2010.04.03 00:02

コメントを書く



(ウェブ上には掲載しません)




« 正確なタイミングでバウンダリスキャン | トップページ | ネットの商売にはいろんな思いがあるようだ »