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 74     74   1310 use v5.18;
  74         263  
5 74     74   444 use strict;
  74         144  
  74         1564  
6 74     74   338 use warnings;
  74         129  
  74         2140  
7 74     74   375 use warnings qw( FATAL utf8 );
  74         153  
  74         2273  
8 74     74   482 use utf8;
  74         157  
  74         408  
9 74     74   1790 use open qw( :std :utf8 );
  74         172  
  74         355  
10 74     74   10123 use Unicode::Normalize qw( NFC );
  74         164  
  74         3901  
11 74     74   475 use Unicode::Collate;
  74         146  
  74         2297  
12 74     74   436 use Encode qw( decode );
  74         151  
  74         4164  
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 74     74   15850 use Carp;
  74         168  
  74         104138  
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.4
29              
30             =cut
31              
32             our $VERSION = '2.4';
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 45 sub functions { my $self = shift; $self->{ 'functions' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'functions' }; }
  25         72  
  25         69  
65 104 50   104 1 134 sub options { my $self = shift; $self->{ 'options' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'options' }; }
  104         168  
  104         405  
66 126 50   126 1 179 sub timings { my $self = shift; $self->{ 'timings' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'timings' }; }
  126         210  
  126         475  
67              
68 52 100   52 1 113 sub option { my $self = shift; my $name = shift; $self->options->{ $name } = $_[ 0 ] if 0 < scalar @_; return $self->options->{ $name }; }
  52         68  
  52         120  
  52         87  
69 65 100   65 1 83 sub timing { my $self = shift; my $name = shift; $self->timings->{ $name } = $_[ 0 ] if 0 < scalar @_; return $self->timings->{ $name }; }
  65         80  
  65         235  
  65         102  
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 30 my $class = shift;
89 9         32 my %args = @_;
90 9         23 my $self = bless {}, $class;
91 9         33 $self->{ 'options' } = {};
92 9         19 $self->{ 'timings' } = {};
93 9 100       25 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         12 $self->_parse_struct( $args{ 'struct' } );
96             }
97             else {
98 6         21 $self->_parse_lines( $args{ 'lines' } );
99             }
100 9         56 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         9 my $output = "JIT:\n";
112 4 50       9 if ( $self->functions ) {
113 4         14 $output .= sprintf " Functions: %s\n", $self->functions;
114             }
115 4 50       9 if ( 0 < scalar keys %{ $self->options } ) {
  4         10  
116 4 100       6 my $str = join( ', ', map { "$_ " . ( $self->option( $_ ) ? "true" : "false" ) } keys %{ $self->options } );
  16         39  
  4         9  
117 4         33 $output .= sprintf " Options: %s\n", $str;
118             }
119 4 50       9 if ( 0 < scalar keys %{ $self->timings } ) {
  4         10  
120 4         10 my $str = join( ', ', map { "$_ " . $self->timing( $_ ) . ' ms' } keys %{ $self->timings } );
  20         45  
  4         8  
121 4         30 $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   8 my $self = shift;
135 3         6 my $struct = shift;
136 3         13 $self->functions( $struct->{ 'Functions' } );
137 3         5 for my $key ( keys %{ $struct->{ 'Options' } } ) {
  3         16  
138 12         18 my $val = $struct->{ 'Options' }->{ $key };
139 12 100       68 $val = undef if $val eq 'false';
140 12 100       138 $self->option( $key, $val ? 1 : 0 );
141             }
142 3         10 for my $key ( keys %{ $struct->{ 'Timing' } } ) {
  3         11  
143 15         31 $self->timing( $key, $struct->{ 'Timing' }->{ $key } );
144             }
145 3         9 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         10 my $lines = shift;
157 6         9 for my $line ( @{ $lines } ) {
  6         15  
158 24 100       162 if ( $line =~ m{ \A \s* Functions: \s+ (\d+) \s* \z }xms ) {
    100          
    100          
159 6         21 $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         22 for my $e ( @parts ) {
164 24         152 $e =~ s/\s*(true|false)\z//;
165 24 100       81 $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         77 my @parts = split( /\s*,\s*/, $1 );
170 6         26 for my $e ( @parts ) {
171 30         175 $e =~ s/\s*(\d+\.\d+)\s+ms\z//;
172 30         98 $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