packageごとのメモリ使用量(と増分)を確認できる Plack::Middleware::MemoryUsage

packageごとのメモリ使用量とリクエストを処理する前後の増分を確認できるPlack::Middlewareを作りました。

時間が経つとぶくぶく太るプロセスがいるときに、犯人特定の助けになると思います。

要、B::TerseSizeB::Size2::Terse, Devel::Symdumpです。

新しめ(5.10以降?)のPerlでB::TerseSize (B::Size)がエラーになってインストールできないときは、

のを入れてください。

を入れてください。

使い方は、

  use Plack::Builder;
  builder {
      enable "MemoryUsage",
          callback => sub {
              my ($env, $res, $before, $after, $diff) = @_;
              my $worst_count = 5;
              for my $pkg (sort { $diff->{$b} <=> $diff->{$a} } keys %$diff) {
                  warn sprintf("%-32s %8d = %8d - %8d [KB]\n",
                               $pkg,
                               $diff->{$pkg}/1024,
                               $after->{$pkg}/1024,
                               $before->{$pkg}/1024,
                              );
                  last if --$worst_count <= 0;
              }
          };
        $app;
  };

な感じで、

  パッケージ名                         増分  req処理後  req処理前
  ====================================================================
  MemoryEater                         36864 =    36873 -        9 [KB]
  B::TerseSize                          191 =      645 -      453 [KB]
  B::AV                                  21 =       37 -       16 [KB]
  B::HV                                   4 =       18 -       14 [KB]
  B::NV                                   0 =        8 -        8 [KB]

な出力が得られます。MemoryUsageをenableするときは、builderの中で一番最初に指定して一番外側のMiddlewareとして処理されるようにした方がいいんでないかと思います。

DESCRIPTIONにも書きましたが、MemoryUsageをenableにすると、性能劣化が炸裂するので、開発環境でのみenableにするとか、本番環境でenableにするならPlack::Middleware::Conditionalを使ってある程度まびいた方がいいと思います。

  builder {
      ## 1/3の確率で enable
      enable_if { int(rand(3)) == 0 } "MemoryUsage",
          callback => sub {
          ...
  builder {
      ## リクエストヘッダに X-Memory-Usage があったときのみ enable
      enable_if { exists $_[0]->{HTTP_X_MEMORY_USAGE} } "MemoryUsage",
          callback => sub {
          ...

謝辞

Plack::Middleware::MemoryUsageは、[twitter:@fujiwara] さんのPlack::Middleware::GTop::ProcMemインスパイアです!!