Skip to content

Instantly share code, notes, and snippets.

@bokutin
Created February 2, 2014 02:27
Show Gist options
  • Save bokutin/8762149 to your computer and use it in GitHub Desktop.
Save bokutin/8762149 to your computer and use it in GitHub Desktop.
Mason1のanonymous componentで妄想するためのベンチ
#!/usr/bin/env perl
use sanity qw(sane);
use Benchmark ":all";
use Data::Dumper;
use Data::Format::Pretty::Perl qw(format_pretty);
use Data::Section::Simple qw(get_data_section);
use File::Path qw(make_path);
use File::Spec::Functions qw(rel2abs);
use HTML::Mason;
use IO::All;
my $comps = get_data_section;
for my $file (keys %$comps) {
my $dir = $file =~ s{[^/]*$}{}r;
-d $dir or make_path($dir) or die $!;
io($file)->print($comps->{$file});
}
my @comp_names = sort grep !/fragment\//, map { s{.*bench/comps}{}r } keys %$comps;
my @interp_variants = (
{ enable_autoflush => 0, static_source => 0 },
{ enable_autoflush => 0, static_source => 1 },
{ enable_autoflush => 1, static_source => 0 }, # HTML::Mason's default
);
my $args = [
rows => [1..200],
cols => ["a".."f"],
];
my $memo = {};
my $count = 100;
my $interp;
sub run {
my $comp_name = shift;
my $comp = $memo->{$comp_name} ||= $interp->load($comp_name) || die;
my $output = "";
my $req = $interp->make_request(
comp => $comp,
args => $args,
out_method => \$output,
);
$req->exec;
$output;
}
for (@interp_variants) {
say "";
say format_pretty $_;
$memo = {};
$interp = HTML::Mason::Interp->new(
allow_globals => [qw($arg1 $arg2)],
comp_root => rel2abs("bench/comps"),
#data_dir => rel2abs("bench/data"),
%$_,
);
run($_) for @comp_names; # warmup
cmpthese($count, {
map {
my $path = $_;
$path => sub { run($path) };
} @comp_names
});
}
__END__
{ enable_autoflush => 0, static_source => 0 }
Rate /fragment_with_args.mas /fragment_no_args.mas /anon_with_args.mas /anon_no_args.mas /anon_no_args_code.mas /sub_local.mas /sub.mas /plain.mas
/fragment_with_args.mas 11.4/s -- -5% -81% -86% -97% -97% -98% -98%
/fragment_no_args.mas 12.0/s 6% -- -80% -85% -97% -97% -98% -98%
/anon_with_args.mas 60.1/s 428% 400% -- -24% -84% -86% -88% -89%
/anon_no_args.mas 79.0/s 594% 557% 31% -- -79% -81% -84% -85%
/anon_no_args_code.mas 376/s 3206% 3029% 526% 376% -- -12% -24% -29%
/sub_local.mas 427/s 3647% 3447% 610% 440% 13% -- -13% -20%
/sub.mas 492/s 4223% 3992% 719% 523% 31% 15% -- -8%
/plain.mas 533/s 4583% 4333% 787% 575% 42% 25% 8% --
{ enable_autoflush => 0, static_source => 1 }
Rate /fragment_with_args.mas /anon_with_args.mas /fragment_no_args.mas /anon_no_args.mas /anon_no_args_code.mas /sub_local.mas /sub.mas /plain.mas
/fragment_with_args.mas 52.2/s -- -15% -22% -37% -87% -88% -90% -91%
/anon_with_args.mas 61.5/s 18% -- -8% -25% -84% -86% -88% -89%
/fragment_no_args.mas 66.7/s 28% 8% -- -19% -83% -84% -87% -88%
/anon_no_args.mas 82.6/s 58% 34% 24% -- -79% -81% -85% -85%
/anon_no_args_code.mas 388/s 642% 530% 482% 370% -- -9% -27% -30%
/sub_local.mas 427/s 717% 593% 540% 417% 10% -- -20% -23%
/sub.mas 533/s 921% 767% 700% 546% 37% 25% -- -4%
/plain.mas 557/s 965% 804% 735% 574% 43% 30% 4% --
{ enable_autoflush => 1, static_source => 0 }
Rate /fragment_with_args.mas /fragment_no_args.mas /anon_with_args.mas /anon_no_args.mas /anon_no_args_code.mas /plain.mas /sub_local.mas /sub.mas
/fragment_with_args.mas 10.2/s -- -8% -75% -79% -89% -91% -93% -93%
/fragment_no_args.mas 11.0/s 9% -- -73% -77% -88% -90% -92% -93%
/anon_with_args.mas 40.6/s 299% 268% -- -17% -57% -64% -72% -73%
/anon_no_args.mas 48.7/s 378% 341% 20% -- -49% -57% -67% -68%
/anon_no_args_code.mas 94.8/s 832% 759% 133% 95% -- -17% -36% -38%
/plain.mas 114/s 1023% 935% 181% 135% 21% -- -22% -25%
/sub_local.mas 147/s 1346% 1232% 262% 202% 55% 29% -- -3%
/sub.mas 152/s 1398% 1280% 275% 213% 61% 33% 4% --
最後のベンチでは plain と sub が逆転してしまっている。
enable_autoflush => 1 だと <% ... %> のコストが比較的高い。
static_source の差が大きい。
Mason2だと同一リクエスト内でのcomp_existsはmemoizeされてるので、ここまで違わない気がする。
Mason1ではどういうことになってるのか未調査。
__DATA__
@@ bench/comps/plain.mas
<%args>
$rows
$cols
</%args>
<table>
% for my $row (@$rows) {
<tr>
% for my $col (@$cols) {
<td>
<% $row %>-<% $col %>
</td>
% }
</tr>
% }
</table>
@@ bench/comps/sub.mas
<%args>
$rows
$cols
</%args>
<%once>
my $code = sub { "$_[0]-$_[1]" };
</%once>
<table>
% for my $row (@$rows) {
<tr>
% for my $col (@$cols) {
<td>
<% $code->($row, $col) %>
</td>
% }
</tr>
% }
</table>
@@ bench/comps/sub_local.mas
<%args>
$rows
$cols
</%args>
<%once>
my $code = sub () { "$arg1-$arg2]" };
</%once>
<table>
% for (@$rows) {
% local $arg1 = $_;
<tr>
% for (@$cols) {
% local $arg2 = $_;
<td>
<% &$code %>
</td>
% }
</tr>
% }
</table>
@@ bench/comps/fragment/cell_with_args.mas
<%args>
$row
$col
</%args>
<% $row %>-<% $col %>\
@@ bench/comps/fragment/cell_no_args.mas
<% 1 %>-<% 2 %>\
@@ bench/comps/anon_with_args.mas
<%args>
$rows
$cols
</%args>
<%once>
use IO::All;
my $anon;
</%once>
<%perl>
$anon ||= $m->interp->make_component(
comp_source => io('bench/comps/fragment/cell_with_args.mas')->all,
);
</%perl>
<table>
% for my $row (@$rows) {
<tr>
% for my $col (@$cols) {
<td>
<& $anon, row => $row, col => $col &>
</td>
% }
</tr>
% }
</table>
@@ bench/comps/anon_no_args.mas
<%args>
$rows
$cols
</%args>
<%once>
use IO::All;
my $anon;
</%once>
<%perl>
$anon ||= $m->interp->make_component(
comp_source => io('bench/comps/fragment/cell_no_args.mas')->all,
);
</%perl>
<table>
% for my $row (@$rows) {
<tr>
% for my $col (@$cols) {
<td>
<& $anon &>
</td>
% }
</tr>
% }
</table>
@@ bench/comps/fragment_with_args.mas
<%args>
$rows
$cols
</%args>
<table>
% for my $row (@$rows) {
<tr>
% for my $col (@$cols) {
<td>
<& /fragment/cell_with_args.mas, row => $row, col => $col &>
</td>
% }
</tr>
% }
</table>
@@ bench/comps/fragment_no_args.mas
<%args>
$rows
$cols
</%args>
<table>
% for my $row (@$rows) {
<tr>
% for my $col (@$cols) {
<td>
<& /fragment/cell_no_args.mas &>
</td>
% }
</tr>
% }
</table>
@@ bench/comps/anon_no_args_code.mas
<%args>
$rows
$cols
</%args>
<%once>
use IO::All;
my $anon;
</%once>
<%perl>
$anon ||= $m->interp->make_component(
comp_source => io('bench/comps/fragment/cell_no_args.mas')->all,
)->{code};
</%perl>
<table>
% for my $row (@$rows) {
<tr>
% for my $col (@$cols) {
<td>
% $anon->();
</td>
% }
</tr>
% }
</table>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment