File Coverage

blib/lib/Surveyor/App.pm
Criterion Covered Total %
statement 15 46 32.6
branch 0 12 0.0
condition n/a
subroutine 5 9 55.5
pod 3 3 100.0
total 23 70 32.8


line stmt bran cond sub pod time code
1             package Surveyor::App;
2 1     1   725 use strict;
  1         2  
  1         28  
3 1     1   5 use warnings;
  1         2  
  1         72  
4              
5             our $VERSION = '0.121';
6              
7             =encoding utf8
8              
9             =head1 NAME
10              
11             Surveyor::App - Run benchmarks from a package
12              
13             =head1 SYNOPSIS
14              
15             use Surveyor::App;
16              
17             =head1 DESCRIPTION
18              
19             C provides a minimal framework and convention for
20             people to distribute benchmarks. By creating a package in a special
21             way, you can easily share your benchmarks with people without having
22             to repeat a lot of code.
23              
24             First, if you want to do some setup before your benchmarks run, define
25             a C method. Do whatever you need there, such as setting
26             environment variables, changing directories, and so on. The C
27             method gets the command-line arguments you specified when you run
28             C, save for any that C used for itself.
29              
30             Next, define your benchmarks in subroutines whose names start with
31             C. Surveyor::App will find each of those, using the part of
32             the name after C as the label for that test.
33              
34             Last, if you want to do some setup before your benchmarks run, define
35             a C method. The C method gets no arguments.
36              
37             Your benchmarking package doesn't have to have any particular name and
38             it doesn't need to subclass or C this package. See
39             L for an example.
40              
41             =over 4
42              
43             =cut
44              
45             =item run( PACKAGE, ITERATIONS, @ARGS )
46              
47             Find all of the subroutines that start with C in C
48             and run each of them C times.
49              
50             Before it does that, though, call the C routine in C
51             as a class method. After benchmarking, call the C routine
52             in C as a class method.
53              
54             =cut
55              
56             sub run {
57 0     0 1   my( $package, $iterations, @args ) = @_;
58 0 0         $package->set_up( @args ) if $package->can( 'set_up' );
59              
60             # the key is a label, which is the stuff after bench_
61 1     1   5 no strict 'refs';
  1         2  
  1         295  
62             my %hash = map {
63 0           (
64 0           do { (my $s = $_) =~ s/\Abench_//; $s },
  0            
65 0           \&{"${package}::$_"}
  0            
66             )
67             } get_all_bench_( $package );
68              
69 0 0         die "Did not find any bench_ subroutines in [$package]\n"
70             unless keys %hash;
71              
72 0           require Benchmark;
73 0           my $results = Benchmark::timethese( $iterations, \%hash );
74              
75 0 0         $package->tear_down() if $package->can( 'tear_down' );
76             }
77              
78             =item test( PACKAGE, @ARGS )
79              
80             Find all of the subroutines that start with C in C
81             and run each of them once. Compare the return values of each to ensure
82             they are the same.
83              
84             Before it does that, though, call the C routine in C
85             as a class method. After benchmarking, call the C routine
86             in C as a class method.
87              
88             =cut
89              
90             sub test {
91 0     0 1   my( $package, @args ) = @_;
92 0           my @subs = get_all_bench_( $package );
93 0           my %results;
94              
95 0 0         $package->set_up( @args ) if $package->can( 'set_up' );
96 0           foreach my $sub ( get_all_bench_( $package ) ) {
97 0           my @return = $package->$sub();
98 0           $results{$sub} = \@return;
99             }
100 0 0         $package->tear_down() if $package->can( 'tear_down' );
101              
102 1     1   12 use Test::More;
  1         3  
  1         27  
103              
104             subtest pairs => sub {
105 0     0     my @subs = keys %results;
106 0           foreach my $i ( 1 .. $#subs ) {
107 0           my @sub_names = @subs[ $i - 1, $i ];
108 0           my( $first, $second ) = @results{ @sub_names };
109 0           local $" = " and ";
110 0           is_deeply( $first, $second, "@sub_names match return values" );
111             }
112 0           };
113              
114 0           done_testing();
115             }
116              
117             =item get_all_bench_( PACKAGE )
118              
119             Extract all of the subroutines starting with C in C.
120             If you don't define a package, it uses the package this subroutine
121             was compiled in (so that's probably useless).
122              
123             =cut
124              
125             sub get_all_bench_ {
126 0     0 1   my( $package ) = @_;
127 0 0         $package = defined $package ? $package : __PACKAGE__;
128              
129 1     1   435 no strict 'refs';
  1         2  
  1         95  
130             my @subs =
131             grep /\Abench_/,
132 0           keys %{"${package}::"};
  0            
133             }
134              
135              
136             =back
137              
138             =head1 TO DO
139              
140              
141             =head1 SEE ALSO
142              
143              
144             =head1 SOURCE AVAILABILITY
145              
146             This source is in a Git repository that I haven't made public
147             because I haven't bothered to set it up. If you want to clone
148             it, just ask and we'll work something out.
149              
150             https://github.com/briandfoy/surveyor-app
151              
152             =head1 AUTHOR
153              
154             brian d foy, C<< >>
155              
156             =head1 COPYRIGHT AND LICENSE
157              
158             Copyright © 2013-2018, brian d foy . All rights reserved.
159              
160             You may redistribute this under the terms of the Artistic License 2.0.
161              
162             =cut
163              
164             1;