Link: CLON - 2006/02/20 - lighttpd+fastcgi時のメモリ共有

| | |
CLON - 2006/02/20 - lighttpd+fastcgi時のメモリ共有 このパターンで実行すると親プロセスがlighttpdになっている以上,forkする元がlighttpdなので,共有されるはずがありません。WebプログラマのためのCopy On Write解説:mod_perl/FastCGIでメモリを節約する方法 | Typemiss.netに書いたとおりです。もうちょっとしっかり実験しておきましょう。 CoWでテンプレートキャッシュを共有!(C::V::H::T編) | Typemiss.netで使ったソースを流用して試してみましょう。前のエントリで10MBのテンプレートが上手にすれば共有キャッシュに入るということが分かっています。 ちょっと変えてnewの中でテンプレートのロードをするようにしてみたり。 package TestApp::V::HT; use strict; use base 'Catalyst::View::HTML::Template'; use NEXT; __PACKAGE__->config(   die_on_bad_params => 0, ); sub new {     my $class = shift;     my ($c, $config) = @_;     my %options = (             cache    => 1,             path     => [ $c->config->{root}, $c->config->{root} . '/base' ],     );     for( 0..999 ) {         my $t = HTML::Template->new( filename=>"$_.tmpl", %options, %$config );     }     $class->NEXT::new(@_); } 1;   さて,この状態でもう一度apacheのmod_perl環境下で共有に入っていることを確認しましょう。 $ GET http://localhost/smaps Pid:     7674 Size:             26172 kB Rss:           21500 kB  Shared_Clean:   2288 kB  Shared_Dirty:  16572 kB  Private_Clean:     0 kB  Private_Dirty:  2640 kB   shared_dirtyに入ってますね。全体としてはapacheの起動前後にfreeコマンドを実行することで20MBほどのメモリが消費されていることが確認できます。 # free                                                                total       used       free     shared    buffers     cached       Mem:        515248      74764     440484          0      12600      45208       -/+ buffers/cache:      16956     498292                                       Swap:       500464          0     500464                                       # /etc/init.d/apache2 start                             # free                                                                total       used       free     shared    buffers     cached       Mem:        515248      96860     418388          0      12656      45268       -/+ buffers/cache:      38936     476312                                       Swap:       500464          0     500464                                         lighttpd + max-procs => 10で試してみましょう。180MBほどのメモリが消費されています。また,起動時にtopを見ていると各プロセスがテンプレートを読み込むためにCPUを使いまくっている様子を見ることができます。 # free              total       used       free     shared    buffers     cached Mem:        515248      90200     425048          0      20664      49912 -/+ buffers/cache:      19624     495624 Swap:       500464          0     500464 # /etc/init.d/lighttpd start # free              total       used       free     shared    buffers     cached Mem:        515248     277332     237916          0      20736      49916 -/+ buffers/cache:     206680     308568 Swap:       500464          0     500464   top - 12:12:36 up  2:37,  2 users,  load average: 1.05, 1.40, 0.74 Tasks:  45 total,  11 running,  34 sleeping,   0 stopped,   0 zombie Cpu(s): 71.0% us, 29.0% sy,  0.0% ni,  0.0% id,  0.0% wa,  0.0% hi,  0.0% si Mem:    515248k total,   109276k used,   405972k free,    13360k buffers Swap:   500464k total,        0k used,   500464k free,    45220k cached   PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND  8464 lighttpd  18   0  7256 5540 1436 R 12.1  1.1   0:00.50 testapp_fastcgi  8465 lighttpd  18   0  7124 5336 1436 R 10.9  1.0   0:00.47 testapp_fastcgi  8469 lighttpd  18   0  6860 5112 1432 R 10.9  1.0   0:00.43 testapp_fastcgi  8470 lighttpd  18   0  6992 5232 1432 R 10.9  1.0   0:00.43 testapp_fastcgi  8472 lighttpd  18   0  6176 4452 1416 R 10.9  0.9   0:00.35 testapp_fastcgi  8467 lighttpd  18   0  6864 5140 1432 R 10.5  1.0   0:00.44 testapp_fastcgi  8468 lighttpd  18   0  6864 5136 1432 R 10.5  1.0   0:00.43 testapp_fastcgi  8471 lighttpd  18   0  6316 4608 1428 R 10.5  0.9   0:00.37 testapp_fastcgi  8466 lighttpd  18   0  6716 5000 1432 R 10.0  1.0   0:00.40 testapp_fastcgi   各プロセスで,テンプレートはもちろん,Perlのモジュールも共有されていないことが,smapsの出力からも分かります。Catalystのライブラリ全部が各プロセスごとにメモリ上に展開されているわけです。 $ GET http://localhost/smaps       Pid:     9959                                                   Size:             22304 kB                                     Rss:           20528 kB                                          Shared_Clean:   1672 kB                                        Shared_Dirty:      0 kB                                        Private_Clean:     0 kB                                        Private_Dirty: 18856 kB                                         fastcgi.plから10プロセスを起動して,lighttpdではexternal server(bin-pathを消す)として設定してみましょう。 $ script/testapp_fastcgi.pl -d -l :10021 -n 10 -p testapp.pid FastCGI daemon started (pid 10183)   ちゃんと共有されますし,20MB程度のメモリ消費で済みます。 $ GET http://localhost/smaps Pid:    10189 Size:             22564 kB Rss:           20224 kB  Shared_Clean:   1132 kB  Shared_Dirty:  16768 kB  Private_Clean:     0 kB  Private_Dirty:  2324 kB   # free                                                          total       used       free     shared    buffers     cached Mem:        515248      90896     424352          0      21572      49940 -/+ buffers/cache:      19384     495864                                   Swap:       500464          0     500464                                   # /etc/init.d/lighttpd start                       # free                                                          total       used       free     shared    buffers     cached Mem:        515248     114836     400412          0      21796      49968 -/+ buffers/cache:      43072     472176                                   Swap:       500464          0     500464                                     これがFCGI::ProcManagerのDESCRIPTIONに書いてある FCGI::ProcManager is used to serve as a FastCGI process manager. By re-implementing it in perl, developers can more finely tune performance in their web applications, and can take advantage of copy-on-write semantics prevalent in UNIX kernel process management. The process manager should be invoked before the caller''s request loop のcopy-on-writeの効果です。 追記: mod_fastcgiとmod_fcgidとlighttpd | Typemiss.netの追記にも書いたように,external serverとして実行しているときの方が,各リクエストごとの処理も高速だという結果もあります。こっちの方が良いことが多いですね。問題はFastCGIアプリの起動管理をどうするかですけど,-dでデーモン化して,-pでPIDファイルを作ってくれるので,どうとでもなりそうです。更には複数アプリを起動するなら自分でPerlでスクリプトを書いて,Catalyst関係のモジュールを読み込みまくってからforkしてしまえばモジュールが共有できたりして幸せになれるかもしれません。 それから,ApacheからFastCGI起動するときでも同じことです。親がapacheじゃ共有のしようがないです。

Trackback URL for this post:

http://old.typemiss.net/trackback/70