← Index
NYTProf Performance Profile   « line view »
For script/ponapi
  Run on Wed Feb 10 15:51:26 2016
Reported on Thu Feb 11 09:43:09 2016

Filename/usr/local/share/perl/5.18.2/Hash/MultiValue.pm
StatementsExecuted 2608473 statements in 9.61s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
100001111.67s2.05sHash::MultiValue::::createHash::MultiValue::create
100001111.65s1.94sHash::MultiValue::::DESTROYHash::MultiValue::DESTROY
100001111.46s1.52sHash::MultiValue::::merge_flatHash::MultiValue::merge_flat
100001111.43s3.76sHash::MultiValue::::newHash::MultiValue::new
102107111.06s1.12sHash::MultiValue::::get_allHash::MultiValue::get_all
11134µs40µsHash::MultiValue::::BEGIN@18Hash::MultiValue::BEGIN@18
11119µs19µsHash::MultiValue::::BEGIN@5Hash::MultiValue::BEGIN@5
11118µs42µsHash::MultiValue::::BEGIN@3Hash::MultiValue::BEGIN@3
11115µs76µsHash::MultiValue::::BEGIN@12Hash::MultiValue::BEGIN@12
11114µs69µsHash::MultiValue::::BEGIN@9Hash::MultiValue::BEGIN@9
11113µs32µsHash::MultiValue::::BEGIN@4Hash::MultiValue::BEGIN@4
1115µs5µsHash::MultiValue::::BEGIN@8Hash::MultiValue::BEGIN@8
0000s0sHash::MultiValue::::STORABLE_freezeHash::MultiValue::STORABLE_freeze
0000s0sHash::MultiValue::::STORABLE_thawHash::MultiValue::STORABLE_thaw
0000s0sHash::MultiValue::::__ANON__[:29]Hash::MultiValue::__ANON__[:29]
0000s0sHash::MultiValue::::__ANON__[:31]Hash::MultiValue::__ANON__[:31]
0000s0sHash::MultiValue::::addHash::MultiValue::add
0000s0sHash::MultiValue::::as_hashrefHash::MultiValue::as_hashref
0000s0sHash::MultiValue::::as_hashref_mixedHash::MultiValue::as_hashref_mixed
0000s0sHash::MultiValue::::as_hashref_multiHash::MultiValue::as_hashref_multi
0000s0sHash::MultiValue::::clearHash::MultiValue::clear
0000s0sHash::MultiValue::::cloneHash::MultiValue::clone
0000s0sHash::MultiValue::::eachHash::MultiValue::each
0000s0sHash::MultiValue::::flattenHash::MultiValue::flatten
0000s0sHash::MultiValue::::from_mixedHash::MultiValue::from_mixed
0000s0sHash::MultiValue::::getHash::MultiValue::get
0000s0sHash::MultiValue::::get_oneHash::MultiValue::get_one
0000s0sHash::MultiValue::::keysHash::MultiValue::keys
0000s0sHash::MultiValue::::merge_mixedHash::MultiValue::merge_mixed
0000s0sHash::MultiValue::::mixedHash::MultiValue::mixed
0000s0sHash::MultiValue::::multiHash::MultiValue::multi
0000s0sHash::MultiValue::::refHash::MultiValue::ref
0000s0sHash::MultiValue::::removeHash::MultiValue::remove
0000s0sHash::MultiValue::::setHash::MultiValue::set
0000s0sHash::MultiValue::::valuesHash::MultiValue::values
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Hash::MultiValue;
2
3239µs265µs
# spent 42µs (18+23) within Hash::MultiValue::BEGIN@3 which was called: # once (18µs+23µs) by Plack::Request::BEGIN@9 at line 3
use strict;
# spent 42µs making 1 call to Hash::MultiValue::BEGIN@3 # spent 23µs making 1 call to strict::import
4235µs252µs
# spent 32µs (13+20) within Hash::MultiValue::BEGIN@4 which was called: # once (13µs+20µs) by Plack::Request::BEGIN@9 at line 4
no warnings 'void';
# spent 32µs making 1 call to Hash::MultiValue::BEGIN@4 # spent 20µs making 1 call to warnings::unimport
5281µs119µs
# spent 19µs within Hash::MultiValue::BEGIN@5 which was called: # once (19µs+0s) by Plack::Request::BEGIN@9 at line 5
use 5.006_002;
# spent 19µs making 1 call to Hash::MultiValue::BEGIN@5
61800nsour $VERSION = '0.15';
7
8234µs15µs
# spent 5µs within Hash::MultiValue::BEGIN@8 which was called: # once (5µs+0s) by Plack::Request::BEGIN@9 at line 8
use Carp ();
# spent 5µs making 1 call to Hash::MultiValue::BEGIN@8
9248µs2123µs
# spent 69µs (14+55) within Hash::MultiValue::BEGIN@9 which was called: # once (14µs+55µs) by Plack::Request::BEGIN@9 at line 9
use Scalar::Util qw(refaddr);
# spent 69µs making 1 call to Hash::MultiValue::BEGIN@9 # spent 55µs making 1 call to Exporter::import
10
11# there does not seem to be a relevant RT or perldelta entry for this
122226µs2137µs
# spent 76µs (15+61) within Hash::MultiValue::BEGIN@12 which was called: # once (15µs+61µs) by Plack::Request::BEGIN@9 at line 12
use constant _SPLICE_SAME_ARRAY_SEGFAULT => $] < '5.008007';
# spent 76µs making 1 call to Hash::MultiValue::BEGIN@12 # spent 61µs making 1 call to constant::import
13
141100nsmy %keys;
1510smy %values;
161400nsmy %registry;
17
18
# spent 40µs (34+6) within Hash::MultiValue::BEGIN@18 which was called: # once (34µs+6µs) by Plack::Request::BEGIN@9 at line 32
BEGIN {
191900ns require Config;
20110µs16µs my $needs_registry = ($^O eq 'Win32' || $Config::Config{useithreads});
# spent 6µs making 1 call to Config::FETCH
211600ns if ($needs_registry) {
22 *CLONE = sub {
23 foreach my $oldaddr (keys %registry) {
24 my $this = refaddr $registry{$oldaddr};
25 $keys{$this} = delete $keys{$oldaddr};
26 $values{$this} = delete $values{$oldaddr};
27 Scalar::Util::weaken($registry{$this} = delete $registry{$oldaddr});
28 }
2914µs };
30 }
31112µs *NEEDS_REGISTRY = sub () { $needs_registry };
3211.92ms140µs}
# spent 40µs making 1 call to Hash::MultiValue::BEGIN@18
33
341500nsif (defined &UNIVERSAL::ref::import) {
35 UNIVERSAL::ref->import;
36}
37
38sub ref { 'HASH' }
39
40
# spent 2.05s (1.67+379ms) within Hash::MultiValue::create which was called 100001 times, avg 20µs/call: # 100001 times (1.67s+379ms) by Hash::MultiValue::new at line 52, avg 20µs/call
sub create {
4110000145.7ms my $class = shift;
42100001156ms my $self = bless {}, $class;
43100001706ms100001185ms my $this = refaddr $self;
# spent 185ms making 100001 calls to Scalar::Util::refaddr, avg 2µs/call
44100001180ms $keys{$this} = [];
4510000185.4ms $values{$this} = [];
46100001722ms100001194ms Scalar::Util::weaken($registry{$this} = $self) if NEEDS_REGISTRY;
# spent 194ms making 100001 calls to Scalar::Util::weaken, avg 2µs/call
47100001385ms $self;
48}
49
50
# spent 3.76s (1.43+2.32) within Hash::MultiValue::new which was called 100001 times, avg 38µs/call: # 100001 times (1.43s+2.32s) by Plack::Request::_parse_query at line 96 of Plack/Request.pm, avg 38µs/call
sub new {
5110000157.4ms my $class = shift;
52100001259ms1000012.05s my $self = $class->create;
# spent 2.05s making 100001 calls to Hash::MultiValue::create, avg 20µs/call
53100001113ms unshift @_, $self;
541000011.59s2000021.79s goto &{ $self->can('merge_flat') };
# spent 1.52s making 100001 calls to Hash::MultiValue::merge_flat, avg 15µs/call # spent 276ms making 100001 calls to UNIVERSAL::can, avg 3µs/call
55}
56
57sub from_mixed {
58 my $class = shift;
59 my $self = $class->create;
60 unshift @_, $self;
61 goto &{ $self->can('merge_mixed') };
62}
63
64
# spent 1.94s (1.65+293ms) within Hash::MultiValue::DESTROY which was called 100001 times, avg 19µs/call: # 100001 times (1.65s+293ms) by HTTP::Server::PSGI::accept_loop at line 107 of HTTP/Server/PSGI.pm, avg 19µs/call
sub DESTROY {
65100001997ms100001293ms my $this = refaddr shift;
# spent 293ms making 100001 calls to Scalar::Util::refaddr, avg 3µs/call
66100001305ms delete $keys{$this};
67100001167ms delete $values{$this};
68100001640ms delete $registry{$this} if NEEDS_REGISTRY;
69}
70
71sub get {
72 my($self, $key) = @_;
73 $self->{$key};
74}
75
76
# spent 1.12s (1.06+59.1ms) within Hash::MultiValue::get_all which was called 102107 times, avg 11µs/call: # 102107 times (1.06s+59.1ms) by PONAPI::Server::_ponapi_query_params at line 262 of lib/PONAPI/Server.pm, avg 11µs/call
sub get_all {
7710210757.5ms my($self, $key) = @_;
78102107431ms10210759.1ms my $this = refaddr $self;
# spent 59.1ms making 102107 calls to Scalar::Util::refaddr, avg 579ns/call
7910210779.7ms my $k = $keys{$this};
80102107815ms (@{$values{$this}}[grep { $key eq $k->[$_] } 0 .. $#$k]);
81}
82
83sub get_one {
84 my ($self, $key) = @_;
85 my @v = $self->get_all($key);
86 return $v[0] if @v == 1;
87 Carp::croak "Key not found: $key" if not @v;
88 Carp::croak "Multiple values match: $key";
89}
90
91sub set {
92 my $self = shift;
93 my $key = shift;
94
95 my $this = refaddr $self;
96 my $k = $keys{$this};
97 my $v = $values{$this};
98
99 my @idx = grep { $key eq $k->[$_] } 0 .. $#$k;
100
101 my $added = @_ - @idx;
102 if ($added > 0) {
103 my $start = $#$k + 1;
104 push @$k, ($key) x $added;
105 push @idx, $start .. $#$k;
106 }
107 elsif ($added < 0) {
108 my ($start, @drop, @keep) = splice @idx, $added;
109 for my $i ($start+1 .. $#$k) {
110 if (@drop and $i == $drop[0]) {
111 shift @drop;
112 next;
113 }
114 push @keep, $i;
115 }
116
117 splice @$_, $start, 0+@$_, ( _SPLICE_SAME_ARRAY_SEGFAULT
118 ? @{[ @$_[@keep] ]} # force different source array
119 : @$_[@keep]
120 ) for $k, $v;
121 }
122
123 if (@_) {
124 @$v[@idx] = @_;
125 $self->{$key} = $_[-1];
126 }
127 else {
128 delete $self->{$key};
129 }
130
131 $self;
132}
133
134sub add {
135 my $self = shift;
136 my $key = shift;
137 $self->merge_mixed( $key => \@_ );
138 $self;
139}
140
141
# spent 1.52s (1.46+57.3ms) within Hash::MultiValue::merge_flat which was called 100001 times, avg 15µs/call: # 100001 times (1.46s+57.3ms) by Plack::Request::_parse_query at line 54, avg 15µs/call
sub merge_flat {
14210000163.7ms my $self = shift;
143100001425ms10000157.3ms my $this = refaddr $self;
# spent 57.3ms making 100001 calls to Scalar::Util::refaddr, avg 573ns/call
14410000167.1ms my $k = $keys{$this};
14510000173.4ms my $v = $values{$this};
146100001497ms push @{ $_ & 1 ? $v : $k }, $_[$_] for 0 .. $#_;
147100001242ms @{$self}{@$k} = @$v;
148100001456ms $self;
149}
150
151sub merge_mixed {
152 my $self = shift;
153 my $this = refaddr $self;
154 my $k = $keys{$this};
155 my $v = $values{$this};
156
157 my $hash;
158 $hash = shift if @_ == 1;
159
160 while ( my ($key, $value) = @_ ? splice @_, 0, 2 : each %$hash ) {
161 my @value = CORE::ref($value) eq 'ARRAY' ? @$value : $value;
162 next if not @value;
163 $self->{$key} = $value[-1];
164 push @$k, ($key) x @value;
165 push @$v, @value;
166 }
167
168 $self;
169}
170
171sub remove {
172 my ($self, $key) = @_;
173 $self->set($key);
174 $self;
175}
176
177sub clear {
178 my $self = shift;
179 %$self = ();
180 my $this = refaddr $self;
181 $keys{$this} = [];
182 $values{$this} = [];
183 $self;
184}
185
186sub clone {
187 my $self = shift;
188 CORE::ref($self)->new($self->flatten);
189}
190
191sub keys {
192 my $self = shift;
193 return @{$keys{refaddr $self}};
194}
195
196sub values {
197 my $self = shift;
198 return @{$values{refaddr $self}};
199}
200
201sub flatten {
202 my $self = shift;
203 my $this = refaddr $self;
204 my $k = $keys{$this};
205 my $v = $values{$this};
206 map { $k->[$_], $v->[$_] } 0 .. $#$k;
207}
208
209sub each {
210 my ($self, $code) = @_;
211 my $this = refaddr $self;
212 my $k = $keys{$this};
213 my $v = $values{$this};
214 for (0 .. $#$k) {
215 $code->($k->[$_], $v->[$_]);
216 }
217 return $self;
218}
219
220sub as_hashref {
221 my $self = shift;
222 my %hash = %$self;
223 \%hash;
224}
225
226sub as_hashref_mixed {
227 my $self = shift;
228 my $this = refaddr $self;
229 my $k = $keys{$this};
230 my $v = $values{$this};
231
232 my %hash;
233 push @{$hash{$k->[$_]}}, $v->[$_] for 0 .. $#$k;
234 for (CORE::values %hash) {
235 $_ = $_->[0] if 1 == @$_;
236 }
237
238 \%hash;
239}
240
241sub mixed { $_[0]->as_hashref_mixed }
242
243sub as_hashref_multi {
244 my $self = shift;
245 my $this = refaddr $self;
246 my $k = $keys{$this};
247 my $v = $values{$this};
248
249 my %hash;
250 push @{$hash{$k->[$_]}}, $v->[$_] for 0 .. $#$k;
251
252 \%hash;
253}
254
255sub multi { $_[0]->as_hashref_multi }
256
257sub STORABLE_freeze {
258 my $self = shift;
259 my $this = refaddr $self;
260 return '', $keys{$this}, $values{$this};
261}
262
263sub STORABLE_thaw {
264 my $self = shift;
265 my ($is_cloning, $serialised, $k, $v) = @_;
266 my $this = refaddr $self;
267 $keys {$this} = $k;
268 $values{$this} = $v;
269 @{$self}{@$k} = @$v;
270 return $self;
271}
272
27317µs1;
274__END__