← Index
NYTProf Performance Profile   « line view »
For ./view
  Run on Fri Jul 31 18:42:36 2015
Reported on Fri Jul 31 18:48:14 2015

Filename/var/www/foswikidev/core/lib/Foswiki/Prefs/Stack.pm
StatementsExecuted 13708 statements in 30.2ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
15222.70ms2.70msFoswiki::Prefs::Stack::::restoreFoswiki::Prefs::Stack::restore
63812.42ms2.79msFoswiki::Prefs::Stack::::newLevelFoswiki::Prefs::Stack::newLevel
673112.02ms2.02msFoswiki::Prefs::Stack::::finalizedBeforeFoswiki::Prefs::Stack::finalizedBefore
111111.67ms2.57msFoswiki::Prefs::Stack::::getPreferenceFoswiki::Prefs::Stack::getPreference
782311.22ms1.22msFoswiki::Prefs::Stack::::backAtLevelFoswiki::Prefs::Stack::backAtLevel
673111.07ms1.07msFoswiki::Prefs::Stack::::prefIsDefinedFoswiki::Prefs::Stack::prefIsDefined
20921978µs978µsFoswiki::Prefs::Stack::::_getLevelFoswiki::Prefs::Stack::_getLevel
10111419µs788µsFoswiki::Prefs::Stack::::getDefinitionLevelFoswiki::Prefs::Stack::getDefinitionLevel
6221385µs851µsFoswiki::Prefs::Stack::::insertFoswiki::Prefs::Stack::insert
1822271µs433µsFoswiki::Prefs::Stack::::finishFoswiki::Prefs::Stack::finish
711163µs516µsFoswiki::Prefs::Stack::::cloneFoswiki::Prefs::Stack::clone
2432118µs118µsFoswiki::Prefs::Stack::::newFoswiki::Prefs::Stack::new
404261µs61µsFoswiki::Prefs::Stack::::sizeFoswiki::Prefs::Stack::size
101126µs26µsFoswiki::Prefs::Stack::::finalizedFoswiki::Prefs::Stack::finalized
11113µs26µsFoswiki::Prefs::Stack::::BEGIN@26Foswiki::Prefs::Stack::BEGIN@26
11110µs12µsFoswiki::Prefs::Stack::::BEGIN@28Foswiki::Prefs::Stack::BEGIN@28
1118µs13µsFoswiki::Prefs::Stack::::BEGIN@27Foswiki::Prefs::Stack::BEGIN@27
1114µs4µsFoswiki::Prefs::Stack::::BEGIN@30Foswiki::Prefs::Stack::BEGIN@30
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;
26226µs238µs
# spent 26µs (13+13) within Foswiki::Prefs::Stack::BEGIN@26 which was called: # once (13µs+13µs) by Foswiki::Prefs::BEGIN@77 at line 26
use strict;
# spent 26µs making 1 call to Foswiki::Prefs::Stack::BEGIN@26 # spent 13µs making 1 call to strict::import
27222µs217µs
# spent 13µs (8+4) within Foswiki::Prefs::Stack::BEGIN@27 which was called: # once (8µs+4µs) by Foswiki::Prefs::BEGIN@77 at line 27
use warnings;
# spent 13µs making 1 call to Foswiki::Prefs::Stack::BEGIN@27 # spent 4µs making 1 call to warnings::import
28255µs215µs
# spent 12µs (10+3) within Foswiki::Prefs::Stack::BEGIN@28 which was called: # once (10µs+3µs) by Foswiki::Prefs::BEGIN@77 at line 28
use bytes;
# spent 12µs making 1 call to Foswiki::Prefs::Stack::BEGIN@28 # spent 3µs making 1 call to bytes::import
29
30
# spent 4µs within Foswiki::Prefs::Stack::BEGIN@30 which was called: # once (4µs+0s) by Foswiki::Prefs::BEGIN@77 at line 35
BEGIN {
3114µs if ( $Foswiki::cfg{UseLocale} ) {
32 require locale;
33 import locale();
34 }
351935µs14µs}
# spent 4µs making 1 call to Foswiki::Prefs::Stack::BEGIN@30
36
37=begin TML
38
39---++ ClassMethod new( $session )
40
41Creates a new Stack object.
42
43=cut
44
45
# spent 118µs within Foswiki::Prefs::Stack::new which was called 24 times, avg 5µs/call: # 16 times (79µs+0s) by Foswiki::Prefs::_getWebPrefsObj at line 188 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 5µs/call # 7 times (27µs+0s) by Foswiki::Prefs::Stack::clone at line 277, avg 4µs/call # once (13µs+0s) by Foswiki::Prefs::new at line 92 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm
sub new {
462410µs my $proto = shift;
472410µs my $class = ref($proto) || $proto;
482449µs my $this = {
49 'final' => {}, # Map preferences to the level the were finalized.
50 'levels' => [], # Maps leves to the corresponding backend objects.
51 'map' => {}, # Associate each preference with its bitstring map.
52 };
532481µs return bless $this, $class;
54}
55
56=begin TML
57
58---++ ObjectMethod finish()
59
60Break circular references.
61
62=cut
63
64# Note to developers; please undef *all* fields in the object explicitly,
65# whether they are references or not. That way this method is "golden
66# documentation" of the live fields in the object.
67
# spent 433µs (271+162) within Foswiki::Prefs::Stack::finish which was called 18 times, avg 24µs/call: # 17 times (99µs+28µs) by Foswiki::Prefs::Web::finish at line 60 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 7µs/call # once (173µs+134µs) by Foswiki::Prefs::finish at line 122 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm
sub finish {
68183µs my $this = shift;
691820µs undef $this->{'final'};
701812µs if ( $this->{'levels'} ) {
71 foreach my $back ( @{ $this->{'levels'} } ) {
7238172µs38162µs $back->finish();
# spent 160µs making 37 calls to Foswiki::Prefs::TopicRAM::finish, avg 4µs/call # spent 2µs making 1 call to Foswiki::Prefs::HASH::finish
73 }
74 }
751814µs undef $this->{'levels'};
761830µs undef $this->{'map'};
77}
78
79=begin TML
80
81---++ ObjectMethod size() -> $size
82
83Returns the size of the stack in number of levels.
84
85=cut
86
87
# spent 61µs within Foswiki::Prefs::Stack::size which was called 40 times, avg 2µs/call: # 16 times (21µs+0s) by Foswiki::Prefs::_pushWebInStack at line 163 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 1µs/call # 9 times (15µs+0s) by Foswiki::Prefs::pushTopicContext at line 274 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call # 8 times (14µs+0s) by Foswiki::Prefs::Web::isInTopOfStack at line 75 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 2µs/call # 7 times (11µs+0s) by Foswiki::Prefs::setPluginPreferences at line 338 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call
sub size {
8840125µs return scalar( @{ $_[0]->{levels} } );
89}
90
91=begin TML
92
93---++ ObjectMethod backAtLevel($level) -> $back
94
95Returns the backend object corresponding to $level. If $level is negative,
96consider that number from the top of the stack. -1 means the top element.
97
98=cut
99
100
# spent 1.22ms within Foswiki::Prefs::Stack::backAtLevel which was called 782 times, avg 2µs/call: # 673 times (1.09ms+0s) by Foswiki::Prefs::getPreference at line 447 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call # 101 times (117µs+0s) by Foswiki::Prefs::getPreference at line 455 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 1µs/call # 8 times (15µs+0s) by Foswiki::Prefs::popTopicContext at line 318 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call
sub backAtLevel {
1017822.33ms return $_[0]->{levels}->[ $_[1] ];
102}
103
104=begin TML
105
106---++ ObjectMethod finalizedBefore($pref, $level) -> $boolean
107
108Returns true if $pref was finalized somewhere earlier than $level. If $pref is
109finalized *in* $level or it's not finalized, returns true.
110
111=cut
112
113
# spent 2.02ms within Foswiki::Prefs::Stack::finalizedBefore which was called 673 times, avg 3µs/call: # 673 times (2.02ms+0s) by Foswiki::Prefs::getPreference at line 448 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 3µs/call
sub finalizedBefore {
114673350µs my ( $this, $key, $level ) = @_;
115673448µs $level += @{ $this->{levels} } if $level < 0;
11667315.0ms return exists $this->{final}{$key} && $this->{final}{$key} < $level;
117}
118
119=begin TML
120
121---++ ObjectMethod finalized($pref) -> $boolean
122
123Returns true if $pref in finalized.
124
125=cut
126
127
# spent 26µs within Foswiki::Prefs::Stack::finalized which was called 10 times, avg 3µs/call: # 10 times (26µs+0s) by Foswiki::Prefs::setSessionPreferences at line 402 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 3µs/call
sub finalized {
128106µs my ( $this, $key ) = @_;
1291035µs return exists $this->{final}{$key};
130}
131
132=begin TML
133
134---++ ObjectMethod prefs() -> @prefs
135
136Returns a list with the name of all defined prefs in the stack.
137
138=cut
139
140sub prefs {
141 return keys %{ $_[0]->{'map'} };
142}
143
144=begin TML
145
146---++ ObjectMethod prefIsDefined($pref) -> $boolean
147
148Returns true if $pref is defined somewhere in the stack.
149
150=cut
151
152
# spent 1.07ms within Foswiki::Prefs::Stack::prefIsDefined which was called 673 times, avg 2µs/call: # 673 times (1.07ms+0s) by Foswiki::Prefs::getPreference at line 451 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 2µs/call
sub prefIsDefined {
1536731.75ms return exists $_[0]->{'map'}{ $_[1] };
154}
155
156=begin TML
157
158---++ ObjectMethod insert($type, $pref, $value) -> $num
159
160Define preference named $pref of type $type as $value. $type can be 'Local' or
161'Set'.
162
163Returns the number of inserted preferences (0 or 1).
164
165=cut
166
167
# spent 851µs (385+466) within Foswiki::Prefs::Stack::insert which was called 62 times, avg 14µs/call: # 52 times (310µs+363µs) by Foswiki::Prefs::pushTopicContext at line 290 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 13µs/call # 10 times (75µs+103µs) by Foswiki::Prefs::setSessionPreferences at line 403 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 18µs/call
sub insert {
1686214µs my $this = shift;
169
1706224µs my $back = $this->{levels}->[-1];
1716258µs62466µs my $num = $back->insert(@_);
# spent 466µs making 62 calls to Foswiki::Prefs::HASH::insert, avg 8µs/call
172
1736213µs my $key = $_[1];
1746237µs $this->{'map'}{$key} = '' unless exists $this->{'map'}{$key};
175
1766224µs my $level = $#{ $this->{levels} };
1776274µs vec( $this->{'map'}{$key}, $level, 1 ) = 1;
178
17962128µs return $num;
180}
181
182=begin TML
183
184---++ ObjectMethod newLevel($back, $prefix)
185
186Pushes all preferences in $back on the stack, except for the finalized ones.
187Optionally $prefix preferences name in the index. This feature is used by
188plugins: A preference PREF defined in MyPlugin topic should be referenced by
189MYPLUGIN_PREF. In this example $prefix is MYPLUGIN_.
190
191=cut
192
193
# spent 2.79ms (2.42+362µs) within Foswiki::Prefs::Stack::newLevel which was called 63 times, avg 44µs/call: # 18 times (948µs+126µs) by Foswiki::Prefs::pushTopicContext at line 284 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 60µs/call # 17 times (781µs+107µs) by Foswiki::Prefs::_pushWebInStack at line 169 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 52µs/call # 9 times (87µs+32µs) by Foswiki::Prefs::pushTopicContext at line 288 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 13µs/call # 9 times (78µs+24µs) by Foswiki::Prefs::pushTopicContext at line 287 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 11µs/call # 7 times (174µs+31µs) by Foswiki::Prefs::setPluginPreferences at line 337 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 29µs/call # once (301µs+33µs) by Foswiki::Prefs::loadDefaultPreferences at line 368 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm # once (41µs+5µs) by Foswiki::Prefs::loadSitePreferences at line 385 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm # once (14µs+4µs) by Foswiki::Prefs::setUserPreferences at line 353 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm
sub newLevel {
1946330µs my ( $this, $back, $prefix ) = @_;
195
1966338µs push @{ $this->{levels} }, $back;
1976332µs my $level = $#{ $this->{levels} };
1986318µs $prefix ||= '';
19963397µs63249µs foreach ( map { $prefix . $_ } $back->prefs ) {
# spent 232µs making 54 calls to Foswiki::Prefs::TopicRAM::prefs, avg 4µs/call # spent 17µs making 9 calls to Foswiki::Prefs::HASH::prefs, avg 2µs/call
200773229µs next if exists $this->{final}{$_};
201714383µs $this->{'map'}{$_} = '' unless exists $this->{'map'}{$_};
202714657µs vec( $this->{'map'}{$_}, $level, 1 ) = 1;
203 }
204
20563240µs63114µs my @finalPrefs = split /[,\s]+/, ( $back->get('FINALPREFERENCES') || '' );
# spent 98µs making 54 calls to Foswiki::Prefs::TopicRAM::get, avg 2µs/call # spent 15µs making 9 calls to Foswiki::Prefs::HASH::get, avg 2µs/call
2066341µs foreach (@finalPrefs) {
207196122µs $this->{final}{$_} = $level
208 unless exists $this->{final}{$_};
209 }
210
21163150µs return $back;
212}
213
214=begin TML
215
216---++ ObjectMethod getDefinitionLevel($pref) -> $level
217
218Returns the $level in which $pref was defined or undef if it's not defined.
219
220=cut
221
222
# spent 788µs (419+369) within Foswiki::Prefs::Stack::getDefinitionLevel which was called 101 times, avg 8µs/call: # 101 times (419µs+369µs) by Foswiki::Prefs::getPreference at line 452 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 8µs/call
sub getDefinitionLevel {
22310145µs my ( $this, $pref ) = @_;
224 return
225101312µs101369µs exists $this->{'map'}{$pref} ? _getLevel( $this->{'map'}{$pref} ) : undef;
# spent 369µs making 101 calls to Foswiki::Prefs::Stack::_getLevel, avg 4µs/call
226}
227
228# Used to get the level of the highest 1, given a bitstring map.
229
# spent 978µs within Foswiki::Prefs::Stack::_getLevel which was called 209 times, avg 5µs/call: # 108 times (609µs+0s) by Foswiki::Prefs::Stack::getPreference at line 262, avg 6µs/call # 101 times (369µs+0s) by Foswiki::Prefs::Stack::getDefinitionLevel at line 225, avg 4µs/call
sub _getLevel {
230209107µs my $map = shift;
231 return
2322091.09ms int( log( ord( substr( $map, -1 ) ) ) / log(2) ) +
233 ( ( length($map) - 1 ) * 8 );
234}
235
236=begin TML
237
238---++ ObjectMethod getPreference($pref [, $level] ) -> $value
239
240Returns the $value of $pref, considering the stack rules (values in higher
241levels overrides those in lower levels).
242
243Optionally consider preferences at most $level. This is usefull to get a
244preference of Web if the stack has Web/Subweb. This makes it possible to use
245the same stack for Web and Web/Subweb.
246
247=cut
248
249
# spent 2.57ms (1.67+902µs) within Foswiki::Prefs::Stack::getPreference which was called 111 times, avg 23µs/call: # 111 times (1.67ms+902µs) by Foswiki::Prefs::Web::get at line 117 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 23µs/call
sub getPreference {
25011164µs my ( $this, $key, $level ) = @_;
25111196µs my $map = $this->{'map'}{$key};
25211125µs return unless defined $map;
25310849µs if ( defined $level ) {
254108365µs my $mask =
255 ( chr(0xFF) x int( $level / 8 ) )
256 . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 );
25710884µs $map &= $mask;
258108173µs substr( $map, -1 ) = ''
259 while length($map) > 0 && ord( substr( $map, -1 ) ) == 0;
26010837µs return unless length($map) > 0;
261 }
262108673µs216902µs return $this->{levels}->[ _getLevel($map) ]->get($key);
# spent 609µs making 108 calls to Foswiki::Prefs::Stack::_getLevel, avg 6µs/call # spent 293µs making 108 calls to Foswiki::Prefs::TopicRAM::get, avg 3µs/call
263}
264
265=begin TML
266
267---++ ObjectMethod clone($level ) -> $stack
268
269This constructs a new $stack object as a clone of this one, up to the given
270$level. If no $level is given, the resulting object is an extac copy.
271
272=cut
273
274
# spent 516µs (163+353) within Foswiki::Prefs::Stack::clone which was called 7 times, avg 74µs/call: # 7 times (163µs+353µs) by Foswiki::Prefs::Web::cloneStack at line 104 of /var/www/foswikidev/core/lib/Foswiki/Prefs/Web.pm, avg 74µs/call
sub clone {
27572µs my ( $this, $level ) = @_;
276
27776µs727µs my $clone = $this->new();
# spent 27µs making 7 calls to Foswiki::Prefs::Stack::new, avg 4µs/call
278781µs $clone->{'map'} = { %{ $this->{'map'} } };
27978µs $clone->{'levels'} = [ @{ $this->{levels} } ];
280720µs $clone->{'final'} = { %{ $this->{final} } };
281715µs7326µs $clone->restore($level) if defined $level;
# spent 326µs making 7 calls to Foswiki::Prefs::Stack::restore, avg 47µs/call
282
283715µs return $clone;
284}
285
286=begin TML
287
288---++ ObjectMethod restore($level)
289
290Restores tha stack to the state it was in the given $level.
291
292=cut
293
294
# spent 2.70ms within Foswiki::Prefs::Stack::restore which was called 15 times, avg 180µs/call: # 8 times (2.37ms+0s) by Foswiki::Prefs::popTopicContext at line 313 of /var/www/foswikidev/core/lib/Foswiki/Prefs.pm, avg 297µs/call # 7 times (326µs+0s) by Foswiki::Prefs::Stack::clone at line 281, avg 47µs/call
sub restore {
295157µs my ( $this, $level ) = @_;
296
29715136µs my @keys = grep { $this->{final}{$_} > $level } keys %{ $this->{final} };
298157µs delete @{ $this->{final} }{@keys};
2991528µs splice @{ $this->{levels} }, $level + 1;
300
3011537µs my $mask =
302 ( chr(0xFF) x int( $level / 8 ) )
303 . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 );
30415233µs foreach my $p ( keys %{ $this->{'map'} } ) {
3051564430µs $this->{'map'}{$p} &= $mask;
306
30715641.05ms while ( length( $this->{'map'}{$p} ) > 0
308 && ord( substr( $this->{'map'}{$p}, -1 ) ) == 0 )
309 {
31011399µs substr( $this->{'map'}{$p}, -1 ) = '';
311 }
312
3131564694µs delete $this->{'map'}{$p} if length( $this->{'map'}{$p} ) == 0;
314 }
315}
316
31712µs1;
318__END__