Filename | /opt/perl-5.18.1/lib/site_perl/5.18.1/Sub/Defer.pm |
Statements | Executed 124 statements in 892µs |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
9 | 2 | 2 | 108µs | 188µs | defer_sub | Sub::Defer::
3 | 1 | 1 | 67µs | 2.65ms | undefer_sub | Sub::Defer::
1 | 1 | 1 | 24µs | 86µs | BEGIN@3 | Sub::Defer::
1 | 1 | 1 | 11µs | 23µs | BEGIN@26 | Sub::Defer::
1 | 1 | 1 | 11µs | 79µs | BEGIN@5 | Sub::Defer::
1 | 1 | 1 | 9µs | 83µs | BEGIN@4 | Sub::Defer::
1 | 1 | 1 | 8µs | 36µs | BEGIN@6 | Sub::Defer::
3 | 1 | 1 | 8µs | 8µs | defer_info | Sub::Defer::
0 | 0 | 0 | 0s | 0s | CLONE | Sub::Defer::
0 | 0 | 0 | 0s | 0s | __ANON__[:49] | Sub::Defer::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Sub::Defer; | ||||
2 | |||||
3 | 3 | 42µs | 3 | 147µs | # spent 86µs (24+61) within Sub::Defer::BEGIN@3 which was called:
# once (24µs+61µs) by Moo::BEGIN@6 at line 3 # spent 86µs making 1 call to Sub::Defer::BEGIN@3
# spent 40µs making 1 call to strictures::import
# spent 21µs making 1 call to strictures::VERSION |
4 | 2 | 43µs | 2 | 156µs | # spent 83µs (9+73) within Sub::Defer::BEGIN@4 which was called:
# once (9µs+73µs) by Moo::BEGIN@6 at line 4 # spent 83µs making 1 call to Sub::Defer::BEGIN@4
# spent 73µs making 1 call to base::import |
5 | 2 | 36µs | 2 | 148µs | # spent 79µs (11+68) within Sub::Defer::BEGIN@5 which was called:
# once (11µs+68µs) by Moo::BEGIN@6 at line 5 # spent 79µs making 1 call to Sub::Defer::BEGIN@5
# spent 68µs making 1 call to Exporter::import |
6 | 2 | 163µs | 2 | 63µs | # spent 36µs (8+27) within Sub::Defer::BEGIN@6 which was called:
# once (8µs+27µs) by Moo::BEGIN@6 at line 6 # spent 36µs making 1 call to Sub::Defer::BEGIN@6
# spent 27µs making 1 call to Exporter::import |
7 | |||||
8 | 1 | 900ns | our $VERSION = '1.003001'; | ||
9 | 1 | 15µs | $VERSION = eval $VERSION; # spent 3µs executing statements in string eval | ||
10 | |||||
11 | 1 | 1µs | our @EXPORT = qw(defer_sub undefer_sub); | ||
12 | |||||
13 | 1 | 100ns | our %DEFERRED; | ||
14 | |||||
15 | # spent 2.65ms (67µs+2.58) within Sub::Defer::undefer_sub which was called 3 times, avg 883µs/call:
# 3 times (67µs+2.58ms) by Foo::Moo::QS::new or Foo::Moo::new or Method::Generate::Constructor::new at line 47, avg 883µs/call | ||||
16 | 3 | 800ns | my ($deferred) = @_; | ||
17 | my ($target, $maker, $undeferred_ref) = @{ | ||||
18 | 3 | 4µs | $DEFERRED{$deferred}||return $deferred | ||
19 | }; | ||||
20 | return ${$undeferred_ref} | ||||
21 | 3 | 700ns | if ${$undeferred_ref}; | ||
22 | 3 | 6µs | 3 | 2.57ms | ${$undeferred_ref} = my $made = $maker->(); # spent 2.57ms making 3 calls to Method::Generate::Constructor::__ANON__[Method/Generate/Constructor.pm:64], avg 855µs/call |
23 | |||||
24 | # make sure the method slot has not changed since deferral time | ||||
25 | 3 | 14µs | 3 | 8µs | if (defined($target) && $deferred eq *{_getglob($target)}{CODE}||'') { # spent 8µs making 3 calls to Moo::_Utils::_getglob, avg 3µs/call |
26 | 2 | 369µs | 2 | 34µs | # spent 23µs (11+11) within Sub::Defer::BEGIN@26 which was called:
# once (11µs+11µs) by Moo::BEGIN@6 at line 26 # spent 23µs making 1 call to Sub::Defer::BEGIN@26
# spent 11µs making 1 call to warnings::unimport |
27 | |||||
28 | # I believe $maker already evals with the right package/name, so that | ||||
29 | # _install_coderef calls are not necessary --ribasushi | ||||
30 | 3 | 6µs | 3 | 4µs | *{_getglob($target)} = $made; # spent 4µs making 3 calls to Moo::_Utils::_getglob, avg 1µs/call |
31 | } | ||||
32 | 3 | 16µs | 3 | 4µs | weaken($DEFERRED{$made} = $DEFERRED{$deferred}); # spent 4µs making 3 calls to Scalar::Util::weaken, avg 1µs/call |
33 | |||||
34 | 3 | 14µs | return $made; | ||
35 | } | ||||
36 | |||||
37 | # spent 8µs within Sub::Defer::defer_info which was called 3 times, avg 3µs/call:
# 3 times (8µs+0s) by Moo::_accessor_maker_for at line 124 of Moo.pm, avg 3µs/call | ||||
38 | 3 | 900ns | my ($deferred) = @_; | ||
39 | 3 | 11µs | $DEFERRED{$deferred||''}; | ||
40 | } | ||||
41 | |||||
42 | # spent 188µs (108+80) within Sub::Defer::defer_sub which was called 9 times, avg 21µs/call:
# 6 times (67µs+35µs) by Sub::Quote::quote_sub at line 69 of Sub/Quote.pm, avg 17µs/call
# 3 times (42µs+45µs) by Method::Generate::Constructor::install_delayed at line 64 of Method/Generate/Constructor.pm, avg 29µs/call | ||||
43 | 9 | 4µs | my ($target, $maker) = @_; | ||
44 | 9 | 900ns | my $undeferred; | ||
45 | 9 | 200ns | my $deferred_info; | ||
46 | my $deferred = sub { | ||||
47 | 3 | 9µs | 3 | 2.65ms | $undeferred ||= undefer_sub($deferred_info->[3]); # spent 2.65ms making 3 calls to Sub::Defer::undefer_sub, avg 883µs/call |
48 | 3 | 17µs | 3 | 28µs | goto &$undeferred; # spent 15µs making 1 call to Method::Generate::Constructor::new
# spent 6µs making 1 call to Foo::Moo::new
# spent 6µs making 1 call to Foo::Moo::QS::new |
49 | 9 | 18µs | }; | ||
50 | 9 | 9µs | $deferred_info = [ $target, $maker, \$undeferred, $deferred ]; | ||
51 | 9 | 51µs | 9 | 10µs | weaken($DEFERRED{$deferred} = $deferred_info); # spent 10µs making 9 calls to Scalar::Util::weaken, avg 1µs/call |
52 | 9 | 8µs | 5 | 70µs | _install_coderef($target => $deferred) if defined $target; # spent 70µs making 5 calls to Moo::_Utils::_install_coderef, avg 14µs/call |
53 | 9 | 27µs | return $deferred; | ||
54 | } | ||||
55 | |||||
56 | sub CLONE { | ||||
57 | %DEFERRED = map { defined $_ ? ($_->[3] => $_) : () } values %DEFERRED; | ||||
58 | weaken($_) for values %DEFERRED; | ||||
59 | } | ||||
60 | |||||
61 | 1 | 5µs | 1; | ||
62 | |||||
63 | =head1 NAME | ||||
64 | |||||
65 | Sub::Defer - defer generation of subroutines until they are first called | ||||
66 | |||||
67 | =head1 SYNOPSIS | ||||
68 | |||||
69 | use Sub::Defer; | ||||
70 | |||||
71 | my $deferred = defer_sub 'Logger::time_since_first_log' => sub { | ||||
72 | my $t = time; | ||||
73 | sub { time - $t }; | ||||
74 | }; | ||||
75 | |||||
76 | Logger->time_since_first_log; # returns 0 and replaces itself | ||||
77 | Logger->time_since_first_log; # returns time - $t | ||||
78 | |||||
79 | =head1 DESCRIPTION | ||||
80 | |||||
81 | These subroutines provide the user with a convenient way to defer creation of | ||||
82 | subroutines and methods until they are first called. | ||||
83 | |||||
84 | =head1 SUBROUTINES | ||||
85 | |||||
86 | =head2 defer_sub | ||||
87 | |||||
88 | my $coderef = defer_sub $name => sub { ... }; | ||||
89 | |||||
90 | This subroutine returns a coderef that encapsulates the provided sub - when | ||||
91 | it is first called, the provided sub is called and is -itself- expected to | ||||
92 | return a subroutine which will be goto'ed to on subsequent calls. | ||||
93 | |||||
94 | If a name is provided, this also installs the sub as that name - and when | ||||
95 | the subroutine is undeferred will re-install the final version for speed. | ||||
96 | |||||
97 | =head2 undefer_sub | ||||
98 | |||||
99 | my $coderef = undefer_sub \&Foo::name; | ||||
100 | |||||
101 | If the passed coderef has been L<deferred|/defer_sub> this will "undefer" it. | ||||
102 | If the passed coderef has not been deferred, this will just return it. | ||||
103 | |||||
104 | If this is confusing, take a look at the example in the L</SYNOPSIS>. | ||||
105 | |||||
106 | =head1 SUPPORT | ||||
107 | |||||
108 | See L<Moo> for support and contact information. | ||||
109 | |||||
110 | =head1 AUTHORS | ||||
111 | |||||
112 | See L<Moo> for authors. | ||||
113 | |||||
114 | =head1 COPYRIGHT AND LICENSE | ||||
115 | |||||
116 | See L<Moo> for the copyright and license. |