File Coverage

blib/lib/XAO/DO/Web/Benchmark.pm
Criterion Covered Total %
statement 58 63 92.0
branch 23 30 76.6
condition 20 30 66.6
subroutine 11 11 100.0
pod 0 6 0.0
total 112 140 80.0


line stmt bran cond sub pod time code
1             =head1 NAME
2              
3             XAO::DO::Web::Benchmark - benchmarking helper
4              
5             =head1 SYNOPSIS
6              
7             <%Benchmark mode='enter' tag='main'%>
8             ....
9             <%Benchmark mode='leave' tag='main'%>
10             ...
11             <%Benchmark mode='stats' tag='main'
12             dprint
13             template={'Count: <$COUNT$> Total: <$TOTAL$> Avg: <$AVERAGE$>'}
14             %>
15             ...
16             <%Benchmark mode='stats'
17             header.template='
    '
18             template= '
  • Tag: <$TAG/h$> Avg: <$AVERAGE$> Med: <$MEDIAN$>
  • '
    19             footer.template=''
    20             %>
    21              
    22             =head1 DESCRIPTION
    23              
    24             Remembers timing at the given points during template processing and
    25             reports on them later. The tag is required for 'enter' and 'leave'
    26             modes.
    27              
    28             System-wide benchmarking can also be controlled with 'system-start'
    29             and 'system-stop' modes. With that all sub-templates are individually
    30             benchmarked. The tags are automatically build based on their 'path' or
    31             'template' arguments.
    32              
    33             Results can be retrieved using 'stats' mode. With a 'dprint' parameter
    34             it will dump results using the dprint() call to be seen in the server
    35             log typically. Given a template or a path the results can be included in
    36             the rendered page.
    37              
    38             =cut
    39              
    40             ###############################################################################
    41             package XAO::DO::Web::Benchmark;
    42 1     1   848 use warnings;
      1         2  
      1         39  
    43 1     1   5 use strict;
      1         2  
      1         21  
    44 1     1   4 use XAO::Utils;
      1         2  
      1         65  
    45 1     1   5 use XAO::Objects;
      1         2  
      1         26  
    46              
    47 1     1   4 use base XAO::Objects->load(objname => 'Web::Action');
      1         3  
      1         4  
    48              
    49             ###############################################################################
    50              
    51             sub display_enter ($@) {
    52 1     1 0 2 my $self=shift;
    53 1         3 my $args=get_args(\@_);
    54 1   33     10 my $tag=$args->{'tag'} || throw $self "- no tag";
    55 1         13 $self->benchmark_enter($tag,$args->{'key'},$args->{'description'});
    56             }
    57              
    58             ###############################################################################
    59              
    60             sub display_leave ($@) {
    61 1     1 0 3 my $self=shift;
    62 1         3 my $args=get_args(\@_);
    63 1   33     11 my $tag=$args->{'tag'} || throw $self "- no tag";
    64 1         6 $self->benchmark_leave($tag,$args->{'key'});
    65             }
    66              
    67             ###############################################################################
    68              
    69             sub display_system_start ($) {
    70 2     2 0 2 my $self = shift;
    71 2         8 $self->benchmark_start();
    72             }
    73              
    74             ###############################################################################
    75              
    76             sub display_system_stop ($) {
    77 1     1 0 2 my $self = shift;
    78 1         6 $self->benchmark_stop();
    79             }
    80              
    81             ###############################################################################
    82              
    83             sub data_stats ($@) {
    84 8     8 0 10 my $self=shift;
    85 8         51 my $args=get_args(\@_);
    86 8         165 return { benchmarks => $self->benchmark_stats($args->{'tag'}) };
    87             }
    88              
    89             ###############################################################################
    90              
    91             sub display_stats ($@) {
    92 8     8 0 15 my $self=shift;
    93 8         19 my $args=get_args(\@_);
    94              
    95 8   33     128 my $stats=$args->{'data'}->{'benchmarks'} || throw $self "- no 'data' (INTERNAL)";
    96              
    97 8         12 my @tags;
    98 8   100     21 my $orderby=$args->{'orderby'} || 'total';
    99              
    100 8 100       28 if($orderby eq 'total') {
        50          
        50          
        100          
        50          
    101 4         15 @tags=sort { $stats->{$b}->{'total'} <=> $stats->{$a}->{'total'} } keys %$stats;
      39         56  
    102             }
    103             elsif($orderby eq 'average') {
    104 0         0 @tags=sort { $stats->{$b}->{'average'} <=> $stats->{$a}->{'average'} } keys %$stats;
      0         0  
    105             }
    106             elsif($orderby eq 'median') {
    107 0         0 @tags=sort { $stats->{$b}->{'median'} <=> $stats->{$a}->{'median'} } keys %$stats;
      0         0  
    108             }
    109             elsif($orderby eq 'count') {
    110 2 50       8 @tags=sort { ($stats->{$b}->{'count'} <=> $stats->{$a}->{'count'}) || ($stats->{$b}->{'average'} <=> $stats->{$a}->{'average'}) } keys %$stats;
      8         22  
    111             }
    112             elsif($orderby eq 'tag') {
    113 2         10 @tags=sort { $a cmp $b } keys %$stats;
      14         21  
    114             }
    115             else {
    116 0         0 throw $self "- unknown orderby";
    117             }
    118              
    119 8 100 66     32 if($args->{'limit'} && scalar(@tags)>$args->{'limit'}) {
    120 2         5 splice(@tags,$args->{'limit'})
    121             }
    122              
    123 8         22 my $page=$self->object;
    124              
    125             $page->display($args,{
    126             path => $args->{'header.path'},
    127             template => $args->{'header.template'},
    128             TOTAL_ITEMS => scalar(@tags),
    129 8 100 66     491 }) if $args->{'header.path'} || defined $args->{'header.template'};
    130              
    131 8         13 my $taglen=0;
    132 8         12 foreach my $tag (@tags) {
    133 35 100       53 $taglen=length $tag if length $tag > $taglen;
    134             }
    135              
    136 8         10 foreach my $tag (@tags) {
    137 35         46 my $d=$stats->{$tag};
    138              
    139 35 50       54 next unless $d->{'count'};
    140              
    141             $page->display($args,{
    142             TAG => $tag,
    143             COUNT => $d->{'count'},
    144             AVERAGE => $d->{'average'},
    145             MEDIAN => $d->{'median'},
    146             TOTAL => $d->{'total'},
    147             CACHEABLE => $d->{'cacheable'} || 0,
    148             CACHE_FLAG => $d->{'cache_flag'} || 0,
    149 35 100 100     240 }) if $args->{'path'} || defined $args->{'template'};
          100        
          100        
    150              
    151 35 100 66     132 if($args->{'dprint'} || $args->{'eprint'}) {
    152             my $str=sprintf('BENCHMARK(%*s): COUNT=%6u TOTAL=%7.3f AVERAGE=%7.3f MEDIAN=%7.3f CACHEABLE=%s CACHE_FLAG=%s',
    153 6         48 $taglen, $tag, $d->{'count'}, $d->{'total'}, $d->{'average'}, $d->{'median'}, $d->{'cacheable'}, $d->{'cache_flag'});
    154 6 50       19 dprint $str if $args->{'dprint'};
    155 6 50       20 eprint $str if $args->{'eprint'};
    156             }
    157             }
    158              
    159             $page->display($args,{
    160             path => $args->{'footer.path'},
    161             template => $args->{'footer.template'},
    162             TOTAL_ITEMS => scalar(@tags),
    163 8 100 66     54 }) if $args->{'footer.path'} || defined $args->{'footer.template'};
    164             }
    165              
    166             ###############################################################################
    167             1;
    168             __END__