← Index
NYTProf Performance Profile   « block view • line view • sub view »
For /usr/local/src/github.com/foswiki/core/bin/view
  Run on Sun Dec 4 17:17:59 2011
Reported on Sun Dec 4 17:26:42 2011

Filename/usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs/Stack.pm
StatementsExecuted 22282 statements in 73.6ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
201129.3ms29.3msFoswiki::Prefs::Stack::::restoreFoswiki::Prefs::Stack::restore
69719.80ms11.0msFoswiki::Prefs::Stack::::newLevelFoswiki::Prefs::Stack::newLevel
325218.25ms20.1msFoswiki::Prefs::Stack::::insertFoswiki::Prefs::Stack::insert
618117.26ms7.26msFoswiki::Prefs::Stack::::finalizedBeforeFoswiki::Prefs::Stack::finalizedBefore
724313.54ms3.54msFoswiki::Prefs::Stack::::backAtLevelFoswiki::Prefs::Stack::backAtLevel
618113.15ms3.15msFoswiki::Prefs::Stack::::prefIsDefinedFoswiki::Prefs::Stack::prefIsDefined
167112.32ms4.07msFoswiki::Prefs::Stack::::getDefinitionLevelFoswiki::Prefs::Stack::getDefinitionLevel
207212.10ms2.10msFoswiki::Prefs::Stack::::_getLevelFoswiki::Prefs::Stack::_getLevel
67111.87ms2.52msFoswiki::Prefs::Stack::::getPreferenceFoswiki::Prefs::Stack::getPreference
5411474µs474µsFoswiki::Prefs::Stack::::finalizedFoswiki::Prefs::Stack::finalized
111358µs365µsFoswiki::Prefs::Stack::::BEGIN@28Foswiki::Prefs::Stack::BEGIN@28
422294µs418µsFoswiki::Prefs::Stack::::finishFoswiki::Prefs::Stack::finish
2421229µs229µsFoswiki::Prefs::Stack::::sizeFoswiki::Prefs::Stack::size
421112µs112µsFoswiki::Prefs::Stack::::newFoswiki::Prefs::Stack::new
11125µs34µsFoswiki::Prefs::Stack::::BEGIN@26Foswiki::Prefs::Stack::BEGIN@26
11122µs42µsFoswiki::Prefs::Stack::::BEGIN@27Foswiki::Prefs::Stack::BEGIN@27
0000s0sFoswiki::Prefs::Stack::::cloneFoswiki::Prefs::Stack::clone
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;
26246µs242µs
# spent 34µs (25+8) within Foswiki::Prefs::Stack::BEGIN@26 which was called: # once (25µs+8µs) by Foswiki::Prefs::BEGIN@70 at line 26
use strict;
# spent 34µs making 1 call to Foswiki::Prefs::Stack::BEGIN@26 # spent 8µs making 1 call to strict::import
27245µs263µs
# spent 42µs (22+20) within Foswiki::Prefs::Stack::BEGIN@27 which was called: # once (22µs+20µs) by Foswiki::Prefs::BEGIN@70 at line 27
use warnings;
# spent 42µs making 1 call to Foswiki::Prefs::Stack::BEGIN@27 # spent 20µs making 1 call to warnings::import
2822.01ms2371µs
# spent 365µs (358+6) within Foswiki::Prefs::Stack::BEGIN@28 which was called: # once (358µs+6µs) by Foswiki::Prefs::BEGIN@70 at line 28
use bytes;
# spent 365µs making 1 call to Foswiki::Prefs::Stack::BEGIN@28 # spent 6µ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 112µs within Foswiki::Prefs::Stack::new which was called 4 times, avg 28µs/call: # 3 times (89µs+0s) by Foswiki::Prefs::_getWebPrefsObj at line 181 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 30µs/call # once (23µs+0s) by Foswiki::Prefs::new at line 85 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm
sub new {
3916108µs my $proto = shift;
40 my $class = ref($proto) || $proto;
41 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 };
46 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 418µs (294+123) within Foswiki::Prefs::Stack::finish which was called 4 times, avg 104µs/call: # 3 times (95µs+24µs) by Foswiki::Prefs::Web::finish at line 53 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs/Web.pm, avg 40µs/call # once (199µs+99µs) by Foswiki::Prefs::finish at line 115 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm
sub finish {
612088µs my $this = shift;
62 undef $this->{'final'};
63420µs if ( $this->{'levels'} ) {
6447µs foreach my $back ( @{ $this->{'levels'} } ) {
659169µs9123µs $back->finish();
# spent 119µs making 8 calls to Foswiki::Prefs::TopicRAM::finish, avg 15µs/call # spent 4µs making 1 call to Foswiki::Prefs::HASH::finish
66 }
67 }
68 undef $this->{'levels'};
69 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 229µs within Foswiki::Prefs::Stack::size which was called 24 times, avg 10µs/call: # 21 times (200µs+0s) by Foswiki::Prefs::pushTopicContext at line 267 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 10µs/call # 3 times (29µs+0s) by Foswiki::Prefs::_pushWebInStack at line 156 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 10µs/call
sub size {
8148259µ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 3.54ms within Foswiki::Prefs::Stack::backAtLevel which was called 724 times, avg 5µs/call: # 517 times (2.51ms+0s) by Foswiki::Prefs::getPreference at line 439 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 5µs/call # 167 times (842µs+0s) by Foswiki::Prefs::getPreference at line 445 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 5µs/call # 40 times (194µs+0s) by Foswiki::Prefs::popTopicContext at line 309 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 5µs/call
sub backAtLevel {
947244.45ms 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 7.26ms within Foswiki::Prefs::Stack::finalizedBefore which was called 618 times, avg 12µs/call: # 618 times (7.26ms+0s) by Foswiki::Prefs::getPreference at line 439 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 12µs/call
sub finalizedBefore {
10718547.36ms my ( $this, $key, $level ) = @_;
1086181.10ms $level += @{ $this->{levels} } if $level < 0;
109 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 474µs within Foswiki::Prefs::Stack::finalized which was called 54 times, avg 9µs/call: # 54 times (474µs+0s) by Foswiki::Prefs::setSessionPreferences at line 394 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 9µs/call
sub finalized {
121108564µs my ( $this, $key ) = @_;
122 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 3.15ms within Foswiki::Prefs::Stack::prefIsDefined which was called 618 times, avg 5µs/call: # 618 times (3.15ms+0s) by Foswiki::Prefs::getPreference at line 441 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 5µs/call
sub prefIsDefined {
1466183.92ms 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 20.1ms (8.25+11.9) within Foswiki::Prefs::Stack::insert which was called 325 times, avg 62µs/call: # 271 times (6.64ms+9.48ms) by Foswiki::Prefs::pushTopicContext at line 284 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 59µs/call # 54 times (1.62ms+2.39ms) by Foswiki::Prefs::setSessionPreferences at line 395 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 74µs/call
sub insert {
16126007.65ms my $this = shift;
162
163 my $back = $this->{levels}->[-1];
16432511.9ms my $num = $back->insert(@_);
# spent 11.9ms making 325 calls to Foswiki::Prefs::HASH::insert, avg 37µs/call
165
166 my $key = $_[1];
167 $this->{'map'}{$key} = '' unless exists $this->{'map'}{$key};
168
169325496µs my $level = $#{ $this->{levels} };
170 vec( $this->{'map'}{$key}, $level, 1 ) = 1;
171
172 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.0ms (9.80+1.20) within Foswiki::Prefs::Stack::newLevel which was called 69 times, avg 159µs/call: # 21 times (5.20ms+431µs) by Foswiki::Prefs::pushTopicContext at line 277 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 268µs/call # 21 times (1.05ms+315µs) by Foswiki::Prefs::pushTopicContext at line 280 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 65µs/call # 21 times (842µs+282µs) by Foswiki::Prefs::pushTopicContext at line 281 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 54µs/call # 3 times (850µs+73µs) by Foswiki::Prefs::_pushWebInStack at line 162 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 308µs/call # once (1.35ms+56µs) by Foswiki::Prefs::loadDefaultPreferences at line 360 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm # once (472µs+26µs) by Foswiki::Prefs::loadSitePreferences at line 377 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm # once (37µs+15µs) by Foswiki::Prefs::setUserPreferences at line 345 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm
sub newLevel {
1875523.72ms my ( $this, $back, $prefix ) = @_;
188
18969127µs push @{ $this->{levels} }, $back;
19069105µs my $level = $#{ $this->{levels} };
191 $prefix ||= '';
192623813µs69709µs foreach ( map { $prefix . $_ } $back->prefs ) {
# spent 577µs making 48 calls to Foswiki::Prefs::TopicRAM::prefs, avg 12µs/call # spent 131µs making 21 calls to Foswiki::Prefs::HASH::prefs, avg 6µs/call
19315893.96ms next if exists $this->{final}{$_};
194 $this->{'map'}{$_} = '' unless exists $this->{'map'}{$_};
195 vec( $this->{'map'}{$_}, $level, 1 ) = 1;
196 }
197
19869489µs my @finalPrefs = split /[,\s]+/, ( $back->get('FINALPREFERENCES') || '' );
# spent 338µs making 48 calls to Foswiki::Prefs::TopicRAM::get, avg 7µs/call # spent 150µs making 21 calls to Foswiki::Prefs::HASH::get, avg 7µs/call
199 foreach (@finalPrefs) {
200276867µs $this->{final}{$_} = $level
201 unless exists $this->{final}{$_};
202 }
203
204 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 4.07ms (2.32+1.75) within Foswiki::Prefs::Stack::getDefinitionLevel which was called 167 times, avg 24µs/call: # 167 times (2.32ms+1.75ms) by Foswiki::Prefs::getPreference at line 442 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 24µs/call
sub getDefinitionLevel {
2163342.01ms my ( $this, $pref ) = @_;
217 return
2181671.75ms exists $this->{'map'}{$pref} ? _getLevel( $this->{'map'}{$pref} ) : undef;
# spent 1.75ms making 167 calls to Foswiki::Prefs::Stack::_getLevel, avg 10µs/call
219}
220
221# Used to get the level of the highest 1, given a bitstring map.
222
# spent 2.10ms within Foswiki::Prefs::Stack::_getLevel which was called 207 times, avg 10µs/call: # 167 times (1.75ms+0s) by Foswiki::Prefs::Stack::getDefinitionLevel at line 218, avg 10µs/call # 40 times (354µs+0s) by Foswiki::Prefs::Stack::getPreference at line 255, avg 9µs/call
sub _getLevel {
2234142.60ms my $map = shift;
224 return
225 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 2.52ms (1.87+643µs) within Foswiki::Prefs::Stack::getPreference which was called 67 times, avg 38µs/call: # 67 times (1.87ms+643µs) by Foswiki::Prefs::Web::get at line 110 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs/Web.pm, avg 38µs/call
sub getPreference {
2432811.21ms my ( $this, $key, $level ) = @_;
244 my $map = $this->{'map'}{$key};
245 return unless defined $map;
246160536µs if ( defined $level ) {
247 my $mask =
248 ( chr(0xFF) x int( $level / 8 ) )
249 . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 );
250 $map &= $mask;
251 substr( $map, -1 ) = ''
252 while length($map) > 0 && ord( substr( $map, -1 ) ) == 0;
253 return unless length($map) > 0;
254 }
25580644µs return $this->{levels}->[ _getLevel($map) ]->get($key);
# spent 354µs making 40 calls to Foswiki::Prefs::Stack::_getLevel, avg 9µs/call # spent 289µs making 40 calls to Foswiki::Prefs::TopicRAM::get, avg 7µ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
267sub clone {
268 my ( $this, $level ) = @_;
269
270 my $clone = $this->new();
271 $clone->{'map'} = { %{ $this->{'map'} } };
272 $clone->{'levels'} = [ @{ $this->{levels} } ];
273 $clone->{'final'} = { %{ $this->{final} } };
274 $clone->restore($level) if defined $level;
275
276 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 29.3ms within Foswiki::Prefs::Stack::restore which was called 20 times, avg 1.47ms/call: # 20 times (29.3ms+0s) by Foswiki::Prefs::popTopicContext at line 306 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Prefs.pm, avg 1.47ms/call
sub restore {
2881202.43ms my ( $this, $level ) = @_;
289
290460718µs my @keys = grep { $this->{final}{$_} > $level } keys %{ $this->{final} };
2912032µs delete @{ $this->{final} }{@keys};
2922029µs splice @{ $this->{levels} }, $level + 1;
293
294 my $mask =
295 ( chr(0xFF) x int( $level / 8 ) )
296 . chr( ( 2**( ( $level % 8 ) + 1 ) ) - 1 );
2972038µs foreach my $p ( keys %{ $this->{'map'} } ) {
2981011625.0ms $this->{'map'}{$p} &= $mask;
299
300 while ( length( $this->{'map'}{$p} ) > 0
301 && ord( substr( $this->{'map'}{$p}, -1 ) ) == 0 )
302 {
3032041.04ms substr( $this->{'map'}{$p}, -1 ) = '';
304 }
305
306 delete $this->{'map'}{$p} if length( $this->{'map'}{$p} ) == 0;
307 }
308}
309
31014µs1;
311__END__