CoW 要点まとめ ============== {{tag: perl, performance}} 共有メモリを上手につかってアプリのパフォーマンスを向上させる ------------------------------------------------------------ {{TOC 3-}} ### CoW とは **CoW** = Copy-On-Write [ {{wikipedia: CoW}} - Wikipedia ] > プロセスのコピーを作成 (fork) するとき、書き換えることのないメモリページは、両方のプロセス(元のプロセスと生成されたプロセス)で共用し、書き換える可能性のあるメモリページは、新たなメモリページを割り当ててコピーを作成する ### 鉄則 fork するプロセスを生成する場合、親子間でメモリ共有した方が良い 1. forkする前に確保したメモリ領域は子プロセスとの間で共有される 1. 共有されたメモリ領域に対して書き込みを行うと共有は解除(コピー)される 1. forkした後に確保したメモリ領域は子プロセスごとに確保される(共有されない) どのプロセスでも同じように参照するだけの(書き換えない)データは、fork前に確保して共有した方が全体でのメモリ使用量を小さく保てる。つまり、fork 数を多くしたりできる。そして、処理数を上げることができる。 ### メモリ共有の確認 あるプロセスのメモリマッピング状態を見るには `cat /proc/$PID/smaps | head` すれば良い * Shared_Clean と Shared_Dirty の合計が共有メモリ量 * Private_* の項目がそのプロセスだけのメモリ * Perl だと {{cpan: Linux::Smaps}} が便利 * シンプルに子プロセスのなかで `ref $foo` してみてそれぞれアドレスが同じか見る ### Plack App の場合 * {{cpan: Plack}} アプリなら、master プロセスで全部 use したり require したりする * 遅延ロードされるものも親で use するべし #### 遅延ロードされるモジュールを調べる #### ##### Plack アプリの場合 ##### * {{cpan: Plack::Middleware::Debug::LazyLoadModules}} を使って遅延ロードされるモジュールを見つける * たとえば、{{cpan: starman}} なら `--preload-app` オプションを活用する * 個人的には `-M` で全部根こそぎ読むようにしている ##### mod_perl の場合 ##### 以下のようなモジュールを利用する package INCdiff; # 親で init しておいて、ケツで handler 呼ぶ use strict; use Apache::Constants qw(OK); use vars qw(%init_module); sub init { $init_module{$_}++ for keys %INC; } sub handler { my @required = grep { !$init_module{$_} } keys %INC; warn "-------- module diff ---------"; warn join "\n", @required; return OK; } 1; ### TIPS #### starman の CoW っぷりを調べるスクリプト #### {{gist: 823476}} 実行結果はこんな感じ !!sh!! $ ./check_starman_cow.pl PID TYPE RSS SHARED 3418 master 17732 13692 (77%) 3419 worker 20736 12996 (62%) 3420 worker 20740 13000 (62%) 3421 worker 20736 12996 (62%) * Perl モジュールの個別メモリ使用量は {{cpan: GTop}} で調べられる ### SEE ALSO * [[http://old.typemiss.net/blog/kounoike/20060202-61 Perl:forkしたプロセス間でのメモリ領域の共有]] * [[http://d.hatena.ne.jp/naoya/20080212/1202830671 Linux のプロセスが Copy on Write で共有しているメモリのサイズを調べる]] * [[http://d.hatena.ne.jp/hideden/20080409/1207740439 mod_perlで親プロセスとのCopy on Writeな共有メモリを増やす方法。]] * [[http://iandeth.dyndns.org/mt/ian/archives/000624.html モジュールをuseした際のメモリ使用量(増加量)を調べてみる]]