File Coverage

blib/lib/Dumbbench/Instance/PerlSub.pm
Criterion Covered Total %
statement 51 51 100.0
branch 8 8 100.0
condition 4 5 80.0
subroutine 13 13 100.0
pod 2 2 100.0
total 78 79 98.7


line stmt bran cond sub pod time code
1             package # hide from PAUSE
2             Dumbbench::Instance::PerlSub::_Lexical;
3             # clean lexical scope
4             sub runsub {
5 23     23   28 my $n = shift;
6 23         24 my $code = shift;
7 23         26 local $_;
8 23         30 for (1..$n) {
9 798         1036 $code->();
10             }
11             }
12              
13             package Dumbbench::Instance::PerlSub;
14 3     3   20 use strict;
  3         5  
  3         83  
15 3     3   17 use warnings;
  3         4  
  3         65  
16 3     3   15 use Carp ();
  3         5  
  3         35  
17 3     3   19 use Time::HiRes ();
  3         7  
  3         64  
18              
19 3     3   17 use Dumbbench::Instance;
  3         5  
  3         58  
20 3     3   12 use parent 'Dumbbench::Instance';
  3         8  
  3         19  
21              
22             use Class::XSAccessor {
23 3         23 getters => [qw(
24             code
25             dry_run_code
26             )],
27             accessors => [qw(
28             _n_loop_timings
29             _n_dry_loop_timings
30             )],
31 3     3   281 };
  3         12  
32              
33 3     3   989 use constant TOO_SMALL => 1.e-4;
  3         5  
  3         824  
34              
35             =encoding utf8
36              
37             =head1 NAME
38              
39             Dumbbench::Instance::PerlSub - Benchmarks a Perl code reference
40              
41             =head1 SYNOPSIS
42              
43             use Dumbbench;
44              
45             my $bench = Dumbbench->new(
46             target_rel_precision => 0.005, # seek ~0.5%
47             initial_runs => 20, # the higher the more reliable
48             );
49             $bench->add_instances(
50             Dumbbench::Instance::PerlSub->new(name => 'mauve', code => sub {...}),
51             # ... more things to benchmark ...
52             );
53             $bench->run();
54             # ...
55              
56             =head1 DESCRIPTION
57              
58             This class inherits from L and implements
59             benchmarking of Perl code references.
60              
61             =head1 METHODS
62              
63             =head2 new
64              
65             Constructor that takes named arguments.
66              
67             In addition to the properties of the base class, the
68             C constructor requires a
69             C parameter. The C needs to be subroutine reference.
70              
71             Optionally, you can provide a C option.
72             It has the same structure and purpose as the C
73             option, but it is used for the dry-runs. By default, an empty sub
74             is used for this, so it's unlikely you will need the dry-run
75             unless you want to strip out some particular overhead.
76              
77             =head2 code
78              
79             Returns the code string that was set during construction.
80              
81             =head2 dry_run_code
82              
83             Returns the dry-run code string that was set during construction.
84              
85             =cut
86              
87             # Note: We don't need to override clone() since we don't have composite attributes
88             # Note2: Can't (reliably) clone code refs anyway :(
89              
90             sub single_run {
91 2     2 1 3 my $self = shift;
92 2         3 return $self->_run(0);
93             }
94              
95             sub single_dry_run {
96 10     10 1 15 my $self = shift;
97 10         15 return $self->_run(1);
98             }
99              
100             sub _run {
101 12     12   13 my $self = shift;
102 12         15 my $dry = shift;
103 12 100       18 my $code_acc = $dry ? 'dry_run_code' : 'code';
104 12 100       15 my $n_loop_acc = $dry ? '_n_dry_loop_timings' : '_n_loop_timings';
105              
106 12         22 my $code = $self->$code_acc;
107 12 100 66 703   46 $code = sub {} if not ref($code) or not ref($code) eq 'CODE';
108              
109 12         17 my $duration;
110 12   100     26 my $n = $self->$n_loop_acc || 1;
111 12         15 while (1) {
112             #my $start;
113             #my $tbase = Time::HiRes::time();
114             #while ( ($start = Time::HiRes::time()) <= $tbase+1.e-15 ) {} # wait for clock tick. See discussion in Benchmark.pm comments
115 23         31 my $start = Time::HiRes::time();
116 23         37 Dumbbench::Instance::PerlSub::_Lexical::runsub($n, $code);
117 23         51 my $end = Time::HiRes::time();
118              
119 23         24 $duration = $end-$start;
120 23 100       38 if ($duration > TOO_SMALL) {
121 12         15 last;
122             }
123 11         12 $n *= 2;
124             }
125 12         22 $self->$n_loop_acc($n);
126              
127 12         44 return $duration / $n;
128             }
129              
130              
131              
132             1;
133              
134              
135             __END__