Perl:forkしたプロセス間でのメモリ領域の共有 (Link: 遅レス。 - Apache + mod_perl - MaxClients の値に注意)

|
遅レス。 - Apache + mod_perl - MaxClients の値に注意 共有されてるメモリ領域は/proc/$pid/smapsで取れます。Linux::Smapsを使うとプロセス全体での合計が見れたりして便利です。 Linux::Smapsの例を見るとLinuxのcopy on writeで共有されている様子が分かりやすいです。Apache + mod_perlやFastCGIで大量にforkするときには注意が必要ですね。 大雑把に言うと以下のようになります。
  • forkする前に確保したメモリ領域は共有される→shared_dirtyになる
  • forkした後にその領域に書き込みを行うとコピーされる→private_dirtyになる
  • forkした後に確保した領域は共有されない(当たり前)→shared/privateにならない(多分)
sharedに入ってる間は実際のメモリは消費されることが無く,privateになるときに改めて確保されるみたいです。ちなみに,clean/dirtyはLinux::Smapsのドキュメントに「dirty pages are written to in RAM but not to the corresponding file.」だそうです。「ファイルとメモリ上のデータが違ってるのがdirty page」ということでしょうか。多分。 更にこのスクリプトをいじってモジュールのrequireをforkの前にやったときと後にやったときで比べてみると,forkの前にrequireしておけば共有されていることが確認できます。httpd.confでPerlRequire/PerlModuleするかstartup.plの類でuseしておくことで,fork前にモジュールをロードし,共有することが可能なのかもしれません。(未確認) この問題は,FastCGIを使ってlighttpdなりApacheなりにプロセス管理をやらせるときにも発生するようです。 lighttpdから複数プロセスを起動した場合の子プロセスのsmapsは以下のようになりました。
 
08048000-08157000 r-xp 00000000 fe:02 25775283   /usr/bin/perl5.8.7
Size:              1084 kB
Rss:                972 kB
Shared_Clean:       972 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:        0 kB
08157000-08161000 rw-p 0010e000 fe:02 25775283   /usr/bin/perl5.8.7
Size:                40 kB
Rss:                 40 kB
Shared_Clean:        28 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:       12 kB
08161000-089e4000 rw-p 08161000 00:00 0          [heap]
Size:              8716 kB
Rss:               8584 kB
Shared_Clean:         0 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:     8584 kB
b7cae000-b7cbb000 r-xp 00000000 fe:02 8512484    /usr/lib/perl5/vendor_perl/5.8.
7/i686-linux-thread-multi/auto/FCGI/FCGI.so
Size:                52 kB
...
 
一方で,testapp_fastcgiから複数起動した場合の子プロセスのsmapsは以下のようになります。
 
08048000-08157000 r-xp 00000000 fe:02 25775283   /usr/bin/perl5.8.7
Size:              1084 kB
Rss:                432 kB
Shared_Clean:       432 kB
Shared_Dirty:         0 kB
Private_Clean:        0 kB
Private_Dirty:        0 kB
08157000-08161000 rw-p 0010e000 fe:02 25775283   /usr/bin/perl5.8.7
Size:                40 kB
Rss:                 40 kB
Shared_Clean:        28 kB
Shared_Dirty:         4 kB
Private_Clean:        0 kB
Private_Dirty:        8 kB
08161000-08a24000 rw-p 08161000 00:00 0          [heap]
Size:              8972 kB
Rss:               8924 kB
Shared_Clean:         0 kB
Shared_Dirty:      8640 kB
Private_Clean:        0 kB
Private_Dirty:      284 kB
b7d71000-b7d8e000 r-xp 00000000 fe:02 12653949   /usr/lib/perl5/5.8.7/i686-linux
-thread-multi/auto/POSIX/POSIX.so
Size:               116 kB
...
 
heapとついているセクションに注目して下さい。どちらもサイズは8-9MBですが,lighttpdから起動した場合はprivate_dirtyに,testapp_fastcgi.plから起動した場合はshared_dirtyに入っています。ヒープ領域ということは,mallocなどでの確保に使われる領域ですから,ロードしたモジュールなどがここに入っているのではないかと推測されます。 なお,/proc/$pid/smapsは比較的新しいkernelでないと存在しないようです。http://search.luky.org/linux-kernel.2005/msg33121.htmlで2.6.11.7に対するPATCHとして投稿されたもののようです。ということは元記事のスライドの時点では無かった訳で・・・どうやって調べてたのでしょうね。

Trackback URL for this post:

http://www.typemiss.net/trackback/61

カーネル2.6.11.7って

新し過ぎ! -babie