Filename | /home/ss5/perl5/perlbrew/perls/perl-5.22.0/lib/site_perl/5.22.0/BenchmarkAnything/Storage/Frontend/Lib.pm |
Statements | Executed 2062 statements in 10.3ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 9.88ms | 58.9ms | connect | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 9.64ms | 53.0s | process_raw_result_queue | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 699µs | 996µs | BEGIN@10 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 420µs | 329ms | BEGIN@280 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 254µs | 97.0ms | new | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 19µs | 26µs | disconnect | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 15µs | 15µs | BEGIN@1.22 | main::
1 | 1 | 1 | 12µs | 34.3ms | gc | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 9µs | 26µs | BEGIN@27 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 8µs | 16µs | BEGIN@275 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 7µs | 16µs | BEGIN@189 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 6µs | 9µs | BEGIN@2 | main::
1 | 1 | 1 | 6µs | 12µs | BEGIN@36 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 6µs | 11µs | BEGIN@51 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 6µs | 11µs | BEGIN@66 | BenchmarkAnything::Storage::Frontend::Lib::
1 | 1 | 1 | 5µs | 15µs | BEGIN@3 | main::
0 | 0 | 0 | 0s | 0s | _are_you_sure | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _default_additional_keys | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _format_flat | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _format_flat_inner_array | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _format_flat_inner_hash | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _format_flat_inner_scalar | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _format_flat_outer | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _get_additional_key_id | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _get_base_url | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _get_benchmark_operators | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _get_user_agent | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | _output_format | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | add | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | createdb | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | getpoint | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | init_search_engine | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | init_workdir | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | listkeys | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | listnames | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | search | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | stats | BenchmarkAnything::Storage::Frontend::Lib::
0 | 0 | 0 | 0s | 0s | sync_search_engine | BenchmarkAnything::Storage::Frontend::Lib::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | 2 | 31µs | 1 | 15µs | # spent 15µs within main::BEGIN@1.22 which was called:
# once (15µs+0s) by main::_connect at line 1 # spent 15µs making 1 call to main::BEGIN@1.22 |
2 | 2 | 15µs | 2 | 12µs | # spent 9µs (6+3) within main::BEGIN@2 which was called:
# once (6µs+3µs) by main::_connect at line 2 # spent 9µs making 1 call to main::BEGIN@2
# spent 3µs making 1 call to strict::import |
3 | 2 | 36µs | 2 | 25µs | # spent 15µs (5+10) within main::BEGIN@3 which was called:
# once (5µs+10µs) by main::_connect at line 3 # spent 15µs making 1 call to main::BEGIN@3
# spent 10µs making 1 call to warnings::import |
4 | package BenchmarkAnything::Storage::Frontend::Lib; | ||||
5 | # git description: v0.021-0-g0676cfd | ||||
6 | |||||
7 | 1 | 400ns | our $AUTHORITY = 'cpan:SCHWIGON'; | ||
8 | # ABSTRACT: Basic functions to access a BenchmarkAnything store | ||||
9 | 1 | 400ns | $BenchmarkAnything::Storage::Frontend::Lib::VERSION = '0.022'; | ||
10 | 2 | 135µs | 2 | 1.05ms | # spent 996µs (699+297) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@10 which was called:
# once (699µs+297µs) by main::_connect at line 10 # spent 996µs making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@10
# spent 56µs making 1 call to Exporter::import |
11 | |||||
12 | |||||
13 | sub new | ||||
14 | # spent 97.0ms (254µs+96.8) within BenchmarkAnything::Storage::Frontend::Lib::new which was called:
# once (254µs+96.8ms) by main::_connect at line 167 of /home/ss5/perl5/perlbrew/perls/perl-5.22.0/bin/benchmarkanything-storage | ||||
15 | 1 | 500ns | my $class = shift; | ||
16 | 1 | 4µs | my $self = bless { @_ }, $class; | ||
17 | 1 | 59µs | require BenchmarkAnything::Config; | ||
18 | 1 | 6µs | 1 | 37.9ms | $self->{config} = BenchmarkAnything::Config->new(cfgfile => $self->{cfgfile}) unless $self->{noconfig}; # spent 37.9ms making 1 call to BenchmarkAnything::Config::new |
19 | 1 | 3µs | 1 | 58.9ms | $self->connect unless $self->{noconnect}; # spent 58.9ms making 1 call to BenchmarkAnything::Storage::Frontend::Lib::connect |
20 | 1 | 4µs | return $self; | ||
21 | } | ||||
22 | |||||
23 | sub _format_flat_inner_scalar | ||||
24 | { | ||||
25 | my ($self, $result, $opt) = @_; | ||||
26 | |||||
27 | 2 | 41µs | 2 | 42µs | # spent 26µs (9+16) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@27 which was called:
# once (9µs+16µs) by main::_connect at line 27 # spent 26µs making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@27
# spent 16µs making 1 call to warnings::unimport |
28 | |||||
29 | return "$result"; | ||||
30 | } | ||||
31 | |||||
32 | sub _format_flat_inner_array | ||||
33 | { | ||||
34 | my ($self, $result, $opt) = @_; | ||||
35 | |||||
36 | 2 | 65µs | 2 | 18µs | # spent 12µs (6+6) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@36 which was called:
# once (6µs+6µs) by main::_connect at line 36 # spent 12µs making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@36
# spent 6µs making 1 call to warnings::unimport |
37 | |||||
38 | return | ||||
39 | join($opt->{separator}, | ||||
40 | map { | ||||
41 | # only SCALARS allowed (where reftype returns undef) | ||||
42 | die "benchmarkanything: unsupported innermost nesting (".reftype($_).") for 'flat' output.\n" if defined reftype($_); | ||||
43 | "".$_ | ||||
44 | } @$result); | ||||
45 | } | ||||
46 | |||||
47 | sub _format_flat_inner_hash | ||||
48 | { | ||||
49 | my ($self, $result, $opt) = @_; | ||||
50 | |||||
51 | 2 | 76µs | 2 | 17µs | # spent 11µs (6+6) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@51 which was called:
# once (6µs+6µs) by main::_connect at line 51 # spent 11µs making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@51
# spent 6µs making 1 call to warnings::unimport |
52 | |||||
53 | return | ||||
54 | join($opt->{separator}, | ||||
55 | map { my $v = $result->{$_}; | ||||
56 | # only SCALARS allowed (where reftype returns undef) | ||||
57 | die "benchmarkanything: unsupported innermost nesting (".reftype($v).") for 'flat' output.\n" if defined reftype($v); | ||||
58 | "$_=".$v | ||||
59 | } keys %$result); | ||||
60 | } | ||||
61 | |||||
62 | sub _format_flat_outer | ||||
63 | { | ||||
64 | my ($self, $result, $opt) = @_; | ||||
65 | |||||
66 | 2 | 443µs | 2 | 17µs | # spent 11µs (6+6) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@66 which was called:
# once (6µs+6µs) by main::_connect at line 66 # spent 11µs making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@66
# spent 6µs making 1 call to warnings::unimport |
67 | |||||
68 | my $output = ""; | ||||
69 | die "benchmarkanything: can not flatten data structure (undef) - try other output format.\n" unless defined $result; | ||||
70 | |||||
71 | my $A = ""; my $B = ""; if ($opt->{fb}) { $A = "["; $B = "]" } | ||||
72 | my $fi = $opt->{fi}; | ||||
73 | |||||
74 | if (!defined reftype $result) { # SCALAR | ||||
75 | $output .= $result."\n"; # stringify | ||||
76 | } | ||||
77 | elsif (reftype $result eq 'ARRAY') { | ||||
78 | for (my $i=0; $i<@$result; $i++) { | ||||
79 | my $entry = $result->[$i]; | ||||
80 | my $prefix = $fi ? "$i:" : ""; | ||||
81 | if (!defined reftype $entry) { # SCALAR | ||||
82 | $output .= $prefix.$A.$self->_format_flat_inner_scalar($entry, $opt)."$B\n"; | ||||
83 | } | ||||
84 | elsif (reftype $entry eq 'ARRAY') { | ||||
85 | $output .= $prefix.$A.$self->_format_flat_inner_array($entry, $opt)."$B\n"; | ||||
86 | } | ||||
87 | elsif (reftype $entry eq 'HASH') { | ||||
88 | $output .= $prefix.$A.$self->_format_flat_inner_hash($entry, $opt)."$B\n"; | ||||
89 | } | ||||
90 | else { | ||||
91 | die "benchmarkanything: can not flatten data structure (".reftype($entry).").\n"; | ||||
92 | } | ||||
93 | } | ||||
94 | } | ||||
95 | elsif (reftype $result eq 'HASH') { | ||||
96 | my @keys = keys %$result; | ||||
97 | foreach my $key (@keys) { | ||||
98 | my $entry = $result->{$key}; | ||||
99 | if (!defined reftype $entry) { # SCALAR | ||||
100 | $output .= "$key:".$self->_format_flat_inner_scalar($entry, $opt)."\n"; | ||||
101 | } | ||||
102 | elsif (reftype $entry eq 'ARRAY') { | ||||
103 | $output .= "$key:".$self->_format_flat_inner_array($entry, $opt)."\n"; | ||||
104 | } | ||||
105 | elsif (reftype $entry eq 'HASH') { | ||||
106 | $output .= "$key:".$self->_format_flat_inner_hash($entry, $opt)."\n"; | ||||
107 | } | ||||
108 | else { | ||||
109 | die "benchmarkanything: can not flatten data structure (".reftype($entry).").\n"; | ||||
110 | } | ||||
111 | } | ||||
112 | } | ||||
113 | else { | ||||
114 | die "benchmarkanything: can not flatten data structure (".reftype($result).") - try other output format.\n"; | ||||
115 | } | ||||
116 | |||||
117 | return $output; | ||||
118 | } | ||||
119 | |||||
120 | sub _format_flat | ||||
121 | { | ||||
122 | my ($self, $result, $opt) = @_; | ||||
123 | |||||
124 | # ensure array container | ||||
125 | # for consistent output in 'getpoint' and 'search' | ||||
126 | my $resultlist = reftype($result) eq 'ARRAY' ? $result : [$result]; | ||||
127 | |||||
128 | my $output = ""; | ||||
129 | $opt->{separator} = ";" unless defined $opt->{separator}; | ||||
130 | $output .= $self->_format_flat_outer($resultlist, $opt); | ||||
131 | return $output; | ||||
132 | } | ||||
133 | |||||
134 | |||||
135 | sub _output_format | ||||
136 | { | ||||
137 | my ($self, $data, $opt) = @_; | ||||
138 | |||||
139 | my $output = ""; | ||||
140 | my $outtype = $opt->{outtype} || 'json'; | ||||
141 | |||||
142 | if ($outtype eq "yaml") | ||||
143 | { | ||||
144 | require YAML::Any; | ||||
145 | $output .= YAML::Any::Dump($data); | ||||
146 | } | ||||
147 | elsif ($outtype eq "json") | ||||
148 | { | ||||
149 | eval "use JSON -convert_blessed_universally"; | ||||
150 | my $json = JSON->new->allow_nonref->pretty->allow_blessed->convert_blessed; | ||||
151 | $output .= $json->encode($data); | ||||
152 | } | ||||
153 | elsif ($outtype eq "ini") { | ||||
154 | require Config::INI::Serializer; | ||||
155 | my $ini = Config::INI::Serializer->new; | ||||
156 | $output .= $ini->serialize($data); | ||||
157 | } | ||||
158 | elsif ($outtype eq "dumper") | ||||
159 | { | ||||
160 | require Data::Dumper; | ||||
161 | $output .= Data::Dumper::Dumper($data); | ||||
162 | } | ||||
163 | elsif ($outtype eq "xml") | ||||
164 | { | ||||
165 | require XML::Simple; | ||||
166 | my $xs = new XML::Simple; | ||||
167 | $output .= $xs->XMLout($data, AttrIndent => 1, KeepRoot => 1); | ||||
168 | } | ||||
169 | elsif ($outtype eq "flat") { | ||||
170 | $output .= $self->_format_flat( $data, $opt ); | ||||
171 | } | ||||
172 | else | ||||
173 | { | ||||
174 | die "benchmarkanything-storage: unrecognized output format: $outtype."; | ||||
175 | } | ||||
176 | return $output; | ||||
177 | } | ||||
178 | |||||
179 | |||||
180 | sub connect | ||||
181 | # spent 58.9ms (9.88+49.0) within BenchmarkAnything::Storage::Frontend::Lib::connect which was called:
# once (9.88ms+49.0ms) by BenchmarkAnything::Storage::Frontend::Lib::new at line 19 | ||||
182 | 1 | 500ns | my ($self) = @_; | ||
183 | |||||
184 | 1 | 800ns | my $backend = $self->{config}{benchmarkanything}{backend}; | ||
185 | 1 | 3µs | if ($backend eq 'local') | ||
186 | { | ||||
187 | 1 | 60µs | require DBI; | ||
188 | 1 | 90µs | require BenchmarkAnything::Storage::Backend::SQL; | ||
189 | 2 | 331µs | 2 | 24µs | # spent 16µs (7+8) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@189 which was called:
# once (7µs+8µs) by main::_connect at line 189 # spent 16µs making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@189
# spent 8µs making 1 call to warnings::unimport |
190 | |||||
191 | # connect | ||||
192 | 1 | 1µs | print "Connect db...\n" if $self->{debug}; | ||
193 | 1 | 2µs | my $dsn = $self->{config}{benchmarkanything}{storage}{backend}{sql}{dsn}; | ||
194 | 1 | 1µs | my $user = $self->{config}{benchmarkanything}{storage}{backend}{sql}{user}; | ||
195 | 1 | 600ns | my $password = $self->{config}{benchmarkanything}{storage}{backend}{sql}{password}; | ||
196 | 1 | 3µs | 1 | 8.29ms | my $dbh = DBI->connect($dsn, $user, $password, {'RaiseError' => 1}) # spent 8.29ms making 1 call to DBI::connect |
197 | or die "benchmarkanything: can not connect: ".$DBI::errstr; | ||||
198 | |||||
199 | # external search engine | ||||
200 | 1 | 2µs | my $searchengine = $self->{config}{benchmarkanything}{searchengine} || {}; | ||
201 | |||||
202 | # remember | ||||
203 | 1 | 1µs | $self->{dbh} = $dbh; | ||
204 | $self->{backend} = BenchmarkAnything::Storage::Backend::SQL->new({dbh => $dbh, | ||||
205 | dbh_config => $self->{config}{benchmarkanything}{storage}{backend}{sql}, | ||||
206 | debug => $self->{debug}, | ||||
207 | force => $self->{force}, | ||||
208 | verbose => $self->{verbose}, | ||||
209 | 1 | 10µs | 1 | 39.7ms | (keys %$searchengine ? (searchengine => $searchengine) : ()), # spent 39.7ms making 1 call to BenchmarkAnything::Storage::Backend::SQL::new |
210 | }); | ||||
211 | } | ||||
212 | elsif ($backend eq 'http') | ||||
213 | { | ||||
214 | my $ua = $self->_get_user_agent; | ||||
215 | my $url = $self->_get_base_url."/api/v1/hello"; | ||||
216 | die "benchmarkanything: can't connect to result storage ($url)\n" if (!$ua->get($url)->res->code or $ua->get($url)->res->code != 200); | ||||
217 | } | ||||
218 | |||||
219 | 1 | 3µs | return $self; | ||
220 | } | ||||
221 | |||||
222 | |||||
223 | sub disconnect | ||||
224 | # spent 26µs (19+7) within BenchmarkAnything::Storage::Frontend::Lib::disconnect which was called:
# once (19µs+7µs) by main::_disconnect at line 178 of /home/ss5/perl5/perlbrew/perls/perl-5.22.0/bin/benchmarkanything-storage | ||||
225 | 1 | 500ns | my ($self) = @_; | ||
226 | |||||
227 | 1 | 3µs | my $backend = $self->{config}{benchmarkanything}{backend}; | ||
228 | 1 | 1µs | if ($backend eq 'local') | ||
229 | { | ||||
230 | 1 | 1µs | if ($self->{dbh}) { | ||
231 | 1 | 17µs | 1 | 7µs | $self->{dbh}->commit unless $self->{dbh}{AutoCommit}; # spent 7µs making 1 call to DBI::common::FETCH |
232 | 1 | 1µs | undef $self->{dbh}; # setting dbh to undef does better cleanup than disconnect(); | ||
233 | } | ||||
234 | } | ||||
235 | 1 | 4µs | return $self; | ||
236 | } | ||||
237 | |||||
238 | |||||
239 | sub _are_you_sure | ||||
240 | { | ||||
241 | my ($self) = @_; | ||||
242 | |||||
243 | # DSN | ||||
244 | my $dsn = $self->{config}{benchmarkanything}{storage}{backend}{sql}{dsn}; | ||||
245 | |||||
246 | # option --really | ||||
247 | if ($self->{really}) | ||||
248 | { | ||||
249 | if ($self->{really} eq $dsn) | ||||
250 | { | ||||
251 | return 1; | ||||
252 | } | ||||
253 | else | ||||
254 | { | ||||
255 | print STDERR "DSN does not match - asking interactive.\n"; | ||||
256 | } | ||||
257 | } | ||||
258 | |||||
259 | # ask on stdin | ||||
260 | print "REALLY DROP AND RE-CREATE DATABASE TABLES [$dsn] (y/N): "; | ||||
261 | read STDIN, my $answer, 1; | ||||
262 | return 1 if $answer && $answer =~ /^y(es)?$/i; | ||||
263 | |||||
264 | # default: NO | ||||
265 | return 0; | ||||
266 | } | ||||
267 | |||||
268 | |||||
269 | sub createdb | ||||
270 | { | ||||
271 | my ($self) = @_; | ||||
272 | |||||
273 | if ($self->_are_you_sure) | ||||
274 | { | ||||
275 | 2 | 30µs | 2 | 24µs | # spent 16µs (8+8) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@275 which was called:
# once (8µs+8µs) by main::_connect at line 275 # spent 16µs making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@275
# spent 8µs making 1 call to warnings::unimport |
276 | |||||
277 | require DBI; | ||||
278 | require File::Slurper; | ||||
279 | require File::ShareDir; | ||||
280 | 2 | 1.19ms | 1 | 329ms | # spent 329ms (420µs+328) within BenchmarkAnything::Storage::Frontend::Lib::BEGIN@280 which was called:
# once (420µs+328ms) by main::_connect at line 280 # spent 329ms making 1 call to BenchmarkAnything::Storage::Frontend::Lib::BEGIN@280 |
281 | |||||
282 | my $batch = DBIx::MultiStatementDo->new(dbh => $self->{dbh}); | ||||
283 | |||||
284 | # get schema SQL according to driver | ||||
285 | my $dsn = $self->{config}{benchmarkanything}{storage}{backend}{sql}{dsn}; | ||||
286 | my ($scheme, $driver, $attr_string, $attr_hash, $driver_dsn) = DBI->parse_dsn($dsn) | ||||
287 | or die "benchmarkanything: can not parse DBI DSN '$dsn'"; | ||||
288 | my ($dbname) = $driver_dsn =~ m/database=(\w+)/g; | ||||
289 | my $sql_file = File::ShareDir::dist_file('BenchmarkAnything-Storage-Backend-SQL', "create-schema.$driver"); | ||||
290 | my $sql = File::Slurper::read_text($sql_file); | ||||
291 | $sql =~ s/^use `testrundb`;/use `$dbname`;/m if $dbname; # replace BenchmarkAnything::Storage::Backend::SQL's default | ||||
292 | |||||
293 | # execute schema SQL | ||||
294 | my @results = $batch->do($sql); | ||||
295 | if (not @results) | ||||
296 | { | ||||
297 | die "benchmarkanything: error while creating BenchmarkAnything DB: ".$batch->dbh->errstr; | ||||
298 | } | ||||
299 | |||||
300 | } | ||||
301 | |||||
302 | return; | ||||
303 | } | ||||
304 | |||||
305 | |||||
306 | sub _default_additional_keys | ||||
307 | { | ||||
308 | my ($self) = @_; | ||||
309 | |||||
310 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
311 | if ($backend eq 'local') | ||||
312 | { | ||||
313 | return { $self->{backend}->default_columns }; | ||||
314 | } | ||||
315 | else | ||||
316 | { | ||||
317 | # Hardcoded from BenchmarkAnything::Storage::Backend::SQL::Query::common, | ||||
318 | # as it is a backend-special and internal thing anyway. | ||||
319 | return { | ||||
320 | 'NAME' => 'b.bench', | ||||
321 | 'UNIT' => 'bu.bench_unit', | ||||
322 | 'VALUE' => 'bv.bench_value', | ||||
323 | 'VALUE_ID' => 'bv.bench_value_id', | ||||
324 | 'CREATED' => 'bv.created_at', | ||||
325 | }; | ||||
326 | } | ||||
327 | } | ||||
328 | |||||
- - | |||||
331 | sub _get_benchmark_operators | ||||
332 | { | ||||
333 | my ($self) = @_; | ||||
334 | |||||
335 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
336 | if ($backend eq 'local') | ||||
337 | { | ||||
338 | return [ $self->{backend}->benchmark_operators ]; | ||||
339 | } | ||||
340 | else | ||||
341 | { | ||||
342 | # Hardcoded from BenchmarkAnything::Storage::Backend::SQL::Query::common, | ||||
343 | # as it is a backend-special and internal thing anyway. | ||||
344 | return [ '=', '!=', 'like', 'not like', '<', '>', '<=', '>=' ]; | ||||
345 | } | ||||
346 | } | ||||
347 | |||||
- - | |||||
350 | sub _get_additional_key_id | ||||
351 | { | ||||
352 | my ($self, $key_name) = @_; | ||||
353 | |||||
354 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
355 | if ($backend eq 'local') | ||||
356 | { | ||||
357 | return $self->{backend}->_get_additional_key_id($key_name); | ||||
358 | } | ||||
359 | else | ||||
360 | { | ||||
361 | die "benchmarkanything: no backend '$backend' allowed here, available backends are: 'local'.\n"; | ||||
362 | } | ||||
363 | } | ||||
364 | |||||
- - | |||||
367 | sub init_workdir | ||||
368 | { | ||||
369 | my ($self) = @_; | ||||
370 | |||||
371 | require File::Basename; | ||||
372 | require File::ShareDir; | ||||
373 | require File::HomeDir; | ||||
374 | require File::Slurper; | ||||
375 | |||||
376 | my $home_ba = File::HomeDir->my_home."/.benchmarkanything"; | ||||
377 | my $command = File::Basename::basename($0); | ||||
378 | |||||
379 | if (-d $home_ba) | ||||
380 | { | ||||
381 | print "Workdir '$home_ba' already exists - skipping.\n" if $self->{verbose}; | ||||
382 | } | ||||
383 | else | ||||
384 | { | ||||
385 | require File::Path; | ||||
386 | File::Path::make_path($home_ba); | ||||
387 | } | ||||
388 | |||||
389 | foreach my $basename (qw(client.cfg server.cfg default.cfg README)) | ||||
390 | { | ||||
391 | my $source_file = File::ShareDir::dist_file('BenchmarkAnything-Storage-Frontend-Lib', "config/$basename"); | ||||
392 | my $dest_file = "$home_ba/$basename"; | ||||
393 | |||||
394 | if (! -e $dest_file) | ||||
395 | { | ||||
396 | my $content = File::Slurper::read_text($source_file); | ||||
397 | |||||
398 | # poor man's templating | ||||
399 | $content =~ s{\[%\s*CLIENTCFG\s*%\]}{$home_ba/client.cfg}g; | ||||
400 | $content =~ s{\[%\s*SERVERCFG\s*%\]}{$home_ba/server.cfg}g; | ||||
401 | $content =~ s{\[%\s*LOCALCFG\s*%\]}{$home_ba/default.cfg}g; | ||||
402 | $content =~ s{\[%\s*CFG\s*%\]}{$dest_file}g; | ||||
403 | $content =~ s{\[%\s*HOME\s*%\]}{$home_ba}g; | ||||
404 | |||||
405 | print "Create configfile: $dest_file...\n" if $self->{verbose}; | ||||
406 | open my $CFGFILE, ">", $dest_file or die "Could not create $dest_file.\n"; | ||||
407 | print $CFGFILE $content; | ||||
408 | close $CFGFILE; | ||||
409 | } | ||||
410 | else | ||||
411 | { | ||||
412 | print "Config '$dest_file' already exists - skipping.\n" if $self->{verbose}; | ||||
413 | } | ||||
414 | } | ||||
415 | |||||
416 | my $dbfile = "$home_ba/benchmarkanything.sqlite"; | ||||
417 | my $we_created_db = 0; | ||||
418 | if (! -e $dbfile) | ||||
419 | { | ||||
420 | print "Create storage: $dbfile...\n" if $self->{verbose}; | ||||
421 | __PACKAGE__->new(cfgfile => "$home_ba/default.cfg", | ||||
422 | really => "dbi:SQLite:$dbfile", | ||||
423 | )->createdb; | ||||
424 | $we_created_db = 1; | ||||
425 | } | ||||
426 | else | ||||
427 | { | ||||
428 | print "Storage '$dbfile' already exists - skipping.\n" if $self->{verbose}; | ||||
429 | } | ||||
430 | |||||
431 | if ($self->{verbose}) | ||||
432 | { | ||||
433 | print "\n"; | ||||
434 | print "By default it will use this config: $home_ba/default.cfg\n"; | ||||
435 | print "If you want another one, set it in your ~/.bash_profile:\n"; | ||||
436 | print " export BENCHMARKANYTHING_CONFIGFILE=$home_ba/client.cfg\n"; | ||||
437 | |||||
438 | unless ($we_created_db) | ||||
439 | { | ||||
440 | print "\n"; | ||||
441 | print "Initialize a new database (it asks for confirmation) with:\n"; | ||||
442 | print " $command createdb\n"; | ||||
443 | print "\nReady.\n"; | ||||
444 | } | ||||
445 | else | ||||
446 | { | ||||
447 | print "\n"; | ||||
448 | print "Create sample values like this:\n"; | ||||
449 | print qq( echo '{"BenchmarkAnythingData":[{"NAME":"benchmarkanything.hello.world", "VALUE":17.2}]}' | $command add\n); | ||||
450 | print "\n"; | ||||
451 | print "List metric names:\n"; | ||||
452 | print qq( $command listnames\n); | ||||
453 | print "\n"; | ||||
454 | print "Query sample values:\n"; | ||||
455 | print qq( echo '{"select":["NAME","VALUE"],"where":[["=","NAME","benchmarkanything.hello.world"]]}' | $command search\n); | ||||
456 | print "\n"; | ||||
457 | } | ||||
458 | } | ||||
459 | |||||
460 | return; | ||||
461 | } | ||||
462 | |||||
463 | |||||
464 | sub add | ||||
465 | { | ||||
466 | my ($self, $data) = @_; | ||||
467 | |||||
468 | # --- validate --- | ||||
469 | if (not $data) | ||||
470 | { | ||||
471 | die "benchmarkanything: no input data provided.\n"; | ||||
472 | } | ||||
473 | |||||
474 | if (not $self->{skipvalidation}) { | ||||
475 | require BenchmarkAnything::Schema; | ||||
476 | print "Verify schema...\n" if $self->{verbose}; | ||||
477 | if (not my $result = BenchmarkAnything::Schema::valid_json_schema($data)) | ||||
478 | { | ||||
479 | die "benchmarkanything: add: invalid input: ".join("; ", $result->errors)."\n"; | ||||
480 | } | ||||
481 | } | ||||
482 | |||||
483 | # --- add to storage --- | ||||
484 | |||||
485 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
486 | if ($backend eq 'local') | ||||
487 | { | ||||
488 | my $success; | ||||
489 | if ($self->{queuemode}) | ||||
490 | { | ||||
491 | # only queue for later processing | ||||
492 | print "Enqueue data [backend:local]...\n" if $self->{verbose} or $self->{debug}; | ||||
493 | $success = $self->{backend}->enqueue_multi_benchmark($data->{BenchmarkAnythingData}); | ||||
494 | } | ||||
495 | else | ||||
496 | { | ||||
497 | print "Add data [backend:local]...\n" if $self->{verbose} or $self->{debug}; | ||||
498 | # preserve order, otherwise add_multi_benchmark() would reorder to optimize insert | ||||
499 | foreach my $chunk (@{$data->{BenchmarkAnythingData}}) | ||||
500 | { | ||||
501 | print "." if $self->{debug}; | ||||
502 | $success = $self->{backend}->add_multi_benchmark([$chunk]); | ||||
503 | } | ||||
504 | } | ||||
505 | if (not $success) | ||||
506 | { | ||||
507 | die "benchmarkanything: error while adding data: ".$@; | ||||
508 | } | ||||
509 | print "Done.\n" if $self->{verbose} or $self->{debug}; | ||||
510 | } | ||||
511 | elsif ($backend eq 'http') | ||||
512 | { | ||||
513 | require BenchmarkAnything::Reporter; | ||||
514 | $self->{config} = BenchmarkAnything::Reporter->new(config => $self->{config}, | ||||
515 | verbose => $self->{verbose}, | ||||
516 | debug => $self->{debug}, | ||||
517 | ); | ||||
518 | } | ||||
519 | else | ||||
520 | { | ||||
521 | die "benchmarkanything: no backend '$backend', available backends are: 'http', 'local'.\n"; | ||||
522 | } | ||||
523 | |||||
524 | return $self; | ||||
525 | } | ||||
526 | |||||
527 | sub _get_user_agent | ||||
528 | { | ||||
529 | require Mojo::UserAgent; | ||||
530 | return Mojo::UserAgent->new; | ||||
531 | } | ||||
532 | |||||
533 | sub _get_base_url | ||||
534 | { | ||||
535 | shift->{config}{benchmarkanything}{backends}{http}{base_url}; | ||||
536 | } | ||||
537 | |||||
538 | |||||
539 | sub search | ||||
540 | { | ||||
541 | my ($self, $query, $value_id) = @_; | ||||
542 | |||||
543 | # --- validate --- | ||||
544 | if (not $query and not $value_id) | ||||
545 | { | ||||
546 | die "benchmarkanything: no query or value_id provided.\n"; | ||||
547 | } | ||||
548 | |||||
549 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
550 | if ($backend eq 'local') | ||||
551 | { | ||||
552 | # single values | ||||
553 | return $self->{backend}->get_single_benchmark_point($value_id) if $value_id; | ||||
554 | return $self->{backend}->search_array($query); | ||||
555 | } | ||||
556 | elsif ($backend eq 'http') | ||||
557 | { | ||||
558 | my $ua = $self->_get_user_agent; | ||||
559 | my $url = $self->_get_base_url."/api/v1/search"; | ||||
560 | my $res; | ||||
561 | if ($value_id) { | ||||
562 | $url .= "/$value_id"; | ||||
563 | $res = $ua->get($url)->res; | ||||
564 | } else { | ||||
565 | $res = $ua->post($url => json => $query)->res; | ||||
566 | } | ||||
567 | |||||
568 | die "benchmarkanything: ".$res->error->{message}." ($url)\n" if $res->error; | ||||
569 | |||||
570 | return $res->json; | ||||
571 | } | ||||
572 | else | ||||
573 | { | ||||
574 | die "benchmarkanything: no backend '$backend', available backends are: 'http', 'local'.\n"; | ||||
575 | } | ||||
576 | } | ||||
577 | |||||
578 | |||||
579 | sub listnames | ||||
580 | { | ||||
581 | my ($self, $pattern) = @_; | ||||
582 | |||||
583 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
584 | if ($backend eq 'local') | ||||
585 | { | ||||
586 | return $self->{backend}->list_benchmark_names(defined($pattern) ? ($pattern) : ()); | ||||
587 | } | ||||
588 | elsif ($backend eq 'http') | ||||
589 | { | ||||
590 | my $ua = $self->_get_user_agent; | ||||
591 | my $url = $self->_get_base_url."/api/v1/listnames"; | ||||
592 | |||||
593 | my $res = $ua->get($url)->res; | ||||
594 | die "benchmarkanything: ".$res->error->{message}." ($url)\n" if $res->error; | ||||
595 | |||||
596 | my $result = $res->json; | ||||
597 | |||||
598 | # output | ||||
599 | return $result; | ||||
600 | } | ||||
601 | else | ||||
602 | { | ||||
603 | die "benchmarkanything: no backend '$backend', available backends are: 'http', 'local'.\n"; | ||||
604 | } | ||||
605 | } | ||||
606 | |||||
607 | |||||
608 | sub listkeys | ||||
609 | { | ||||
610 | my ($self, $pattern) = @_; | ||||
611 | |||||
612 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
613 | if ($backend eq 'local') | ||||
614 | { | ||||
615 | return $self->{backend}->list_additional_keys(defined($pattern) ? ($pattern) : ()); | ||||
616 | } | ||||
617 | elsif ($backend eq 'http') | ||||
618 | { | ||||
619 | my $ua = $self->_get_user_agent; | ||||
620 | my $url = $self->_get_base_url."/api/v1/listkeys"; | ||||
621 | |||||
622 | my $res = $ua->get($url)->res; | ||||
623 | die "benchmarkanything: ".$res->error->{message}." ($url)\n" if $res->error; | ||||
624 | |||||
625 | my $result = $res->json; | ||||
626 | |||||
627 | # output | ||||
628 | return $result; | ||||
629 | } | ||||
630 | else | ||||
631 | { | ||||
632 | die "benchmarkanything: no backend '$backend', available backends are: 'http', 'local'.\n"; | ||||
633 | } | ||||
634 | } | ||||
635 | |||||
636 | |||||
637 | sub stats | ||||
638 | { | ||||
639 | my ($self) = @_; | ||||
640 | |||||
641 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
642 | if ($backend eq 'local') | ||||
643 | { | ||||
644 | return $self->{backend}->get_stats; | ||||
645 | } | ||||
646 | elsif ($backend eq 'http') | ||||
647 | { | ||||
648 | my $ua = $self->_get_user_agent; | ||||
649 | my $url = $self->_get_base_url."/api/v1/stats"; | ||||
650 | |||||
651 | my $res = $ua->get($url)->res; | ||||
652 | die "benchmarkanything: ".$res->error->{message}." ($url)\n" if $res->error; | ||||
653 | |||||
654 | my $result = $res->json; | ||||
655 | |||||
656 | # output | ||||
657 | return $result; | ||||
658 | } | ||||
659 | else | ||||
660 | { | ||||
661 | die "benchmarkanything: no backend '$backend', available backends are: 'http', 'local'.\n"; | ||||
662 | } | ||||
663 | } | ||||
664 | |||||
665 | |||||
666 | sub gc | ||||
667 | # spent 34.3ms (12µs+34.3) within BenchmarkAnything::Storage::Frontend::Lib::gc which was called:
# once (12µs+34.3ms) by main::_gc at line 433 of /home/ss5/perl5/perlbrew/perls/perl-5.22.0/bin/benchmarkanything-storage | ||||
668 | 1 | 400ns | my ($self) = @_; | ||
669 | |||||
670 | 1 | 3µs | my $backend = $self->{config}{benchmarkanything}{backend}; | ||
671 | 1 | 8µs | 1 | 34.3ms | if ($backend eq 'local') # spent 34.3ms making 1 call to BenchmarkAnything::Storage::Backend::SQL::gc |
672 | { | ||||
673 | $self->{backend}->gc; | ||||
674 | } | ||||
675 | } | ||||
676 | |||||
677 | |||||
678 | sub process_raw_result_queue | ||||
679 | # spent 53.0s (9.64ms+53.0) within BenchmarkAnything::Storage::Frontend::Lib::process_raw_result_queue which was called:
# once (9.64ms+53.0s) by main::_processqueue at line 406 of /home/ss5/perl5/perlbrew/perls/perl-5.22.0/bin/benchmarkanything-storage | ||||
680 | 1 | 400ns | my ($self, $count) = @_; | ||
681 | |||||
682 | 1 | 300ns | $count ||= 10; | ||
683 | |||||
684 | 1 | 2µs | my $backend = $self->{config}{benchmarkanything}{backend}; | ||
685 | 1 | 1µs | if ($backend eq 'local') | ||
686 | { | ||||
687 | 1 | 100ns | my $dequeued_raw_bench_bundle_id; | ||
688 | 1 | 1.62ms | do { | ||
689 | 1000 | 5.10ms | 1000 | 53.0s | $dequeued_raw_bench_bundle_id = $self->{backend}->process_queued_multi_benchmark; # spent 53.0s making 1000 calls to BenchmarkAnything::Storage::Backend::SQL::process_queued_multi_benchmark, avg 53.0ms/call |
690 | 1000 | 869µs | $count--; | ||
691 | } until ($count < 1 or not defined($dequeued_raw_bench_bundle_id)); | ||||
692 | } | ||||
693 | else | ||||
694 | { | ||||
695 | die "benchmarkanything: only backend 'local' allowed in 'process_raw_result_queue'.\n"; | ||||
696 | } | ||||
697 | 1 | 6µs | return; | ||
698 | } | ||||
699 | |||||
700 | |||||
701 | sub init_search_engine | ||||
702 | { | ||||
703 | my ($self, $force) = @_; | ||||
704 | |||||
705 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
706 | if ($backend eq 'local') | ||||
707 | { | ||||
708 | $self->{backend}->init_search_engine($force); | ||||
709 | } | ||||
710 | else | ||||
711 | { | ||||
712 | die "benchmarkanything: only backend 'local' allowed in 'init_search_engine'.\n"; | ||||
713 | } | ||||
714 | return; | ||||
715 | } | ||||
716 | |||||
717 | |||||
718 | sub sync_search_engine | ||||
719 | { | ||||
720 | my ($self, $force, $start, $count) = @_; | ||||
721 | |||||
722 | my $backend = $self->{config}{benchmarkanything}{backend}; | ||||
723 | if ($backend eq 'local') | ||||
724 | { | ||||
725 | $self->{backend}->sync_search_engine($force, $start, $count); | ||||
726 | } | ||||
727 | else | ||||
728 | { | ||||
729 | die "benchmarkanything: only backend 'local' allowed in 'sync_search_engine'.\n"; | ||||
730 | } | ||||
731 | return; | ||||
732 | } | ||||
733 | |||||
- - | |||||
736 | sub getpoint | ||||
737 | { | ||||
738 | my ($self, $value_id) = @_; | ||||
739 | |||||
740 | return $self->search(undef, $value_id); | ||||
741 | die "benchmarkanything: please provide a benchmark value_id'\n" unless $value_id; | ||||
742 | } | ||||
743 | |||||
744 | 1 | 3µs | 1; | ||
745 | |||||
746 | __END__ |