File Coverage

blib/lib/Pg/Explain/JIT.pm
Criterion Covered Total %
statement 98 98 100.0
branch 28 34 82.3
condition n/a
subroutine 19 19 100.0
pod 7 7 100.0
total 152 158 96.2


line stmt bran cond sub pod time code
1             package Pg::Explain::JIT;
2              
3             # UTF8 boilerplace, per http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/
4 73     73   960 use v5.18;
  73         254  
5 73     73   422 use strict;
  73         148  
  73         1611  
6 73     73   344 use warnings;
  73         160  
  73         2184  
7 73     73   359 use warnings qw( FATAL utf8 );
  73         167  
  73         2314  
8 73     73   403 use utf8;
  73         158  
  73         400  
9 73     73   1844 use open qw( :std :utf8 );
  73         145  
  73         393  
10 73     73   9820 use Unicode::Normalize qw( NFC );
  73         154  
  73         3882  
11 73     73   475 use Unicode::Collate;
  73         152  
  73         2404  
12 73     73   403 use Encode qw( decode );
  73         188  
  73         4338  
13              
14             if ( grep /\P{ASCII}/ => @ARGV ) {
15             @ARGV = map { decode( 'UTF-8', $_ ) } @ARGV;
16             }
17              
18             # UTF8 boilerplace, per http://stackoverflow.com/questions/6162484/why-does-modern-perl-avoid-utf-8-by-default/
19              
20 73     73   15842 use Carp;
  73         160  
  73         104877  
21              
22             =head1 NAME
23              
24             Pg::Explain::JIT - Stores information about JIT from PostgreSQL's explain analyze.
25              
26             =head1 VERSION
27              
28             Version 2.3
29              
30             =cut
31              
32             our $VERSION = '2.3';
33              
34             =head1 SYNOPSIS
35              
36             This module provides wrapper around various information about JIT that can be parsed from plans returned by explain analyze in PostgreSQL.
37              
38             Object of this class is created by Pg::Explain when parsing plan, and is later available as $explain->jit.
39              
40             =head1 ACCESSORS
41              
42             =head2 functions( [val] )
43              
44             Returns/sets number of functions / operators that were JIT compiled.
45              
46             =head2 options( [val] )
47              
48             Returns/sets whole hashref of options that were used by JIT compiler.
49              
50             =head2 option( name, [val] )
51              
52             Returns/sets value of single option that was used by JIT compiler.
53              
54             =head2 timings( [val] )
55              
56             Returns/sets whole hashref of how long it took to process various stages of JIT compiling.
57              
58             =head2 timing( name, [val] )
59              
60             Returns/sets time of single stage of JIT compiling.
61              
62             =cut
63              
64 25 100   25 1 36 sub functions { my $self = shift; $self->{ 'functions' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'functions' }; }
  25         80  
  25         70  
65 104 50   104 1 137 sub options { my $self = shift; $self->{ 'options' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'options' }; }
  104         177  
  104         414  
66 126 50   126 1 164 sub timings { my $self = shift; $self->{ 'timings' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'timings' }; }
  126         210  
  126         426  
67              
68 52 100   52 1 110 sub option { my $self = shift; my $name = shift; $self->options->{ $name } = $_[ 0 ] if 0 < scalar @_; return $self->options->{ $name }; }
  52         70  
  52         124  
  52         100  
69 65 100   65 1 85 sub timing { my $self = shift; my $name = shift; $self->timings->{ $name } = $_[ 0 ] if 0 < scalar @_; return $self->timings->{ $name }; }
  65         122  
  65         247  
  65         121  
70              
71             =head1 METHODS
72              
73             =head2 new
74              
75             Object constructor. Should get one of:
76              
77             =over
78              
79             =item * struct - hashref based on parsing of JSON/YAML/XML plans
80              
81             =item * lines - arrayref of strings containling lines describing JIT from text plans
82              
83             =back
84              
85             =cut
86              
87             sub new {
88 9     9 1 28 my $class = shift;
89 9         34 my %args = @_;
90 9         32 my $self = bless {}, $class;
91 9         31 $self->{ 'options' } = {};
92 9         22 $self->{ 'timings' } = {};
93 9 100       24 if ( $args{ 'struct' } ) {
94 3 50       10 croak "Pg::Explain::JIT constructor cannot be called with both struct and lines!" if $args{ 'lines' };
95 3         14 $self->_parse_struct( $args{ 'struct' } );
96             }
97             else {
98 6         23 $self->_parse_lines( $args{ 'lines' } );
99             }
100 9         63 return $self;
101             }
102              
103             =head2 as_text
104              
105             Returns text that represents the JIT info as in explain analyze output for 'text' format.
106              
107             =cut
108              
109             sub as_text {
110 4     4 1 8 my $self = shift;
111 4         10 my $output = "JIT:\n";
112 4 50       11 if ( $self->functions ) {
113 4         12 $output .= sprintf " Functions: %s\n", $self->functions;
114             }
115 4 50       9 if ( 0 < scalar keys %{ $self->options } ) {
  4         12  
116 4 100       11 my $str = join( ', ', map { "$_ " . ( $self->option( $_ ) ? "true" : "false" ) } keys %{ $self->options } );
  16         44  
  4         10  
117 4         34 $output .= sprintf " Options: %s\n", $str;
118             }
119 4 50       9 if ( 0 < scalar keys %{ $self->timings } ) {
  4         9  
120 4         7 my $str = join( ', ', map { "$_ " . $self->timing( $_ ) . ' ms' } keys %{ $self->timings } );
  20         50  
  4         11  
121 4         32 $output .= sprintf " Timing: %s\n", $str;
122             }
123             }
124              
125             =head1 INTERNAL METHODS
126              
127             =head2 _parse_struct
128              
129             Parses given struct, as returned from parsing JSON/YAML/XML formats.
130              
131             =cut
132              
133             sub _parse_struct {
134 3     3   10 my $self = shift;
135 3         5 my $struct = shift;
136 3         16 $self->functions( $struct->{ 'Functions' } );
137 3         6 for my $key ( keys %{ $struct->{ 'Options' } } ) {
  3         15  
138 12         25 my $val = $struct->{ 'Options' }->{ $key };
139 12 100       67 $val = undef if $val eq 'false';
140 12 100       144 $self->option( $key, $val ? 1 : 0 );
141             }
142 3         8 for my $key ( keys %{ $struct->{ 'Timing' } } ) {
  3         15  
143 15         46 $self->timing( $key, $struct->{ 'Timing' }->{ $key } );
144             }
145 3         22 return;
146             }
147              
148             =head2 _parse_lines
149              
150             Parses given lines, as parsed out of TEXT explain format.
151              
152             =cut
153              
154             sub _parse_lines {
155 6     6   13 my $self = shift;
156 6         8 my $lines = shift;
157 6         11 for my $line ( @{ $lines } ) {
  6         29  
158 24 100       202 if ( $line =~ m{ \A \s* Functions: \s+ (\d+) \s* \z }xms ) {
    100          
    100          
159 6         26 $self->functions( $1 );
160             }
161             elsif ( $line =~ m{ \A \s* Options: \s+ (\S.*\S) \s* \z }xms ) {
162 6         76 my @parts = split( /\s*,\s*/, $1 );
163 6         20 for my $e ( @parts ) {
164 24         183 $e =~ s/\s*(true|false)\z//;
165 24 100       96 $self->option( $e, $1 eq "true" ? 1 : 0 );
166             }
167             }
168             elsif ( $line =~ m{ \A \s* Timing: \s+ (\S.*\S) \s* \z }xms ) {
169 6         83 my @parts = split( /\s*,\s*/, $1 );
170 6         25 for my $e ( @parts ) {
171 30         187 $e =~ s/\s*(\d+\.\d+)\s+ms\z//;
172 30         99 $self->timing( $e, $1 );
173             }
174             }
175             }
176             }
177              
178             =head1 AUTHOR
179              
180             hubert depesz lubaczewski, C<< >>
181              
182             =head1 BUGS
183              
184             Please report any bugs or feature requests to C.
185              
186             =head1 SUPPORT
187              
188             You can find documentation for this module with the perldoc command.
189              
190             perldoc Pg::Explain::JIT
191              
192             =head1 COPYRIGHT & LICENSE
193              
194             Copyright 2008-2021 hubert depesz lubaczewski, all rights reserved.
195              
196             This program is free software; you can redistribute it and/or modify it
197             under the same terms as Perl itself.
198              
199              
200             =cut
201              
202             1; # End of Pg::Explain::JIT