File Coverage

blib/lib/DashProfiler.pm
Criterion Covered Total %
statement 15 69 21.7
branch 0 28 0.0
condition 0 3 0.0
subroutine 5 17 29.4
pod 12 12 100.0
total 32 129 24.8


line stmt bran cond sub pod time code
1             package DashProfiler;
2              
3 1     1   19159 use strict;
  1         2  
  1         43  
4 1     1   5 use warnings;
  1         2  
  1         48  
5              
6             our $VERSION = "1.13"; # $Revision: 48 $
7              
8             =head1 NAME
9              
10             DashProfiler - efficiently collect call count and timing data aggregated by context
11              
12             =head1 SYNOPSIS
13              
14             The DashProfiler modules enable you to efficiently collect performance data
15             by adding just a line of code to the functions or objects you want to monitor.
16              
17             Data is aggregated by context and optionally also by a granular time axis.
18              
19             See L for a general introduction.
20              
21             =head1 DESCRIPTION
22              
23             =head2 Performance
24              
25             DashProfiler is fast, very fast. Especially given the functionality and flexibility it offers.
26              
27             When you build DashProfiler, the test suite shows the performance on your
28             system when you run "make test". On my system, for example it reports:
29              
30             t/02.sample.......ok 1/0 you're using perl 5.010000 on darwin-2level -O3
31             Average 'cold' sample overhead is 0.000021s (max 0.000104s, min 0.000019s)
32             Average 'hot' sample overhead is 0.000017s (max 0.000102s, min 0.000016s)
33              
34             =head2 Apache mod_perl
35              
36             DashProfiler was designed to work well with Apache mod_perl in high volume production environments.
37              
38             Refer to L for details.
39              
40             =cut
41              
42 1     1   5 use Carp;
  1         5  
  1         94  
43 1     1   22368 use Data::Dumper;
  1         16193  
  1         63  
44              
45 1     1   791 use DashProfiler::Core;
  1         3  
  1         14  
46              
47             my %profiles;
48             my %precondition;
49              
50             =head1 PRIMARY METHODS
51              
52             =head2 add_profile
53              
54             DashProfiler->add_profile( 'my_profile_name' );
55             DashProfiler->add_profile( my_profile_name => { ... } );
56             $core = DashProfiler->add_core( my_profile_name => { ... } );
57              
58             Calls DashProfiler::Core->new to create a new DashProfiler::Core object and
59             then caches it, using the name as the key, so it can be refered to by name.
60              
61             See L for details of the arguments.
62              
63             =cut
64              
65             sub add_profile {
66 0     0 1   my $class = shift;
67 0 0         croak "A profile called '$_[0]' already exists" if $profiles{$_[0]};
68 0           my $self = DashProfiler::Core->new(@_);
69 0           $profiles{ $self->{profile_name} } = $self;
70 0           return $self;
71             }
72              
73              
74             =head2 prepare
75              
76             $sampler = DashProfiler->prepare($profile_name, ...);
77              
78             Calls prepare(...) on the DashProfiler named by $profile_name.
79             Returns a sampler code reference prepared to take samples.
80              
81             If no profile with that name exists then it will warn, but only once per name.
82              
83             =cut
84              
85             sub prepare {
86 0     0 1   my $class = shift;
87 0           my $profile_name = shift;
88 0           my $profile_ref = $profiles{$profile_name};
89 0 0         unless ($profile_ref) { # to catch spelling mistakes
90 0 0         carp "No $class profiler called '$profile_name' exists"
91             unless defined $profile_ref;
92 0           $profiles{$profile_name} = 0; # only warn once
93 0           return;
94             };
95 0           return $profile_ref->prepare(@_);
96             }
97              
98              
99             =head2 profile_names
100              
101             @profile_names = DashProfiler->profile_names;
102              
103             Returns a list of all the profile names added via L.
104              
105             =cut
106              
107             sub profile_names {
108 0     0 1   my $class = shift;
109             # return keys but skip 0 entries that might be added by prepare()
110 0           return grep { $profiles{$_} } keys %profiles;
  0            
111             }
112              
113              
114             =head2 get_profile
115              
116             $core = DashProfiler->get_profile( $profile_name );
117              
118             Returns the DashProfiler::Core object associated with that name.
119              
120             =cut
121              
122             sub get_profile {
123 0     0 1   my ($self, $profile_name) = @_;
124 0           return $profiles{$profile_name};
125             }
126              
127              
128             =head2 profile_as_text
129              
130             $text = DashProfiler->profile_as_text( $profile_name )
131              
132             Calls profile_as_text(...) on the DashProfiler named by $profile_name.
133             Returns undef if no profile with that name exists.
134              
135             =cut
136              
137             sub profile_as_text {
138 0     0 1   my $self = shift;
139 0           my $profile_name = shift;
140 0 0         my $profile_ref = $self->get_profile($profile_name) or return;
141 0           return $profile_ref->profile_as_text(@_);
142             }
143              
144              
145             =head1 METHODS AFFECTING ALL PROFILES
146              
147             =head2 all_profiles_as_text
148              
149             @text = DashProfiler->all_profiles_as_text
150              
151             Calls profile_as_text() on all profiles, ordered by name.
152              
153             =cut
154              
155             sub all_profiles_as_text {
156 0     0 1   my $class = shift;
157 0           return map { $profiles{$_}->profile_as_text() } sort keys %profiles;
  0            
158             }
159              
160              
161             =head2 dump_all_profiles
162              
163             dump_all_profiles()
164              
165             Equivalent to
166              
167             warn $_ for DashProfiler->all_profiles_as_text();
168              
169             =cut
170              
171             sub dump_all_profiles {
172 0     0 1   my $class = shift;
173 0           warn $_ for $class->all_profiles_as_text();
174 0           return 1;
175             }
176              
177              
178             =head2 reset_all_profiles
179              
180             Calls C for all profiles.
181              
182             Typically called from mod_perl PerlChildInitHandler.
183              
184             =cut
185              
186             sub reset_all_profiles { # eg PerlChildInitHandler
187 0     0 1   my $class = shift;
188 0 0         if (my $pre = $precondition{reset_all_profiles}) {
189 0 0         return 1 unless $pre->();
190             }
191 0           $_->reset_profile_data for values %profiles;
192 0           return -1; # DECLINED
193             }
194             $precondition{reset_all_profiles} = undef;
195              
196              
197             =head2 flush_all_profiles
198              
199             flush_all_profiles()
200              
201             Calls flush() for all profiles.
202             Typically called from mod_perl PerlChildExitHandler
203              
204             =cut
205              
206             sub flush_all_profiles { # eg PerlChildExitHandler
207 0     0 1   my $class = shift;
208 0 0         if (my $pre = $precondition{flush_all_profiles}) {
209 0 0         return -1 # DECLINED
210             unless $pre->();
211             }
212 0           $_->flush for values %profiles;
213 0           return -1; # DECLINED
214             }
215             $precondition{flush_all_profiles} = undef;
216              
217              
218             =head2 start_sample_period_all_profiles
219              
220             start_sample_period_all_profiles()
221              
222             Calls start_sample_period() for all profiles.
223             Typically called from mod_perl PerlPostReadRequestHandler
224              
225             =cut
226              
227             sub start_sample_period_all_profiles { # eg PerlPostReadRequestHandler
228 0     0 1   my $class = shift;
229 0 0         if (my $pre = $precondition{start_sample_period_all_profiles}) {
230 0 0         return -1 # DECLINED
231             unless $pre->();
232             }
233 0           $_->start_sample_period for values %profiles;
234 0           return -1; # DECLINED
235             }
236             $precondition{start_sample_period_all_profiles} = undef;
237              
238              
239             =head2 end_sample_period_all_profiles
240              
241             end_sample_period_all_profiles()
242              
243             Calls end_sample_period() for all profiles.
244             Then calls flush_if_due() for all profiles.
245             Typically called from mod_perl PerlCleanupHandler
246              
247             =cut
248              
249             sub end_sample_period_all_profiles { # eg PerlCleanupHandler
250 0     0 1   my $class = shift;
251 0 0         if (my $pre = $precondition{end_sample_period_all_profiles}) {
252 0 0         return -1 # DECLINED
253             unless $pre->();
254             }
255 0           $_->end_sample_period for values %profiles;
256 0           $_->flush_if_due for values %profiles;
257 0           return -1; # DECLINED
258             }
259             $precondition{end_sample_period_all_profiles} = undef;
260              
261             =head1 OTHER METHODS
262              
263             =head2 set_precondition
264              
265             DashProfiler->set_precondition( function => sub { ... } );
266              
267             Available functions are:
268              
269             reset_all_profiles
270             flush_all_profiles
271             start_sample_period_all_profiles
272             end_sample_period_all_profiles
273              
274             The set_precondition method associates a code reference with a function.
275             When the function is called the corresponding precondition code is executed
276             first. If the precondition code does not return true then the function returns
277             immediately.
278              
279             This mechanism is most useful for fine-tuning when periods start and end.
280             For example, there may be times when start_sample_period_all_profiles() is
281             being called when you might not want to actually start a new period.
282              
283             Alternatively the precondition code could itself call start_sample_period()
284             for one or more specific profiles and then return false.
285              
286             See L for an example use.
287              
288             =cut
289              
290             sub set_precondition {
291 0     0 1   my ($class, $name, $code) = @_;
292 0 0 0       croak "Not a CODE reference" if $code and ref $code ne 'CODE';
293 0 0         croak "Invalid function name '$name'" unless exists $precondition{$name};
294 0           $precondition{$name} = $code;
295 0           return;
296             }
297              
298              
299             =head1 AUTHOR
300              
301             DashProfiler by Tim Bunce, L and
302             L
303              
304             =head1 COPYRIGHT
305              
306             The DashProfiler distribution is Copyright (c) 2007-2008 Tim Bunce. Ireland.
307             All rights reserved.
308              
309             You may distribute under the terms of either the GNU General Public
310             License or the Artistic License, as specified in the Perl README file.
311              
312             =cut
313              
314             1;