Plack::Middleware::Profiler::NYTProfでプロファイリング

PlackアプリをプロファイリングするモジュールPlack::Middleware::Profiler::NYTProfを更新しました。
https://github.com/dann/p5-plack-middleware-profiler-nytprof

bayashiさんにパッチをもらって、負荷テスト環境などでも使えるようになりました。ある一定の負荷がかかった環境でしか性能問題がおきないといったケースはよくあるので、負荷テスト環境で、少し負荷をかけた状態で詳細なプロファイリングをしたい場合などに使ってみてください。

プロファリングのオーバーヘッドと負荷を減らすために、サンプリング、プロファイリング対象の限定、レポート機能のoffの3点の機能を追加しています。

サンプリング

全部のプロセスに負荷をかけるのではなく、対象をenable_profileというcallbackで、条件によってプロファイリングを有効にすることができます。特定のプロセスや何回かに1回プロファイリングするなどでサンプリングしながら、プロファイリングするのがおすすめです。

プロファイリング対象の限定

NYTProfは、PerlVMをhookして測定しているので、オーバーヘッドが他のプロファイラより小さくなっています。
ただ、それでもプロファイリングするレベルがstatementレベルなどと小さいとオーバーヘッドは大きくなってしまいます。
そこで、以下のDevel::NYTProfの文書に書いてあるように、プロダクション環境ではプロファイル対象を限定するのがおすすめです。

http://search.cpan.org/~timb/Devel-NYTProf/lib/Devel/NYTProf.pm#MAKING_NYTPROF_FASTER

これは、env_nytprofにblocks=0, slowops=0などを追加することで実現します。

HTMLレポートの出力をしない

これは単純に元々が開発環境用を目的に作られた機能なので、デフォルトがオンになっているのをオフにできる機能を用意したというだけのことです。負荷テスト環境では、HTMLレポートをそのまま生成するのではなく、NYTProfのプロファイリング結果だけを出力して、後でみられるようにすればよく、HTMLレポートはoffにしておかないといけません。
これは、enable_reporting optionを0に設定することで実現します。

設定のサンプル

まとめると、例えば以下のような設定で使います。

use Mojolicious::Lite;
use Plack::Builder;

get '/' => 'index';

builder {
  enable "Profiler::NYTProf",
    env_nytprof          => 'start=no:addpid=0:blocks=0:slowops=0:file=/tmp/nytprof.out',
    profiling_result_dir => sub { '/tmp' },
    enable_reporting     => 0,
    enable_profile       => sub { $$ % 2 == 0 }
    ;
 
  app->start;
};

__DATA__

@@ index.html.ep
<html><body>Hello World</body></html>

Enjoy!

#元々は開発環境で使うことを想定して、Plack Hackathonhttp://dann.g.hatena.ne.jp/dann/20091129/p1)で3年前につくったものですが、こうしてまた使われるというのも嬉しいものです。bayashiさん、ありがとうございました!