| Filename | /home/ss5/perl5/perlbrew/perls/perl-5.22.0/lib/site_perl/5.22.0/CHI/Stats.pm |
| Statements | Executed 18 statements in 758µs |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 2.12ms | 7.16ms | CHI::Stats::BEGIN@6 |
| 1 | 1 | 1 | 714µs | 8.55ms | CHI::Stats::BEGIN@3 |
| 1 | 1 | 1 | 426µs | 3.30ms | CHI::Stats::BEGIN@5 |
| 1 | 1 | 1 | 14µs | 19µs | CHI::Stats::BEGIN@8 |
| 1 | 1 | 1 | 9µs | 29µs | CHI::Stats::BEGIN@4 |
| 1 | 1 | 1 | 5µs | 6µs | CHI::Stats::BEGIN@7 |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::__ANON__[:114] |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::__ANON__[:11] |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::__ANON__[:12] |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::__ANON__[:131] |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::__ANON__[:13] |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::clear |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::disable |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::enable |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::flush |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::format_time |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::log_namespace_stats |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::parse_stats_logs |
| 0 | 0 | 0 | 0s | 0s | CHI::Stats::stats_for_driver |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package CHI::Stats; | ||||
| 2 | 1 | 400ns | $CHI::Stats::VERSION = '0.60'; | ||
| 3 | 2 | 62µs | 2 | 8.58ms | # spent 8.55ms (714µs+7.83) within CHI::Stats::BEGIN@3 which was called:
# once (714µs+7.83ms) by CHI::BEGIN@5 at line 3 # spent 8.55ms making 1 call to CHI::Stats::BEGIN@3
# spent 32µs making 1 call to Exporter::import |
| 4 | 2 | 19µs | 2 | 36µs | # spent 29µs (9+20) within CHI::Stats::BEGIN@4 which was called:
# once (9µs+20µs) by CHI::BEGIN@5 at line 4 # spent 29µs making 1 call to CHI::Stats::BEGIN@4
# spent 7µs making 1 call to List::Util::import |
| 5 | 2 | 52µs | 2 | 4.53ms | # spent 3.30ms (426µs+2.87) within CHI::Stats::BEGIN@5 which was called:
# once (426µs+2.87ms) by CHI::BEGIN@5 at line 5 # spent 3.30ms making 1 call to CHI::Stats::BEGIN@5
# spent 1.23ms making 1 call to Log::Any::import |
| 6 | 2 | 60µs | 2 | 8.34ms | # spent 7.16ms (2.12+5.04) within CHI::Stats::BEGIN@6 which was called:
# once (2.12ms+5.04ms) by CHI::BEGIN@5 at line 6 # spent 7.16ms making 1 call to CHI::Stats::BEGIN@6
# spent 1.18ms making 1 call to Moo::import |
| 7 | 2 | 12µs | 2 | 7µs | # spent 6µs (5+1) within CHI::Stats::BEGIN@7 which was called:
# once (5µs+1µs) by CHI::BEGIN@5 at line 7 # spent 6µs making 1 call to CHI::Stats::BEGIN@7
# spent 1µs making 1 call to strict::import |
| 8 | 2 | 536µs | 2 | 24µs | # spent 19µs (14+5) within CHI::Stats::BEGIN@8 which was called:
# once (14µs+5µs) by CHI::BEGIN@5 at line 8 # spent 19µs making 1 call to CHI::Stats::BEGIN@8
# spent 5µs making 1 call to warnings::import |
| 9 | |||||
| 10 | 1 | 2µs | 1 | 10.6ms | has 'chi_root_class' => ( is => 'ro' ); # spent 10.6ms making 1 call to Moo::has |
| 11 | 1 | 5µs | 1 | 97µs | has 'data' => ( is => 'ro', default => sub { {} } ); # spent 97µs making 1 call to Moo::has |
| 12 | 1 | 2µs | 1 | 117µs | has 'enabled' => ( is => 'rwp', default => sub { 0 } ); # spent 117µs making 1 call to Moo::has |
| 13 | 1 | 2µs | 1 | 75µs | has 'start_time' => ( is => 'ro', default => sub { time } ); # spent 75µs making 1 call to Moo::has |
| 14 | |||||
| 15 | sub enable { $_[0]->_set_enabled(1) } | ||||
| 16 | sub disable { $_[0]->_set_enabled(0) } | ||||
| 17 | |||||
| 18 | sub flush { | ||||
| 19 | my ($self) = @_; | ||||
| 20 | |||||
| 21 | my $data = $self->data; | ||||
| 22 | foreach my $label ( sort keys %$data ) { | ||||
| 23 | my $label_stats = $data->{$label}; | ||||
| 24 | foreach my $namespace ( sort keys(%$label_stats) ) { | ||||
| 25 | my $namespace_stats = $label_stats->{$namespace}; | ||||
| 26 | if (%$namespace_stats) { | ||||
| 27 | $self->log_namespace_stats( $label, $namespace, | ||||
| 28 | $namespace_stats ); | ||||
| 29 | } | ||||
| 30 | } | ||||
| 31 | } | ||||
| 32 | $self->clear(); | ||||
| 33 | } | ||||
| 34 | |||||
| 35 | sub log_namespace_stats { | ||||
| 36 | my ( $self, $label, $namespace, $namespace_stats ) = @_; | ||||
| 37 | |||||
| 38 | my %data = ( | ||||
| 39 | label => $label, | ||||
| 40 | end_time => time(), | ||||
| 41 | namespace => $namespace, | ||||
| 42 | root_class => $self->chi_root_class, | ||||
| 43 | %$namespace_stats | ||||
| 44 | ); | ||||
| 45 | %data = | ||||
| 46 | map { /_ms$/ ? ( $_, int( $data{$_} ) ) : ( $_, $data{$_} ) } | ||||
| 47 | keys(%data); | ||||
| 48 | $log->infof( 'CHI stats: %s', json_encode( \%data ) ); | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | sub format_time { | ||||
| 52 | my ($time) = @_; | ||||
| 53 | |||||
| 54 | my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = | ||||
| 55 | localtime($time); | ||||
| 56 | return sprintf( | ||||
| 57 | "%04d%02d%02d:%02d:%02d:%02d", | ||||
| 58 | $year + 1900, | ||||
| 59 | $mon + 1, $mday, $hour, $min, $sec | ||||
| 60 | ); | ||||
| 61 | } | ||||
| 62 | |||||
| 63 | sub stats_for_driver { | ||||
| 64 | my ( $self, $cache ) = @_; | ||||
| 65 | |||||
| 66 | my $stats = | ||||
| 67 | ( $self->data->{ $cache->label }->{ $cache->namespace } ||= {} ); | ||||
| 68 | $stats->{start_time} ||= time; | ||||
| 69 | return $stats; | ||||
| 70 | } | ||||
| 71 | |||||
| 72 | sub parse_stats_logs { | ||||
| 73 | my $self = shift; | ||||
| 74 | my ( %results_hash, @results, %numeric_fields_seen ); | ||||
| 75 | foreach my $log_file (@_) { | ||||
| 76 | my $logfh; | ||||
| 77 | if ( ref($log_file) ) { | ||||
| 78 | $logfh = $log_file; | ||||
| 79 | } | ||||
| 80 | else { | ||||
| 81 | open( $logfh, '<', $log_file ) or die "cannot open $log_file: $!"; | ||||
| 82 | $log->infof( "processing '%s'", $log_file ); | ||||
| 83 | } | ||||
| 84 | while ( my $line = <$logfh> ) { | ||||
| 85 | chomp($line); | ||||
| 86 | if ( my ($json) = ( $line =~ /CHI stats: (\{.*\})$/ ) ) { | ||||
| 87 | my %hash = %{ json_decode($json) }; | ||||
| 88 | my $root_class = delete( $hash{root_class} ); | ||||
| 89 | my $namespace = delete( $hash{namespace} ); | ||||
| 90 | my $label = delete( $hash{label} ); | ||||
| 91 | my $results_set = | ||||
| 92 | ( $results_hash{$root_class}->{$label}->{$namespace} ||= {} ); | ||||
| 93 | if ( !%$results_set ) { | ||||
| 94 | $results_set->{root_class} = $root_class; | ||||
| 95 | $results_set->{namespace} = $namespace; | ||||
| 96 | $results_set->{label} = $label; | ||||
| 97 | push( @results, $results_set ); | ||||
| 98 | } | ||||
| 99 | while ( my ( $key, $value ) = each(%hash) ) { | ||||
| 100 | next if $key =~ /_time$/; | ||||
| 101 | $results_set->{$key} += $value; | ||||
| 102 | $numeric_fields_seen{$key}++; | ||||
| 103 | } | ||||
| 104 | } | ||||
| 105 | } | ||||
| 106 | } | ||||
| 107 | my @numeric_fields = sort( keys(%numeric_fields_seen) ); | ||||
| 108 | |||||
| 109 | my $sum = sub { | ||||
| 110 | my ( $rs, $name, @fields ) = @_; | ||||
| 111 | if ( grep { $rs->{$_} } @fields ) { | ||||
| 112 | $rs->{$name} = sum( map { $rs->{$_} || 0 } @fields ); | ||||
| 113 | } | ||||
| 114 | }; | ||||
| 115 | foreach my $rs (@results) { | ||||
| 116 | $sum->( $rs, 'misses', 'absent_misses', 'expired_misses' ); | ||||
| 117 | $sum->( $rs, 'gets', 'hits', 'misses' ); | ||||
| 118 | } | ||||
| 119 | |||||
| 120 | my %totals = map { ( $_, 'TOTALS' ) } qw(root_class namespace label); | ||||
| 121 | foreach my $field (@numeric_fields) { | ||||
| 122 | $totals{$field} = sum( map { $_->{$field} || 0 } @results ); | ||||
| 123 | } | ||||
| 124 | push( @results, \%totals ); | ||||
| 125 | |||||
| 126 | my $divide = sub { | ||||
| 127 | my ( $rs, $name, $top, $bottom ) = @_; | ||||
| 128 | if ( $rs->{$top} && $rs->{$bottom} ) { | ||||
| 129 | $rs->{$name} = ( $rs->{$top} / $rs->{$bottom} ); | ||||
| 130 | } | ||||
| 131 | }; | ||||
| 132 | |||||
| 133 | foreach my $rs (@results) { | ||||
| 134 | $divide->( $rs, 'avg_compute_time_ms', 'compute_time_ms', 'computes' ); | ||||
| 135 | $divide->( $rs, 'avg_get_time_ms', 'get_time_ms', 'gets' ); | ||||
| 136 | $divide->( $rs, 'avg_set_time_ms', 'set_time_ms', 'sets' ); | ||||
| 137 | $divide->( $rs, 'avg_set_key_size', 'set_key_size', 'sets' ); | ||||
| 138 | $divide->( $rs, 'avg_set_value_size', 'set_value_size', 'sets' ); | ||||
| 139 | $divide->( $rs, 'hit_rate', 'hits', 'gets' ); | ||||
| 140 | } | ||||
| 141 | return \@results; | ||||
| 142 | } | ||||
| 143 | |||||
| 144 | sub clear { | ||||
| 145 | my ($self) = @_; | ||||
| 146 | |||||
| 147 | my $data = $self->data; | ||||
| 148 | foreach my $key ( keys %{$data} ) { | ||||
| 149 | %{ $data->{$key} } = (); | ||||
| 150 | } | ||||
| 151 | $self->{start_time} = time; | ||||
| 152 | } | ||||
| 153 | |||||
| 154 | 1 | 6µs | 1; | ||
| 155 | |||||
| 156 | __END__ |