← Index
NYTProf Performance Profile   « line view »
For ch-1.pl
  Run on Mon Sep 9 20:21:43 2019
Reported on Mon Sep 9 20:23:12 2019

Filename/usr/lib/x86_64-linux-gnu/perl5/5.26/Function/Parameters.pm
StatementsExecuted 186 statements in 3.85ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1117.07ms7.49msFunction::Parameters::::BEGIN@6Function::Parameters::BEGIN@6
1111.76ms2.30msFunction::Parameters::::BEGIN@7Function::Parameters::BEGIN@7
111145µs274µsFunction::Parameters::::importFunction::Parameters::import
31165µs65µsFunction::Parameters::::CORE:regcompFunction::Parameters::CORE:regcomp (opcode)
11125µs25µsFunction::Parameters::::BEGIN@3Function::Parameters::BEGIN@3
32122µs94µsFunction::Parameters::::_assert_valid_identifierFunction::Parameters::_assert_valid_identifier
147116µs16µsFunction::Parameters::::_delete_defaultFunction::Parameters::_delete_default
63115µs15µsFunction::Parameters::::CORE:matchFunction::Parameters::CORE:match (opcode)
11112µs21µsFunction::Parameters::::BEGIN@4Function::Parameters::BEGIN@4
11110µs10µsFunction::Parameters::::_register_infoFunction::Parameters::_register_info
11110µs24µsFunction::Parameters::::BEGIN@80Function::Parameters::BEGIN@80
1119µs221µsFunction::Parameters::::BEGIN@15Function::Parameters::BEGIN@15
1117µs7µsFunction::Parameters::::BEGIN@14Function::Parameters::BEGIN@14
1116µs6µsFunction::Parameters::::CORE:sortFunction::Parameters::CORE:sort (opcode)
1114µs9µsFunction::Parameters::::_assert_valid_attributesFunction::Parameters::_assert_valid_attributes
0000s0sFunction::Parameters::::__ANON__[:104]Function::Parameters::__ANON__[:104]
0000s0sFunction::Parameters::::__ANON__[:95]Function::Parameters::__ANON__[:95]
0000s0sFunction::Parameters::::_croakFunction::Parameters::_croak
0000s0sFunction::Parameters::::_find_or_add_idxFunction::Parameters::_find_or_add_idx
0000s0sFunction::Parameters::::_malformed_typeFunction::Parameters::_malformed_type
0000s0sFunction::Parameters::::_mkparam1Function::Parameters::_mkparam1
0000s0sFunction::Parameters::::_mkparamsFunction::Parameters::_mkparams
0000s0sFunction::Parameters::::_reify_type_autoFunction::Parameters::_reify_type_auto
0000s0sFunction::Parameters::::_reify_type_auto_termFunction::Parameters::_reify_type_auto_term
0000s0sFunction::Parameters::::_reify_type_auto_unionFunction::Parameters::_reify_type_auto_union
0000s0sFunction::Parameters::::_reify_type_mooseFunction::Parameters::_reify_type_moose
0000s0sFunction::Parameters::::infoFunction::Parameters::info
0000s0sFunction::Parameters::::unimportFunction::Parameters::unimport
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Function::Parameters;
2
3272µs125µs
# spent 25µs within Function::Parameters::BEGIN@3 which was called: # once (25µs+0s) by main::BEGIN@23 at line 3
use v5.14.0;
# spent 25µs making 1 call to Function::Parameters::BEGIN@3
4247µs230µs
# spent 21µs (12+9) within Function::Parameters::BEGIN@4 which was called: # once (12µs+9µs) by main::BEGIN@23 at line 4
use warnings;
# spent 21µs making 1 call to Function::Parameters::BEGIN@4 # spent 9µs making 1 call to warnings::import
5
62204µs27.58ms
# spent 7.49ms (7.07+422µs) within Function::Parameters::BEGIN@6 which was called: # once (7.07ms+422µs) by main::BEGIN@23 at line 6
use Carp qw(croak confess);
# spent 7.49ms making 1 call to Function::Parameters::BEGIN@6 # spent 90µs making 1 call to Exporter::import
72227µs22.36ms
# spent 2.30ms (1.76+532µs) within Function::Parameters::BEGIN@7 which was called: # once (1.76ms+532µs) by main::BEGIN@23 at line 7
use Scalar::Util qw(blessed);
# spent 2.30ms making 1 call to Function::Parameters::BEGIN@7 # spent 67µs making 1 call to Exporter::import
8
9sub _croak {
10 my (undef, $file, $line) = caller 1;
11 die @_, " at $file line $line.\n";
12}
13
14245µs17µs
# spent 7µs within Function::Parameters::BEGIN@14 which was called: # once (7µs+0s) by main::BEGIN@23 at line 14
use XSLoader;
# spent 7µs making 1 call to Function::Parameters::BEGIN@14
15
# spent 221µs (9+212) within Function::Parameters::BEGIN@15 which was called: # once (9µs+212µs) by main::BEGIN@23 at line 19
BEGIN {
161400ns our $VERSION = '2.001003';
17 #$VERSION =~ s/-TRIAL[0-9]*\z//;
181221µs1212µs XSLoader::load;
# spent 212µs making 1 call to XSLoader::load
191500µs1221µs}
# spent 221µs making 1 call to Function::Parameters::BEGIN@15
20
21
# spent 94µs (22+72) within Function::Parameters::_assert_valid_identifier which was called 3 times, avg 31µs/call: # 2 times (17µs+39µs) by Function::Parameters::import at line 256, avg 28µs/call # once (6µs+32µs) by Function::Parameters::import at line 324
sub _assert_valid_identifier {
2232µs my ($name, $with_dollar) = @_;
2331µs my $bonus = $with_dollar ? '\$' : '';
24394µs672µs $name =~ /\A${bonus}[^\W\d]\w*\z/
# spent 65µs making 3 calls to Function::Parameters::CORE:regcomp, avg 22µs/call # spent 6µs making 3 calls to Function::Parameters::CORE:match, avg 2µs/call
25 or confess qq{"$name" doesn't look like a valid identifier};
26}
27
28
# spent 9µs (4+6) within Function::Parameters::_assert_valid_attributes which was called: # once (4µs+6µs) by Function::Parameters::import at line 280
sub _assert_valid_attributes {
291400ns my ($attrs) = @_;
30110µs16µs $attrs =~ m{
# spent 6µs making 1 call to Function::Parameters::CORE:match
31 \A \s*+
32 : \s*+
33 (?&ident) (?! [^\s:(] ) (?&param)?+ \s*+
34 (?:
35 (?: : \s*+ )?
36 (?&ident) (?! [^\s:(] ) (?&param)?+ \s*+
37 )*+
38 \z
39
40 (?(DEFINE)
41 (?<ident>
42 [^\W\d]
43 \w*+
44 )
45 (?<param>
46 \(
47 [^()\\]*+
48 (?:
49 (?:
50 \\ .
51 |
52 (?&param)
53 )
54 [^()\\]*+
55 )*+
56 \)
57 )
58 )
59 }sx or confess qq{"$attrs" doesn't look like valid attributes};
60}
61
62sub _reify_type_moose {
63 require Moose::Util::TypeConstraints;
64 Moose::Util::TypeConstraints::find_or_create_isa_type_constraint($_[0])
65}
66
67sub _malformed_type {
68 my ($type, $msg) = @_;
69 my $pos = pos $_[0];
70 substr $type, $pos, 0, ' <-- HERE ';
71 croak "Malformed type: $msg marked by <-- HERE in '$type'";
72}
73
74sub _reify_type_auto_term {
75 # (str, caller)
76 $_[0] =~ /\G ( \w+ (?: :: \w+)* ) \s* /xgc or _malformed_type $_[0], "missing type name";
77 my $name = $1;
78 $name = "$_[1]::$name" unless $name =~ /::/;
79 my $fun = do {
8022.18ms238µs
# spent 24µs (10+14) within Function::Parameters::BEGIN@80 which was called: # once (10µs+14µs) by main::BEGIN@23 at line 80
no strict 'refs';
# spent 24µs making 1 call to Function::Parameters::BEGIN@80 # spent 14µs making 1 call to strict::unimport
81 defined &$name or croak "Undefined type name $name";
82 \&$name
83 };
84
85 $_[0] =~ /\G \[ \s* /xgc
86 or return $fun;
87
88 my @args;
89 until ($_[0] =~ /\G \] \s* /xgc) {
90 $_[0] =~ /\G , \s* /xgc or _malformed_type $_[0], "missing ',' or ']'"
91 if @args;
92 push @args, &_reify_type_auto_union;
93 }
94
95 sub { $fun->([map $_->(), @args]) }
96}
97
98sub _reify_type_auto_union {
99 # (str, caller)
100 my $fun = &_reify_type_auto_term;
101 while ($_[0] =~ /\G \| \s* /xgc) {
102 my $right = &_reify_type_auto_term;
103 my $left = $fun;
104 $fun = sub { $left->() | $right->() };
105 }
106 $fun
107}
108
109sub _reify_type_auto {
110 my ($type) = @_;
111 my $caller = caller;
112
113 $type =~ /\G \s+ /xgc;
114 my $tfun = _reify_type_auto_union $type, $caller;
115 $type =~ /\G \z/xgc or _malformed_type $type, "trailing garbage";
116 $tfun->()
117}
118
119
# spent 16µs within Function::Parameters::_delete_default which was called 14 times, avg 1µs/call: # 2 times (5µs+0s) by Function::Parameters::import at line 338, avg 2µs/call # 2 times (2µs+0s) by Function::Parameters::import at line 341, avg 1µs/call # 2 times (2µs+0s) by Function::Parameters::import at line 339, avg 1µs/call # 2 times (2µs+0s) by Function::Parameters::import at line 342, avg 950ns/call # 2 times (2µs+0s) by Function::Parameters::import at line 340, avg 950ns/call # 2 times (2µs+0s) by Function::Parameters::import at line 343, avg 750ns/call # 2 times (1µs+0s) by Function::Parameters::import at line 344, avg 650ns/call
sub _delete_default {
120144µs my ($href, $key, $default) = @_;
1211430µs exists $href->{$key} ? delete $href->{$key} : $default
122}
123
124sub _find_or_add_idx {
125 my ($array, $x) = @_;
126 my $index;
127 for my $i (0 .. $#$array) {
128 if ($array->[$i] == $x) {
129 $index = $i;
130 last;
131 }
132 }
133 unless (defined $index) {
134 $index = @$array;
135 push @$array, $x;
136 }
137 $index
138}
139
140123µsmy %type_map = (
141 function_strict => {},
142 function_lax => {
143 defaults => 'function_strict',
144 strict => 0,
145 },
146 function => { defaults => 'function_strict' },
147
148 method_strict => {
149 defaults => 'function_strict',
150 attributes => ':method',
151 shift => '$self',
152 invocant => 1,
153 },
154 method_lax => {
155 defaults => 'method_strict',
156 strict => 0,
157 },
158 method => { defaults => 'method_strict' },
159
160 classmethod_strict => {
161 defaults => 'method_strict',
162 shift => '$class',
163 },
164 classmethod_lax => {
165 defaults => 'classmethod_strict',
166 strict => 0,
167 },
168 classmethod => { defaults => 'classmethod_strict' },
169
170 around => {
171 defaults => 'method',
172 name => 'required',
173 install_sub => 'around',
174 shift => ['$orig', '$self'],
175 runtime => 1,
176 },
177 (
178 map +(
179 $_ => {
180 defaults => 'method',
181 name => 'required',
182 install_sub => $_,
183 runtime => 1,
184 }
185 ), qw(
186 before after augment override
187 ),
188 ),
189);
190
19119µsmy %import_map = (
192 fun => 'function',
193 (
194 map +($_ => $_),
195 qw(
196 method
197 classmethod
198 before
199 after
200 around
201 augment
202 override
203 )
204 ),
205
206 ':strict' => {
207 fun => 'function_strict',
208 method => 'method_strict',
209 },
210
211 ':lax' => {
212 fun => 'function_lax',
213 method => 'method_lax',
214 },
215
216 ':std' => [qw(fun method)],
217 ':modifiers' => [qw(
218 before
219 after
220 around
221 augment
222 override
223 )],
224);
22512µsfor my $v (values %import_map) {
226126µs if (ref $v eq 'ARRAY') {
227 $v = {
22828µs map +($_ => $import_map{$_} || die "Internal error: $v => $_"),
229 @$v
230 };
231 }
232}
233
234
# spent 274µs (145+129) within Function::Parameters::import which was called: # once (145µs+129µs) by main::BEGIN@23 at line 23 of /homes/dcw/src/perl/weeklychallenge/perlweeklychallenge-club/challenge-025/duncan-c-white/perl5/ch-1.pl
sub import {
2351600ns my $class = shift;
236
2371200ns my %imports;
23812µs @_ = qw(:std) if !@_;
2391700ns for my $item (@_) {
2401200ns my $part;
2411400ns if (ref $item) {
242 $part = $item;
243 } else {
24411µs my $type = $import_map{$item}
245 or croak qq{"$item" is not exported by the $class module};
24611µs $part = ref $type
247 ? $type
248 : { $item => $type };
249 }
25014µs @imports{keys %$part} = values %$part;
251 }
252
2531200ns my %spec;
254
255116µs16µs for my $name (sort keys %imports) {
# spent 6µs making 1 call to Function::Parameters::CORE:sort
25623µs256µs _assert_valid_identifier $name;
# spent 56µs making 2 calls to Function::Parameters::_assert_valid_identifier, avg 28µs/call
25721µs my $proto_type = $imports{$name};
258
25923µs $proto_type = {defaults => $proto_type} unless ref $proto_type;
260
26124µs my %type = %$proto_type;
26227µs while (my $defaults = delete $type{defaults}) {
26353µs my $base = $type_map{$defaults}
264 or confess qq["$defaults" doesn't look like a valid type (one of ${\join ', ', sort keys %type_map})];
26558µs %type = (%$base, %type);
266 }
267
2682500ns if (exists $type{strict}) {
269 $type{check_argument_count} ||= $type{strict};
270 delete $type{strict};
271 }
272
2732300ns my %clean;
274
27522µs $clean{name} = delete $type{name} // 'optional';
27627µs23µs $clean{name} =~ /\A(?:optional|required|prohibited)\z/
# spent 3µs making 2 calls to Function::Parameters::CORE:match, avg 2µs/call
277 or confess qq["$clean{name}" doesn't look like a valid name attribute (one of optional, required, prohibited)];
278
27921µs $clean{attrs} = delete $type{attributes} // '';
28022µs19µs _assert_valid_attributes $clean{attrs} if $clean{attrs};
# spent 9µs making 1 call to Function::Parameters::_assert_valid_attributes
281
28222µs if (!exists $type{reify_type}) {
283 $clean{reify_type} = \&_reify_type_auto;
284 } else {
285 my $rt = delete $type{reify_type} // '(undef)';
286 if (!ref $rt) {
287 $rt =
288 $rt eq 'auto' ? \&_reify_type_auto :
289 $rt eq 'moose' ? \&_reify_type_moose :
290 confess qq{"$rt" isn't a known predefined type reifier};
291 } elsif (ref $rt ne 'CODE') {
292 confess qq{"$rt" doesn't look like a type reifier};
293 }
294
295 $clean{reify_type} = $rt;
296 }
297
2982900ns if (!exists $type{install_sub}) {
299 $clean{install_sub} = '';
300 } else {
301 my $is = delete $type{install_sub};
302 if (!ref $is) {
303 _assert_valid_identifier $is;
304 } elsif (ref $is ne 'CODE') {
305 confess qq{"$is" doesn't look like a sub installer};
306 }
307
308 $clean{install_sub} = $is;
309 }
310
31122µs $clean{shift} = do {
31221µs my $shift = delete $type{shift} // [];
31322µs $shift = [$shift] if !ref $shift;
3142500ns my $str = '';
3152400ns my @shifty_types;
31621µs for my $item (@$shift) {
3171200ns my ($name, $type);
3181300ns if (ref $item) {
319 @$item == 2 or confess "A 'shift' item must have 2 elements, not " . @$item;
320 ($name, $type) = @$item;
321 } else {
3221300ns $name = $item;
323 }
32411µs138µs _assert_valid_identifier $name, 1;
# spent 38µs making 1 call to Function::Parameters::_assert_valid_identifier
3251500ns $name eq '$_' and confess q[Using "$_" as a parameter is not supported];
3261600ns $str .= $name;
3271300ns if (defined $type) {
328 blessed($type) or confess "${name}'s type must be an object, not $type";
329 my $index = _find_or_add_idx \@shifty_types, $type;
330 $str .= "/$index";
331 }
33211µs $str .= ' ';
333 }
33421µs $clean{shift_types} = \@shifty_types;
33522µs $str
336 };
337
33823µs25µs $clean{default_arguments} = _delete_default \%type, 'default_arguments', 1;
# spent 5µs making 2 calls to Function::Parameters::_delete_default, avg 2µs/call
33924µs22µs $clean{named_parameters} = _delete_default \%type, 'named_parameters', 1;
# spent 2µs making 2 calls to Function::Parameters::_delete_default, avg 1µs/call
34022µs22µs $clean{types} = _delete_default \%type, 'types', 1;
# spent 2µs making 2 calls to Function::Parameters::_delete_default, avg 950ns/call
34122µs22µs $clean{invocant} = _delete_default \%type, 'invocant', 0;
# spent 2µs making 2 calls to Function::Parameters::_delete_default, avg 1µs/call
34222µs22µs $clean{runtime} = _delete_default \%type, 'runtime', 0;
# spent 2µs making 2 calls to Function::Parameters::_delete_default, avg 950ns/call
34322µs22µs $clean{check_argument_count} = _delete_default \%type, 'check_argument_count', 1;
# spent 2µs making 2 calls to Function::Parameters::_delete_default, avg 750ns/call
34422µs21µs $clean{check_argument_types} = _delete_default \%type, 'check_argument_types', 1;
# spent 1µs making 2 calls to Function::Parameters::_delete_default, avg 650ns/call
345
3462600ns %type and confess "Invalid keyword property: @{[sort keys %type]}";
347
34825µs $spec{$name} = \%clean;
349 }
350
35112µs my %config = %{$^H{+HINTK_CONFIG} // {}};
35211µs for my $kw (keys %spec) {
3532900ns my $type = $spec{$kw};
354
355 my $flags =
356 $type->{name} eq 'prohibited' ? FLAG_ANON_OK :
35721µs $type->{name} eq 'required' ? FLAG_NAME_OK :
358 FLAG_ANON_OK | FLAG_NAME_OK
359 ;
3602800ns $flags |= FLAG_DEFAULT_ARGS if $type->{default_arguments};
3612500ns $flags |= FLAG_CHECK_NARGS if $type->{check_argument_count};
3622600ns $flags |= FLAG_CHECK_TARGS if $type->{check_argument_types};
3632500ns $flags |= FLAG_INVOCANT if $type->{invocant};
3642400ns $flags |= FLAG_NAMED_PARAMS if $type->{named_parameters};
3652400ns $flags |= FLAG_TYPES_OK if $type->{types};
3662400ns $flags |= FLAG_RUNTIME if $type->{runtime};
367 $config{$kw} = {
368 HINTSK_FLAGS, => $flags,
369 HINTSK_SHIFT, => $type->{shift},
370 HINTSK_ATTRS, => $type->{attrs},
371 HINTSK_REIFY, => $type->{reify_type},
372 HINTSK_INSTL, => $type->{install_sub},
373 !@{$type->{shift_types}} ? () : (
374 HINTSK_SHIF2, => $type->{shift_types},
37526µs ),
376 };
377 }
378111µs $^H{+HINTK_CONFIG} = \%config;
379}
380
381sub unimport {
382 my $class = shift;
383
384 if (!@_) {
385 delete $^H{+HINTK_CONFIG};
386 return;
387 }
388
389 my %config = %{$^H{+HINTK_CONFIG}};
390 delete @config{@_};
391 $^H{+HINTK_CONFIG} = \%config;
392}
393
394
395our %metadata;
396
397
# spent 10µs within Function::Parameters::_register_info which was called: # once (10µs+0s) by main::NULL at line 102 of /homes/dcw/src/perl/weeklychallenge/perlweeklychallenge-club/challenge-025/duncan-c-white/perl5/ch-1.pl
sub _register_info {
398 my (
39912µs $key,
400 $declarator,
401 $shift,
402 $positional_required,
403 $positional_optional,
404 $named_required,
405 $named_optional,
406 $slurpy,
407 $slurpy_type,
408 ) = @_;
409
41014µs my $info = {
411 declarator => $declarator,
412 shift => $shift,
413 positional_required => $positional_required,
414 positional_optional => $positional_optional,
415 named_required => $named_required,
416 named_optional => $named_optional,
417 slurpy => defined $slurpy ? [$slurpy, $slurpy_type] : undef,
418 };
419
42019µs $metadata{$key} = $info;
421}
422
423sub _mkparam1 {
424 my ($pair) = @_;
425 my ($v, $t) = @{$pair || []} or return undef;
426 Function::Parameters::Param->new(
427 name => $v,
428 type => $t,
429 )
430}
431
432sub _mkparams {
433 my @r;
434 while (my ($v, $t) = splice @_, 0, 2) {
435 push @r, Function::Parameters::Param->new(
436 name => $v,
437 type => $t,
438 );
439 }
440 \@r
441}
442
443sub info {
444 my ($func) = @_;
445 my $key = _cv_root $func or return undef;
446 my $info = $metadata{$key} or return undef;
447 require Function::Parameters::Info;
448 Function::Parameters::Info->new(
449 keyword => $info->{declarator},
450 nshift => $info->{shift},
451 slurpy => _mkparam1($info->{slurpy}),
452 (
453 map +("_$_" => _mkparams @{$info->{$_}}),
454 qw(
455 positional_required
456 positional_optional
457 named_required
458 named_optional
459 )
460 )
461 )
462}
463
464120µs'ok'
465
466__END__
 
# spent 15µs within Function::Parameters::CORE:match which was called 6 times, avg 3µs/call: # 3 times (6µs+0s) by Function::Parameters::_assert_valid_identifier at line 24, avg 2µs/call # 2 times (3µs+0s) by Function::Parameters::import at line 276, avg 2µs/call # once (6µs+0s) by Function::Parameters::_assert_valid_attributes at line 30
sub Function::Parameters::CORE:match; # opcode
# spent 65µs within Function::Parameters::CORE:regcomp which was called 3 times, avg 22µs/call: # 3 times (65µs+0s) by Function::Parameters::_assert_valid_identifier at line 24, avg 22µs/call
sub Function::Parameters::CORE:regcomp; # opcode
# spent 6µs within Function::Parameters::CORE:sort which was called: # once (6µs+0s) by Function::Parameters::import at line 255
sub Function::Parameters::CORE:sort; # opcode