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 72     72   868 use v5.18;
  72         211  
5 72     72   345 use strict;
  72         143  
  72         1330  
6 72     72   284 use warnings;
  72         120  
  72         1941  
7 72     72   332 use warnings qw( FATAL utf8 );
  72         146  
  72         1985  
8 72     72   329 use utf8;
  72         121  
  72         365  
9 72     72   1451 use open qw( :std :utf8 );
  72         116  
  72         339  
10 72     72   8616 use Unicode::Normalize qw( NFC );
  72         124  
  72         3549  
11 72     72   418 use Unicode::Collate;
  72         130  
  72         1985  
12 72     72   333 use Encode qw( decode );
  72         143  
  72         3926  
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 72     72   14085 use Carp;
  72         125  
  72         88842  
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.2
29              
30             =cut
31              
32             our $VERSION = '2.2';
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 38 sub functions { my $self = shift; $self->{ 'functions' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'functions' }; }
  25         62  
  25         60  
65 104 50   104 1 113 sub options { my $self = shift; $self->{ 'options' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'options' }; }
  104         151  
  104         331  
66 126 50   126 1 133 sub timings { my $self = shift; $self->{ 'timings' } = $_[ 0 ] if 0 < scalar @_; return $self->{ 'timings' }; }
  126         168  
  126         366  
67              
68 52 100   52 1 160 sub option { my $self = shift; my $name = shift; $self->options->{ $name } = $_[ 0 ] if 0 < scalar @_; return $self->options->{ $name }; }
  52         67  
  52         102  
  52         85  
69 65 100   65 1 75 sub timing { my $self = shift; my $name = shift; $self->timings->{ $name } = $_[ 0 ] if 0 < scalar @_; return $self->timings->{ $name }; }
  65         74  
  65         201  
  65         93  
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 20 my $class = shift;
89 9         27 my %args = @_;
90 9         22 my $self = bless {}, $class;
91 9         34 $self->{ 'options' } = {};
92 9         25 $self->{ 'timings' } = {};
93 9 100       22 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         13 $self->_parse_struct( $args{ 'struct' } );
96             }
97             else {
98 6         21 $self->_parse_lines( $args{ 'lines' } );
99             }
100 9         46 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         7 my $output = "JIT:\n";
112 4 50       9 if ( $self->functions ) {
113 4         9 $output .= sprintf " Functions: %s\n", $self->functions;
114             }
115 4 50       7 if ( 0 < scalar keys %{ $self->options } ) {
  4         10  
116 4 100       7 my $str = join( ', ', map { "$_ " . ( $self->option( $_ ) ? "true" : "false" ) } keys %{ $self->options } );
  16         86  
  4         9  
117 4         17 $output .= sprintf " Options: %s\n", $str;
118             }
119 4 50       5 if ( 0 < scalar keys %{ $self->timings } ) {
  4         10  
120 4         15 my $str = join( ', ', map { "$_ " . $self->timing( $_ ) . ' ms' } keys %{ $self->timings } );
  20         37  
  4         7  
121 4         25 $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   7 my $self = shift;
135 3         7 my $struct = shift;
136 3         14 $self->functions( $struct->{ 'Functions' } );
137 3         5 for my $key ( keys %{ $struct->{ 'Options' } } ) {
  3         13  
138 12         18 my $val = $struct->{ 'Options' }->{ $key };
139 12 100       58 $val = undef if $val eq 'false';
140 12 100       114 $self->option( $key, $val ? 1 : 0 );
141             }
142 3         6 for my $key ( keys %{ $struct->{ 'Timing' } } ) {
  3         12  
143 15         28 $self->timing( $key, $struct->{ 'Timing' }->{ $key } );
144             }
145 3         7 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   10 my $self = shift;
156 6         14 my $lines = shift;
157 6         8 for my $line ( @{ $lines } ) {
  6         15  
158 24 100       128 if ( $line =~ m{ \A \s* Functions: \s+ (\d+) \s* \z }xms ) {
    100          
    100          
159 6         27 $self->functions( $1 );
160             }
161             elsif ( $line =~ m{ \A \s* Options: \s+ (\S.*\S) \s* \z }xms ) {
162 6         59 my @parts = split( /\s*,\s*/, $1 );
163 6         17 for my $e ( @parts ) {
164 24         120 $e =~ s/\s*(true|false)\z//;
165 24 100       75 $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         63 my @parts = split( /\s*,\s*/, $1 );
170 6         15 for my $e ( @parts ) {
171 30         145 $e =~ s/\s*(\d+\.\d+)\s+ms\z//;
172 30         86 $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