← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 19:05:14 2015
Reported on Fri Jul 31 19:08:09 2015

Filename/var/www/foswiki11/lib/Foswiki/Prefs/Stack.pm
StatementsExecuted 28142 statements in 52.2ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
8611116.0ms21.2msFoswiki::Prefs::Stack::::getPreferenceFoswiki::Prefs::Stack::getPreference
1308110.2ms11.4msFoswiki::Prefs::Stack::::newLevelFoswiki::Prefs::Stack::newLevel
42225.66ms5.66msFoswiki::Prefs::Stack::::restoreFoswiki::Prefs::Stack::restore
941213.45ms3.45msFoswiki::Prefs::Stack::::_getLevelFoswiki::Prefs::Stack::_getLevel
570112.20ms2.20msFoswiki::Prefs::Stack::::finalizedBeforeFoswiki::Prefs::Stack::finalizedBefore
659311.36ms1.36msFoswiki::Prefs::Stack::::backAtLevelFoswiki::Prefs::Stack::backAtLevel
36111.23ms3.91msFoswiki::Prefs::Stack::::cloneFoswiki::Prefs::Stack::clone
570111.22ms1.22msFoswiki::Prefs::Stack::::prefIsDefinedFoswiki::Prefs::Stack::prefIsDefined
128321.01ms1.01msFoswiki::Prefs::Stack::::newFoswiki::Prefs::Stack::new
9322865µs1.15msFoswiki::Prefs::Stack::::finishFoswiki::Prefs::Stack::finish
8311507µs944µsFoswiki::Prefs::Stack::::getDefinitionLevelFoswiki::Prefs::Stack::getDefinitionLevel
4821463µs1.00msFoswiki::Prefs::Stack::::insertFoswiki::Prefs::Stack::insert
15642382µs382µsFoswiki::Prefs::Stack::::sizeFoswiki::Prefs::Stack::size
111206µs209µsFoswiki::Prefs::Stack::::BEGIN@28Foswiki::Prefs::Stack::BEGIN@28
81152µs52µsFoswiki::Prefs::Stack::::finalizedFoswiki::Prefs::Stack::finalized
11116µs30µsFoswiki::Prefs::Stack::::BEGIN@26Foswiki::Prefs::Stack::BEGIN@26
1119µs15µsFoswiki::Prefs::Stack::::BEGIN@27Foswiki::Prefs::Stack::BEGIN@27
0000s0sFoswiki::Prefs::Stack::::prefsFoswiki::Prefs::Stack::prefs
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# See bottom of file for license and copyright information
2
3=begin TML
4
5---+ UNPUBLISHED package Foswiki::Prefs::Stack
6
7Foswiki preferences mechanism are like stacks:
8 * Preferences pushed later have precedence over ones pushed earlier I must
9 * be able to return (restore) to a state I was earlier
10
11This stack can exist as an index, so preference data is not copied everywhere.
12
13The index is composed by three elements:
14 * A bitstring map. Each preference has a bitmap. Each bit corresponds to a
15 level. The bit is 1 if the preference is defined at that level and 0
16 otherwise. If a preference is "defined" in some level, but it was
17 finalized, then the corresponding bit is 0.
18 * A level list storing a backend object that is associated with each level
19 * A final hash that maps preferences to the level they were finalized.
20
21This class deals with this stuff and must be used only by =Foswiki::Prefs=
22
23=cut
24
25package Foswiki::Prefs::Stack;
26227µs244µs
# spent 30µs (16+14) within Foswiki::Prefs::Stack::BEGIN@26 which was called: # once (16µs+14µs) by Foswiki::Prefs::BEGIN@70 at line 26
use strict;
# spent 30µs making 1 call to Foswiki::Prefs::Stack::BEGIN@26 # spent 14µs making 1 call to strict::import
27226µs221µs
# spent 15µs (9+6) within Foswiki::Prefs::Stack::BEGIN@27 which was called: # once (9µs+6µs) by Foswiki::Prefs::BEGIN@70 at line 27
use warnings;
# spent 15µs making 1 call to Foswiki::Prefs::Stack::BEGIN@27 # spent 6µs making 1 call to warnings::import
2821.14ms2212µs
# spent 209µs (206+3) within Foswiki::Prefs::Stack::BEGIN@28 which was called: # once (206µs+3µs) by Foswiki::Prefs::BEGIN@70 at line 28
use bytes;
# spent 209µs making 1 call to Foswiki::Prefs::Stack::BEGIN@28 # spent 3µs making 1 call to bytes::import
29
30=begin TML
31
32---++ ClassMethod new( $session )
33
34Creates a new Stack object.
35
36=cut
37
38
# spent 1.01ms within Foswiki::Prefs::Stack::new which was called 128 times, avg 8µs/call: # 91 times (768µs+0s) by Foswiki::Prefs::_getWebPrefsObj at line 183 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 8µs/call # 36 times (229µs+0s) by Foswiki::Prefs::Stack::clone at line 270, avg 6µs/call # once (10µs+0s) by Foswiki::Prefs::new at line 85 of /var/www/foswiki11/lib/Foswiki/Prefs.pm
sub new {
3912883µs my $proto = shift;
40128112µs my $class = ref($proto) || $proto;
41128420µs my $this = {
42 'final' => {}, # Map preferences to the level the were finalized.
43 'levels' => [], # Maps leves to the corresponding backend objects.
44 'map' => {}, # Associate each preference with its bitstring map.
45 };
46128591µs return bless $this, $class;
47}
48
49=begin TML
50
51---++ ObjectMethod finish()
52
53Break circular references.
54
55=cut
56
57# Note to developers; please undef *all* fields in the object explicitly,
58# whether they are references or not. That way this method is "golden
59# documentation" of the live fields in the object.
60
# spent 1.15ms (865µs+281µs) within Foswiki::Prefs::Stack::finish which was called 93 times, avg 12µs/call: # 92 times (643µs+187µs) by Foswiki::Prefs::Web::finish at line 53 of /var/www/foswiki11/lib/Foswiki/Prefs/Web.pm, avg 9µs/call # once (222µs+94µs) by Foswiki::Prefs::finish at line 115 of /var/www/foswiki11/lib/Foswiki/Prefs.pm
sub finish {
619316µs my $this = shift;
6293107µs undef $this->{'final'};
639370µs if ( $this->{'levels'} ) {
64 foreach my $back ( @{ $this->{'levels'} } ) {
65142367µs142281µs $back->finish();
# spent 279µs making 141 calls to Foswiki::Prefs::TopicRAM::finish, avg 2µs/call # spent 2µs making 1 call to Foswiki::Prefs::HASH::finish
66 }
67 }
689379µs undef $this->{'levels'};
6993171µs undef $this->{'map'};
70}
71
72=begin TML
73
74---++ ObjectMethod size() -> $size
75
76Returns the size of the stack in number of levels.
77
78=cut
79
80
# spent 382µs within Foswiki::Prefs::Stack::size which was called 156 times, avg 2µs/call: # 91 times (220µs+0s) by Foswiki::Prefs::_pushWebInStack at line 158 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 2µs/call # 51 times (102µs+0s) by Foswiki::Prefs::Web::isInTopOfStack at line 68 of /var/www/foswiki11/lib/Foswiki/Prefs/Web.pm, avg 2µs/call # 7 times (43µs+0s) by Foswiki::Prefs::setPluginPreferences at line 333 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 6µs/call # 7 times (16µs+0s) by Foswiki::Prefs::pushTopicContext at line 269 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 2µs/call
sub size {
81156713µs return scalar @{ $_[0]->{levels} };
82}
83
84=begin TML
85
86---++ ObjectMethod backAtLevel($level) -> $back
87
88Returns the backend object corresponding to $level. If $level is negative,
89consider that number from the top of the stack. -1 means the top element.
90
91=cut
92
93
# spent 1.36ms within Foswiki::Prefs::Stack::backAtLevel which was called 659 times, avg 2µs/call: # 570 times (1.19ms+0s) by Foswiki::Prefs::getPreference at line 442 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 2µs/call # 83 times (154µs+0s) by Foswiki::Prefs::getPreference at line 450 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 2µs/call # 6 times (19µs+0s) by Foswiki::Prefs::popTopicContext at line 313 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 3µs/call
sub backAtLevel {
946592.65ms return $_[0]->{levels}->[ $_[1] ];
95}
96
97=begin TML
98
99---++ ObjectMethod finalizedBefore($pref, $level) -> $boolean
100
101Returns true if $pref was finalized somewhere earlier than $level. If $pref is
102finalized *in* $level or it's not finalized, returns true.
103
104=cut
105
106
# spent 2.20ms within Foswiki::Prefs::Stack::finalizedBefore which was called 570 times, avg 4µs/call: # 570 times (2.20ms+0s) by Foswiki::Prefs::getPreference at line 443 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 4µs/call
sub finalizedBefore {
107570402µs my ( $this, $key, $level ) = @_;
108570492µs $level += @{ $this->{levels} } if $level < 0;
1095701.98ms return exists $this->{final}{$key} && $this->{final}{$key} < $level;
110}
111
112=begin TML
113
114---++ ObjectMethod finalized($pref) -> $boolean
115
116Returns true if $pref in finalized.
117
118=cut
119
120
# spent 52µs within Foswiki::Prefs::Stack::finalized which was called 8 times, avg 7µs/call: # 8 times (52µs+0s) by Foswiki::Prefs::setSessionPreferences at line 397 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 7µs/call
sub finalized {
121815µs my ( $this, $key ) = @_;
122865µs return exists $this->{final}{$key};
123}
124
125=begin TML
126
127---++ ObjectMethod prefs() -> @prefs
128
129Returns a list with the name of all defined prefs in the stack.
130
131=cut
132
133sub prefs {
134 return keys %{ $_[0]->{'map'} };
135}
136
137=begin TML
138
139---++ ObjectMethod prefIsDefined($pref) -> $boolean
140
141Returns true if $pref is defined somewhere in the stack.
142
143=cut
144
145
# spent 1.22ms within Foswiki::Prefs::Stack::prefIsDefined which was called 570 times, avg 2µs/call: # 570 times (1.22ms+0s) by Foswiki::Prefs::getPreference at line 446 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 2µs/call
sub prefIsDefined {
1465701.82ms return exists $_[0]->{'map'}{ $_[1] };
147}
148
149=begin TML
150
151---++ ObjectMethod insert($type, $pref, $value) -> $num
152
153Define preference named $pref of type $type as $value. $type can be 'Local' or
154'Set'.
155
156Returns the number of inserted preferences (0 or 1).
157
158=cut
159
160
# spent 1.00ms (463µs+538µs) within Foswiki::Prefs::Stack::insert which was called 48 times, avg 21µs/call: # 40 times (307µs+353µs) by Foswiki::Prefs::pushTopicContext at line 285 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 17µs/call # 8 times (156µs+184µs) by Foswiki::Prefs::setSessionPreferences at line 398 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 43µs/call
sub insert {
1614815µs my $this = shift;
162
1634829µs my $back = $this->{levels}->[-1];
1644881µs48538µs my $num = $back->insert(@_);
# spent 538µs making 48 calls to Foswiki::Prefs::HASH::insert, avg 11µs/call
165
1664829µs my $key = $_[1];
1674847µs $this->{'map'}{$key} = '' unless exists $this->{'map'}{$key};
168
1694824µs my $level = $#{ $this->{levels} };
1704886µs vec( $this->{'map'}{$key}, $level, 1 ) = 1;
171
17248144µs return $num;
173}
174
175=begin TML
176
177---++ ObjectMethod newLevel($back, $prefix)
178
179Pushes all preferences in $back on the stack, except for the finalized ones.
180Optionally $prefix preferences name in the index. This feature is used by
181plugins: A preference PREF defined in MyPlugin topic should be referenced by
182MYPLUGIN_PREF. In this example $prefix is MYPLUGIN_.
183
184=cut
185
186
# spent 11.4ms (10.2+1.24) within Foswiki::Prefs::Stack::newLevel which was called 130 times, avg 88µs/call: # 92 times (7.97ms+941µs) by Foswiki::Prefs::_pushWebInStack at line 164 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 97µs/call # 14 times (979µs+109µs) by Foswiki::Prefs::pushTopicContext at line 279 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 78µs/call # 7 times (595µs+93µs) by Foswiki::Prefs::setPluginPreferences at line 332 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 98µs/call # 7 times (90µs+42µs) by Foswiki::Prefs::pushTopicContext at line 283 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 19µs/call # 7 times (80µs+26µs) by Foswiki::Prefs::pushTopicContext at line 282 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 15µs/call # once (298µs+16µs) by Foswiki::Prefs::loadDefaultPreferences at line 363 of /var/www/foswiki11/lib/Foswiki/Prefs.pm # once (171µs+10µs) by Foswiki::Prefs::loadSitePreferences at line 380 of /var/www/foswiki11/lib/Foswiki/Prefs.pm # once (10µs+3µs) by Foswiki::Prefs::setUserPreferences at line 348 of /var/www/foswiki11/lib/Foswiki/Prefs.pm
sub newLevel {
187130108µs my ( $this, $back, $prefix ) = @_;
188
189130175µs push @{ $this->{levels} }, $back;
190130122µs my $level = $#{ $this->{levels} };
19113079µs $prefix ||= '';
1921301.62ms130763µs foreach ( map { $prefix . $_ } $back->prefs ) {
# spent 745µs making 123 calls to Foswiki::Prefs::TopicRAM::prefs, avg 6µs/call # spent 18µs making 7 calls to Foswiki::Prefs::HASH::prefs, avg 3µs/call
1931962882µs next if exists $this->{final}{$_};
19417151.78ms $this->{'map'}{$_} = '' unless exists $this->{'map'}{$_};
19517152.55ms vec( $this->{'map'}{$_}, $level, 1 ) = 1;
196 }
197
1981301.06ms130478µs my @finalPrefs = split /[,\s]+/, ( $back->get('FINALPREFERENCES') || '' );
# spent 454µs making 123 calls to Foswiki::Prefs::TopicRAM::get, avg 4µs/call # spent 24µs making 7 calls to Foswiki::Prefs::HASH::get, avg 3µs/call
199130143µs foreach (@finalPrefs) {
200595748µs $this->{final}{$_} = $level
201 unless exists $this->{final}{$_};
202 }
203
204130533µs return $back;
205}
206
207=begin TML
208
209---++ ObjectMethod getDefinitionLevel($pref) -> $level
210
211Returns the $level in which $pref was defined or undef if it's not defined.
212
213=cut
214
215
# spent 944µs (507+437) within Foswiki::Prefs::Stack::getDefinitionLevel which was called 83 times, avg 11µs/call: # 83 times (507µs+437µs) by Foswiki::Prefs::getPreference at line 447 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 11µs/call
sub getDefinitionLevel {
2168350µs my ( $this, $pref ) = @_;
217 return
21883411µs83437µs exists $this->{'map'}{$pref} ? _getLevel( $this->{'map'}{$pref} ) : undef;
# spent 437µs making 83 calls to Foswiki::Prefs::Stack::_getLevel, avg 5µs/call
219}
220
221# Used to get the level of the highest 1, given a bitstring map.
222
# spent 3.45ms within Foswiki::Prefs::Stack::_getLevel which was called 941 times, avg 4µs/call: # 858 times (3.01ms+0s) by Foswiki::Prefs::Stack::getPreference at line 255, avg 4µs/call # 83 times (437µs+0s) by Foswiki::Prefs::Stack::getDefinitionLevel at line 218, avg 5µs/call
sub _getLevel {
223941337µs my $map = shift;
224 return
2259418.54ms int( log( ord( substr( $map, -1 ) ) ) / log(2) ) +
226 ( ( length($map) - 1 ) * 8 );
227}
228
229=begin TML
230
231---++ ObjectMethod getPreference($pref [, $level] ) -> $value
232
233Returns the $value of $pref, considering the stack rules (values in higher
234levels overrides those in lower levels).
235
236Optionally consider preferences at most $level. This is usefull to get a
237preference of Web if the stack has Web/Subweb. This makes it possible to use
238the same stack for Web and Web/Subweb.
239
240=cut
241
242
# spent 21.2ms (16.0+5.14) within Foswiki::Prefs::Stack::getPreference which was called 861 times, avg 25µs/call: # 861 times (16.0ms+5.14ms) by Foswiki::Prefs::Web::get at line 110 of /var/www/foswiki11/lib/Foswiki/Prefs/Web.pm, avg 25µs/call
sub getPreference {
243861472µs my ( $this, $key, $level ) = @_;
244861648µs my $map = $this->{'map'}{$key};
245861154µs return unless defined $map;
246858307µs if ( defined $level ) {
2478582.44ms my $mask =
248 ( chr(0xFF) x int( $level / 8 ) )
249 . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 );
250858490µs $map &= $mask;
2518581.18ms substr( $map, -1 ) = ''
252 while length($map) > 0 && ord( substr( $map, -1 ) ) == 0;
253858368µs return unless length($map) > 0;
254 }
2558588.33ms17165.14ms return $this->{levels}->[ _getLevel($map) ]->get($key);
# spent 3.01ms making 858 calls to Foswiki::Prefs::Stack::_getLevel, avg 4µs/call # spent 2.13ms making 858 calls to Foswiki::Prefs::TopicRAM::get, avg 2µs/call
256}
257
258=begin TML
259
260---++ ObjectMethod clone($level ) -> $stack
261
262This constructs a new $stack object as a clone of this one, up to the given
263$level. If no $level is given, the resulting object is an extac copy.
264
265=cut
266
267
# spent 3.91ms (1.23+2.68) within Foswiki::Prefs::Stack::clone which was called 36 times, avg 109µs/call: # 36 times (1.23ms+2.68ms) by Foswiki::Prefs::Web::cloneStack at line 97 of /var/www/foswiki11/lib/Foswiki/Prefs/Web.pm, avg 109µs/call
sub clone {
2683620µs my ( $this, $level ) = @_;
269
2703644µs36229µs my $clone = $this->new();
# spent 229µs making 36 calls to Foswiki::Prefs::Stack::new, avg 6µs/call
27136585µs $clone->{'map'} = { %{ $this->{'map'} } };
2723663µs $clone->{'levels'} = [ @{ $this->{levels} } ];
27336155µs $clone->{'final'} = { %{ $this->{final} } };
27436127µs362.45ms $clone->restore($level) if defined $level;
# spent 2.45ms making 36 calls to Foswiki::Prefs::Stack::restore, avg 68µs/call
275
27636118µs return $clone;
277}
278
279=begin TML
280
281---++ ObjectMethod restore($level)
282
283Restores tha stack to the state it was in the given $level.
284
285=cut
286
287
# spent 5.66ms within Foswiki::Prefs::Stack::restore which was called 42 times, avg 135µs/call: # 36 times (2.45ms+0s) by Foswiki::Prefs::Stack::clone at line 274, avg 68µs/call # 6 times (3.20ms+0s) by Foswiki::Prefs::popTopicContext at line 308 of /var/www/foswiki11/lib/Foswiki/Prefs.pm, avg 534µs/call
sub restore {
2884243µs my ( $this, $level ) = @_;
289
29042332µs my @keys = grep { $this->{final}{$_} > $level } keys %{ $this->{final} };
2914234µs delete @{ $this->{final} }{@keys};
29242102µs splice @{ $this->{levels} }, $level + 1;
293
29442159µs my $mask =
295 ( chr(0xFF) x int( $level / 8 ) )
296 . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 );
29742645µs foreach my $p ( keys %{ $this->{'map'} } ) {
29820241.01ms $this->{'map'}{$p} &= $mask;
299
30020241.98ms while ( length( $this->{'map'}{$p} ) > 0
301 && ord( substr( $this->{'map'}{$p}, -1 ) ) == 0 )
302 {
303139186µs substr( $this->{'map'}{$p}, -1 ) = '';
304 }
305
30620241.26ms delete $this->{'map'}{$p} if length( $this->{'map'}{$p} ) == 0;
307 }
308}
309
31012µs1;
311__END__