File Coverage

blib/lib/Tool/Bench.pm
Criterion Covered Total %
statement 41 41 100.0
branch 4 6 66.6
condition 3 4 75.0
subroutine 8 8 100.0
pod 4 4 100.0
total 60 63 95.2


line stmt bran cond sub pod time code
1             package Tool::Bench;
2             {
3             $Tool::Bench::VERSION = '0.003';
4             }
5 2     2   144730 use Mouse;
  2         68612  
  2         10  
6 2     2   787 use List::Util qw{shuffle};
  2         4  
  2         278  
7 2     2   7268 use Data::Dumper;
  2         18441  
  2         1015  
8              
9             # ABSTRACT: Tool Bench is a generic framework for running benchmarks.
10              
11             =head1 NAME
12              
13             Tool::Bench - Tool Bench is a generic framework for running benchmarks.
14              
15             =head1 SYNOPSIS
16              
17             Ok so I'm sure your asking your self, yet another benchmarking suit? Sure there
18             are many others but this one is not specific to Perl. Think of Tool::Bench more
19             as a jazzy version of the unix 'time' command it just happens to be written in
20             perl. With 'time' you have a very simple wrap a clock around this command for
21             one run. Tool::Bench goes a bit further by wrapping a clock around the
22             execution of an number of CodeRef, run as many times as you want. Then because
23             all these times are stored you can build reports from the results of all these
24             runs.
25              
26             That said Tool::Bench is designed to just be the clock engine, you
27             have to draw the line somewhere. So here's a quick example of usage.
28              
29             use Tool::Bench;
30             my $bench = Tool::Bench->new;
31              
32             # simplest case: add a code ref with a name
33             $bench->add_items( simple => sub{...} );
34              
35             # slightly more complex item: now with events
36             $bench->add_items( complex => { startup => sub{...},
37             code => sub{...},
38             teardown => sub{...},
39             },
40             );
41              
42             # add items can takes a hash so you can add more then one item
43             $bench->add_items( name1 => sub{...},
44             name2 => { startup => sub{...},
45             code => sub{...},
46             },
47             name3 => sub{...},
48             );
49              
50             # now that your all set up, you'll want to run them
51             # lets say that you want to run each item 3 times
52             $bench->run(3);
53              
54             # now you've got a bunch of data stored off... lets do something with it.
55              
56             $bench->report(format => 'Text');
57            
58             =head1 ATTRIBUTES
59              
60             =head2 items
61              
62             This is the store for all the items to be bench marked. When called directly
63             you will get an arrayref of Item objects.
64              
65             =cut
66              
67             has items =>
68             is => 'rw',
69             isa => 'ArrayRef[Tool::Bench::Item]',
70             lazy => 1,
71             default => sub{[]},
72             ;
73              
74             =head1 METHODS
75              
76             =head2 items_count
77              
78             Returns the count of the number of items currently stored.
79              
80             =cut
81              
82 4     4 1 5 sub items_count { scalar( @{ shift->items } ) };
  4         22  
83              
84             =head2 add_items
85              
86             $bench->add_items( $name => $coderef );
87             $bench->add_items( $name => { startup => $coderef,
88             code => $coderef,
89             teardown => $coderef,
90             #verify => $coderef, # currently not implimented
91             }
92             ...
93             );
94              
95             This method will take your input and build new Item objects and store them
96             in the items stack. See L for more info on the events.
97              
98             Returns items_count.
99             =cut
100              
101             sub add_items {
102 3     3 1 1688 require Tool::Bench::Item;
103 3         6 my $self = shift;
104 3         9 my %items = @_;
105 3         11 for my $name ( keys %items ) {
106 4         6 my $ref = ref($items{$name});
107 4 50       12 my $new = $ref eq 'CODE' ? {code => $items{$name}}
    100          
108             : $ref eq 'HASH' ? $items{$name}
109             : {};
110              
111 4         6 push @{$self->items}, Tool::Bench::Item->new( name => $name, %$new );
  4         42  
112             }
113 3         8 return $self->items_count;
114             }
115              
116             =head2 run
117              
118              
119             When you are done adding all your items, you'll want to run them. Run takes an
120             int that refers to the number of times that you want to run each item, the
121             default is 1.
122              
123             $bench->run; # fire off the run method of all known items in shuffled order
124             $bench->run(3); # run all items 3 times, random order non-sequential runs
125              
126             Returns the number of times that it ran each item.
127              
128             =cut
129              
130             sub run {
131 2     2 1 4 my $self = shift;
132 2   100     15 my $times = shift || 1;
133 2         4 my $count = 0;
134 2         3 $_->pre_run->() for @{ $self->items }; # pre run even tripping
  2         17  
135 2         24 foreach my $i (1..int($times)) {
136 4         11 foreach my $item ( shuffle( @{ $self->items } ) ) {
  4         76  
137 16         64 $item->run;
138 16         164 $count++;
139             }
140             }
141 2         5 $_->post_run->() for @{ $self->items }; # post run even tripping
  2         31  
142 2         75 $count; # seems completely pointless but should return something at least marginally useful
143             }
144              
145              
146             #---------------------------------------------------------------------------
147             # REPORTING
148             #---------------------------------------------------------------------------
149              
150             =head2 report
151              
152             Lastly, once you've run the items, you'll likely want to mine them and build
153             a report. The report method by default will return a Text report, though you
154             can ask for other formats. The 'format' value is expected to be the last part
155             of the class to generate the report.
156              
157             $bench->report(format => 'Text'); # uses Tool::Bench::Report::Text
158             $bench->report(format => 'JSON'); # uses Tool::Bench::Report::JSON
159              
160             By using class names you can build your own report simply, see
161             L for more info on how to build report types.
162              
163             =cut
164              
165             sub report {
166 2     2 1 18 my ($self, %args) = @_;
167 2   50     34 my $type = $args{format} || 'Text';
168 2         7 my $class = qq{Tool::Bench::Report::$type};
169 2 50       181 eval qq{require $class} or die $@; #TODO this is messy
170 2         168 $class->new->report(
171             items => $self->items,
172             %args,
173             );
174             }
175              
176 2     2   19 no Mouse;
  2         4  
  2         19  
177             1;