add Sartak's moose_bench.pl script to benchmarks/
[gitmo/Moose.git] / benchmarks / moose_bench.pl
1 #!/usr/bin/env perl
2 use strict;
3 use warnings;
4 use Time::HiRes 'time';
5 use List::Util 'sum';
6 use IPC::System::Simple 'system';
7 use autodie;
8 use Parse::BACKPAN::Packages;
9 use LWP::Simple;
10 use Archive::Tar;
11 use File::Slurp 'slurp';
12
13 my $backpan = Parse::BACKPAN::Packages->new;
14 my @cmops   = $backpan->distributions('Class-MOP');
15 my @mooses  = $backpan->distributions('Moose');
16
17 my $cmop_version = 0;
18 my $cmop_dir;
19
20 my $base = "http://backpan.cpan.org/";
21
22 for my $moose (@mooses) {
23     my $moose_dir = build($moose);
24
25     # Find the CMOP dependency
26     my $makefile = slurp("$moose_dir/Makefile.PL");
27     my ($cmop_dep) = $makefile =~ /Class::MOP.*?([0-9._]+)/
28         or die "Unable to find Class::MOP version dependency in $moose_dir/Makefile.PL";
29
30     # typo?
31     $cmop_dep = '0.64_07' if $cmop_dep eq '0.6407';
32
33     # nonexistent dev releases?
34     $cmop_dep = '0.79' if $cmop_dep eq '0.78_02';
35     $cmop_dep = '0.83' if $cmop_dep eq '0.82_01';
36
37     bump_cmop($cmop_dep, $moose);
38
39     warn "Building $moose_dir";
40     eval {
41         system("(cd '$moose_dir' && '$^X' '-I$cmop_dir/lib' Makefile.PL && make && sudo make install) >/dev/null");
42
43         my @times;
44         for (1 .. 5) {
45             my $start = time;
46             system(
47                 $^X,
48                 "-I$moose_dir/lib",
49                 "-I$cmop_dir/lib",
50                 '-e', 'package Class; use Moose;',
51             );
52             push @times, time - $start;
53         }
54
55         my $duration = sum(@times) / @times;
56         my $mem = qx[$^X -I$moose_dir/lib -I$cmop_dir/lib -MGTop -e 'my (\$gtop, \$before); BEGIN { \$gtop = GTop->new; \$before = \$gtop->proc_mem(\$\$)->size; } package Class; use Moose; print \$gtop->proc_mem(\$\$)->size - \$before'];
57         printf "%7s: %0.4f (%s), %d bytes\n",
58             $moose->version,
59             $duration,
60             join(', ', map { sprintf "%0.4f", $_ } @times),
61             $mem;
62     };
63     warn $@ if $@;
64 }
65
66 sub bump_cmop {
67     my $expected = shift;
68     my $moose = shift;
69
70     return $cmop_dir if $cmop_version eq $expected;
71
72     my @orig_cmops = @cmops;
73     shift @cmops until !@cmops || $cmops[0]->version eq $expected;
74
75     die "Ran out of cmops, wanted $expected for "
76         . $moose->distvname
77         . " (had " . join(', ', map { $_->version } @orig_cmops) . ")"
78             if !@cmops;
79
80     $cmop_version = $cmops[0]->version;
81     $cmop_dir = build($cmops[0]);
82
83     warn "Building $cmop_dir";
84     system("(cd '$cmop_dir' && '$^X' Makefile.PL && make && sudo make install) >/dev/null");
85
86     return $cmop_dir;
87 }
88
89 sub build {
90     my $dist = shift;
91     my $distvname = $dist->distvname;
92     return $distvname if -d $distvname;
93
94     warn "Downloading $distvname";
95     my $tarball = get($base . $dist->prefix);
96     open my $handle, '<', \$tarball;
97
98     my $tar = Archive::Tar->new;
99     $tar->read($handle);
100     $tar->extract;
101
102     my ($arbitrary_file) = $tar->list_files;
103     (my $directory = $arbitrary_file) =~ s{/.*}{};
104     return $directory;
105 }
106