summaryrefslogtreecommitdiff
path: root/benchmarks/moose_bench.pl
blob: b8dc4268c8dfe38e70bb22fcc3128006aed74a60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/usr/bin/env perl
use strict;
use warnings;
use Time::HiRes 'time';
use List::Util 'sum';
use IPC::System::Simple 'system';
use autodie;
use Parse::BACKPAN::Packages;
use LWP::Simple;
use Archive::Tar;
use Path::Tiny;

my $backpan = Parse::BACKPAN::Packages->new;
my @cmops   = $backpan->distributions('Class-MOP');
my @mooses  = $backpan->distributions('Moose');

my $cmop_version = 0;
my $cmop_dir;

my $base = "http://backpan.cpan.org/";

my %time;
my %mem;

open my $output, ">", "moose_bench.txt";

for my $moose (@mooses) {
    my $moose_dir = build($moose);

    # Find the CMOP dependency
    my $makefile = path("$moose_dir/Makefile.PL")->slurp_utf8;
    my ($cmop_dep) = $makefile =~ /Class::MOP.*?([0-9._]+)/
        or die "Unable to find Class::MOP version dependency in $moose_dir/Makefile.PL";

    # typo?
    $cmop_dep = '0.64_07' if $cmop_dep eq '0.6407';

    # nonexistent dev releases?
    $cmop_dep = '0.79' if $cmop_dep eq '0.78_02';
    $cmop_dep = '0.83' if $cmop_dep eq '0.82_01';

    bump_cmop($cmop_dep, $moose);

    warn "Building $moose_dir";
    eval {
        system("(cd '$moose_dir' && '$^X' '-I$cmop_dir/lib' Makefile.PL && make && sudo make install) >/dev/null");

        my @times;
        for (1 .. 5) {
            my $start = time;
            system(
                $^X,
                "-I$moose_dir/lib",
                "-I$cmop_dir/lib",
                '-e', 'package Class; use Moose;',
            );
            push @times, time - $start;
        }

        $time{$moose->version} = sum(@times) / @times;
        $mem{$moose->version} = 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'];
        my $line = sprintf "%7s: %0.4f (%s), %d bytes\n",
            $moose->version,
            $time{$moose->version},
            join(', ', map { sprintf "%0.4f", $_ } @times),
            $mem{$moose->version};
        print $output $line;
    };
    warn $@ if $@;
}

require Chart::Clicker;
require Chart::Clicker::Data::Series;
require Chart::Clicker::Data::DataSet;
my @versions = sort keys %time;
my @startups = map {     $time{$_}        } @versions;
my @memories = map { int($mem{$_} / 1024) } @versions;
my @keys     = (0..$#versions);
my $cc = Chart::Clicker->new(width => 900, height => 400);
my $sutime = Chart::Clicker::Data::Series->new(
    values => \@startups,
    keys   => \@keys,
    name   => 'Startup Time',
);
my $def = $cc->get_context('default');
$def->domain_axis->tick_values(\@keys);
$def->domain_axis->tick_labels(\@versions);
$def->domain_axis->tick_label_angle(1.57);
$def->domain_axis->tick_font->size(8);
$def->range_axis->fudge_amount('0.05');

my $context = Chart::Clicker::Context->new(name => 'memory');
$context->range_axis->tick_values([qw(1024 2048 3072 4096 5120)]);
$context->range_axis->format('%d');
$context->domain_axis->hidden(1);
$context->range_axis->fudge_amount('0.05');
$cc->add_to_contexts($context);

my $musage = Chart::Clicker::Data::Series->new(
    values => \@memories,
    keys => \@keys,
    name => 'Memory Usage (kb)'
);

my $ds1 = Chart::Clicker::Data::DataSet->new(series => [ $sutime ]);
my $ds2 = Chart::Clicker::Data::DataSet->new(series => [ $musage ]);
$ds2->context('memory');

$cc->add_to_datasets($ds1);
$cc->add_to_datasets($ds2);
$cc->write_output('moose_bench.png');

sub bump_cmop {
    my $expected = shift;
    my $moose = shift;

    return $cmop_dir if $cmop_version eq $expected;

    my @orig_cmops = @cmops;
    shift @cmops until !@cmops || $cmops[0]->version eq $expected;

    die "Ran out of cmops, wanted $expected for "
        . $moose->distvname
        . " (had " . join(', ', map { $_->version } @orig_cmops) . ")"
            if !@cmops;

    $cmop_version = $cmops[0]->version;
    $cmop_dir = build($cmops[0]);

    warn "Building $cmop_dir";
    system("(cd '$cmop_dir' && '$^X' Makefile.PL && make && sudo make install) >/dev/null");

    return $cmop_dir;
}

sub build {
    my $dist = shift;
    my $distvname = $dist->distvname;
    return $distvname if -d $distvname;

    warn "Downloading $distvname";
    my $tarball = get($base . $dist->prefix);
    open my $handle, '<', \$tarball;

    my $tar = Archive::Tar->new;
    $tar->read($handle);
    $tar->extract;

    my ($arbitrary_file) = $tar->list_files;
    (my $directory = $arbitrary_file) =~ s{/.*}{};
    return $directory;
}