Filename | /var/www/foswiki11/lib/Foswiki/MetaCache.pm |
Statements | Executed 241464 statements in 245ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
26366 | 4 | 3 | 241ms | 1.16s | get | Foswiki::MetaCache::
1 | 1 | 1 | 2.79ms | 2.79ms | finish | Foswiki::MetaCache::
1 | 1 | 1 | 33µs | 33µs | new | Foswiki::MetaCache::
1 | 1 | 1 | 14µs | 27µs | BEGIN@3 | Foswiki::MetaCache::
1 | 1 | 1 | 10µs | 40µs | BEGIN@23 | Foswiki::MetaCache::
1 | 1 | 1 | 10µs | 52µs | BEGIN@31 | Foswiki::MetaCache::
1 | 1 | 1 | 10µs | 22µs | BEGIN@20 | Foswiki::MetaCache::
1 | 1 | 1 | 9µs | 14µs | BEGIN@4 | Foswiki::MetaCache::
1 | 1 | 1 | 4µs | 4µs | BEGIN@24 | Foswiki::MetaCache::
1 | 1 | 1 | 3µs | 3µs | BEGIN@26 | Foswiki::MetaCache::
1 | 1 | 1 | 3µs | 3µs | BEGIN@21 | Foswiki::MetaCache::
1 | 1 | 1 | 3µs | 3µs | BEGIN@22 | Foswiki::MetaCache::
1 | 1 | 1 | 3µs | 3µs | BEGIN@25 | Foswiki::MetaCache::
0 | 0 | 0 | 0s | 0s | hasCached | Foswiki::MetaCache::
0 | 0 | 0 | 0s | 0s | removeMeta | Foswiki::MetaCache::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | # See bottom of file for license and copyright information | ||||
2 | package Foswiki::MetaCache; | ||||
3 | 2 | 31µs | 2 | 40µs | # spent 27µs (14+13) within Foswiki::MetaCache::BEGIN@3 which was called:
# once (14µs+13µs) by Foswiki::Search::BEGIN@24 at line 3 # spent 27µs making 1 call to Foswiki::MetaCache::BEGIN@3
# spent 13µs making 1 call to strict::import |
4 | 2 | 37µs | 2 | 20µs | # spent 14µs (9+5) within Foswiki::MetaCache::BEGIN@4 which was called:
# once (9µs+5µs) by Foswiki::Search::BEGIN@24 at line 4 # spent 14µs making 1 call to Foswiki::MetaCache::BEGIN@4
# spent 5µs making 1 call to warnings::import |
5 | |||||
6 | =begin TML | ||||
7 | |||||
8 | ---+ package Foswiki::MetaCache | ||||
9 | |||||
10 | A cache of Meta objects - initially used to speed up searching and sorting, but by foswiki 2.0 hopefully this | ||||
11 | will be used for all readonly accesses to the store. | ||||
12 | |||||
13 | Replaces the mishmash of the Search InfoCache Support package; cache of topic info. | ||||
14 | When information about search hits is | ||||
15 | compiled for output, this cache is used to avoid recovering the same info | ||||
16 | about the same topic more than once. | ||||
17 | |||||
18 | =cut | ||||
19 | |||||
20 | 2 | 22µs | 2 | 34µs | # spent 22µs (10+12) within Foswiki::MetaCache::BEGIN@20 which was called:
# once (10µs+12µs) by Foswiki::Search::BEGIN@24 at line 20 # spent 22µs making 1 call to Foswiki::MetaCache::BEGIN@20
# spent 12µs making 1 call to Assert::import |
21 | 2 | 18µs | 1 | 3µs | # spent 3µs within Foswiki::MetaCache::BEGIN@21 which was called:
# once (3µs+0s) by Foswiki::Search::BEGIN@24 at line 21 # spent 3µs making 1 call to Foswiki::MetaCache::BEGIN@21 |
22 | 2 | 20µs | 1 | 3µs | # spent 3µs within Foswiki::MetaCache::BEGIN@22 which was called:
# once (3µs+0s) by Foswiki::Search::BEGIN@24 at line 22 # spent 3µs making 1 call to Foswiki::MetaCache::BEGIN@22 |
23 | 2 | 27µs | 2 | 70µs | # spent 40µs (10+30) within Foswiki::MetaCache::BEGIN@23 which was called:
# once (10µs+30µs) by Foswiki::Search::BEGIN@24 at line 23 # spent 40µs making 1 call to Foswiki::MetaCache::BEGIN@23
# spent 30µs making 1 call to Exporter::import |
24 | 2 | 17µs | 1 | 4µs | # spent 4µs within Foswiki::MetaCache::BEGIN@24 which was called:
# once (4µs+0s) by Foswiki::Search::BEGIN@24 at line 24 # spent 4µs making 1 call to Foswiki::MetaCache::BEGIN@24 |
25 | 2 | 22µs | 1 | 3µs | # spent 3µs within Foswiki::MetaCache::BEGIN@25 which was called:
# once (3µs+0s) by Foswiki::Search::BEGIN@24 at line 25 # spent 3µs making 1 call to Foswiki::MetaCache::BEGIN@25 |
26 | 2 | 24µs | 1 | 3µs | # spent 3µs within Foswiki::MetaCache::BEGIN@26 which was called:
# once (3µs+0s) by Foswiki::Search::BEGIN@24 at line 26 # spent 3µs making 1 call to Foswiki::MetaCache::BEGIN@26 |
27 | |||||
28 | #use Monitor (); | ||||
29 | #Monitor::MonitorMethod('Foswiki::MetaCache', 'getTopicListIterator'); | ||||
30 | |||||
31 | 2 | 647µs | 2 | 94µs | # spent 52µs (10+42) within Foswiki::MetaCache::BEGIN@31 which was called:
# once (10µs+42µs) by Foswiki::Search::BEGIN@24 at line 31 # spent 52µs making 1 call to Foswiki::MetaCache::BEGIN@31
# spent 42µs making 1 call to constant::import |
32 | |||||
33 | =begin TML | ||||
34 | |||||
35 | ---++ ClassMethod new($session) | ||||
36 | |||||
37 | =cut | ||||
38 | |||||
39 | # spent 33µs within Foswiki::MetaCache::new which was called:
# once (33µs+0s) by Foswiki::Search::metacache at line 93 of /var/www/foswiki11/lib/Foswiki/Search.pm | ||||
40 | 1 | 2µs | my ( $class, $session ) = @_; | ||
41 | |||||
42 | #my $this = $class->SUPER::new([]); | ||||
43 | 1 | 27µs | my $this = bless( | ||
44 | { | ||||
45 | session => $session, | ||||
46 | cache => {}, | ||||
47 | new_count => 0, | ||||
48 | get_count => 0, | ||||
49 | undef_count => 0, | ||||
50 | meta_cache_session_user => $session->{user}, | ||||
51 | }, | ||||
52 | $class | ||||
53 | ); | ||||
54 | |||||
55 | 1 | 7µs | return $this; | ||
56 | } | ||||
57 | |||||
58 | =begin TML | ||||
59 | |||||
60 | ---++ ObjectMethod finish() | ||||
61 | Break circular references. | ||||
62 | |||||
63 | Note to developers; please undef *all* fields in the object explicitly, | ||||
64 | whether they are references or not. That way this method is "golden | ||||
65 | documentation" of the live fields in the object. | ||||
66 | |||||
67 | =cut | ||||
68 | |||||
69 | # spent 2.79ms within Foswiki::MetaCache::finish which was called:
# once (2.79ms+0s) by Foswiki::Search::finish at line 77 of /var/www/foswiki11/lib/Foswiki/Search.pm | ||||
70 | 1 | 800ns | my $this = shift; | ||
71 | 1 | 1µs | undef $this->{session}; | ||
72 | |||||
73 | #must clear cache every request until the cache is hooked up to Store's save | ||||
74 | |||||
75 | 1 | 5µs | foreach my $web ( keys( %{ $this->{cache} } ) ) { | ||
76 | 2 | 709µs | foreach my $topic ( keys( %{ $this->{cache}->{$web} } ) ) { | ||
77 | 305 | 1.89ms | undef $this->{cache}->{$web}{$topic}; | ||
78 | 305 | 106µs | $this->{undef_count}++; | ||
79 | } | ||||
80 | 2 | 67µs | undef $this->{cache}->{$web}; | ||
81 | } | ||||
82 | 1 | 1µs | undef $this->{cache}; | ||
83 | |||||
84 | 1 | 6µs | if (TRACE) { | ||
85 | print STDERR | ||||
86 | "MetaCache: new: $this->{new_count} get: $this->{get_count} undef: $this->{undef_count} \n"; | ||||
87 | } | ||||
88 | |||||
89 | } | ||||
90 | |||||
91 | =begin TML | ||||
92 | |||||
93 | ---++ ObjectMethod hasCached($webtopic) -> boolean | ||||
94 | |||||
95 | returns true if the topic is already int he cache. | ||||
96 | |||||
97 | =cut | ||||
98 | |||||
99 | sub hasCached { | ||||
100 | my ( $this, $web, $topic ) = @_; | ||||
101 | ASSERT( defined($topic) ) if DEBUG; | ||||
102 | return unless ( defined($topic) ); | ||||
103 | |||||
104 | return defined( $this->{cache}->{$web}{$topic} ); | ||||
105 | } | ||||
106 | |||||
107 | sub removeMeta { | ||||
108 | my ( $this, $web, $topic ) = @_; | ||||
109 | |||||
110 | if ( defined($topic) ) { | ||||
111 | my $cached_webtopic = $this->{cache}->{$web}{$topic}; | ||||
112 | |||||
113 | if ($cached_webtopic) { | ||||
114 | $cached_webtopic->finish() if blessed($cached_webtopic); | ||||
115 | delete $this->{cache}->{$web}{$topic}; | ||||
116 | } | ||||
117 | } | ||||
118 | elsif ( defined($web) ) { | ||||
119 | foreach my $topic ( keys( %{ $this->{cache}->{$web} } ) ) { | ||||
120 | $this->removeMeta( $web, $topic ); | ||||
121 | } | ||||
122 | delete $this->{cache}->{$web}; | ||||
123 | } | ||||
124 | |||||
125 | return; | ||||
126 | } | ||||
127 | |||||
128 | =begin TML | ||||
129 | |||||
130 | ---++ ObjectMethod get($webtopic, $meta) -> a cache obj (sorry, needs to be refactored out to return a Foswiki::Meta obj only | ||||
131 | |||||
132 | get a requested meta object - web or topic typically, might work for attachments too | ||||
133 | |||||
134 | optionally the $meta parameter can be used to add that to the cache - useful if you've already loaded and parsed the topic. | ||||
135 | |||||
136 | =cut | ||||
137 | |||||
138 | # spent 1.16s (241ms+918ms) within Foswiki::MetaCache::get which was called 26366 times, avg 44µs/call:
# 8845 times (58.0ms+99.0ms) by Foswiki::Search::formatResults at line 787 of /var/www/foswiki11/lib/Foswiki/Search.pm, avg 18µs/call
# 8760 times (87.1ms+803ms) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 230 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 102µs/call
# 8760 times (95.6ms+14.5ms) by Foswiki::Search::InfoCache::addTopic at line 99 of /var/www/foswiki11/lib/Foswiki/Search/InfoCache.pm, avg 13µs/call
# once (74µs+657µs) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 114 of /var/www/foswiki11/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm | ||||
139 | 26366 | 17.0ms | my ( $this, $web, $topic, $meta ) = @_; | ||
140 | 26366 | 12.7ms | 8760 | 7.56ms | ASSERT( $meta->isa('Foswiki::Meta') ) if ( defined($meta) and DEBUG ); # spent 7.56ms making 8760 calls to Assert::ASSERTS_OFF, avg 863ns/call |
141 | |||||
142 | 26366 | 3.92ms | if ( !defined($topic) ) { | ||
143 | |||||
144 | #there are some instances - like the result set sorting, where we need to quickly pass "$web.$topic" | ||||
145 | ( $web, $topic ) = Foswiki::Func::normalizeWebTopicName( '', $web ); | ||||
146 | } | ||||
147 | |||||
148 | #print STDERR "------------do i get a lookin ($web, $topic) as ".$this->{session}->{user}."ne ".$this->{meta_cache_session_user}."\n"; | ||||
149 | 26366 | 8.19ms | $this->{get_count}++; | ||
150 | |||||
151 | 26366 | 13.6ms | unless ( $this->{cache}->{$web} ) { | ||
152 | $this->{cache}->{$web} = {}; | ||||
153 | } | ||||
154 | |||||
155 | #if we've _returned_ to the real session user, after promotion, undef cached topic's loaded during promotion | ||||
156 | #see Item10097 WARNING: this is a pretty dangerous 'fix' as any developer that writes a replacement metacache for their store/search needs to make sure they too grok that the session user is promoted to admin several times per request :( | ||||
157 | 26366 | 35.2ms | if ( | ||
158 | |||||
159 | #($this->{non_session_user_entries}) and #BUGGER. turns out we start with the same local user=admin rubbish to get the WebPrefs | ||||
160 | ( defined( $this->{cache}->{$web}{$topic} ) ) | ||||
161 | and ( defined( $this->{cache}->{$web}{$topic}->{allowViewUser} ) ) | ||||
162 | ) | ||||
163 | { | ||||
164 | undef $this->{cache}->{$web}{$topic}; | ||||
165 | delete $this->{cache}->{$web}{$topic}; | ||||
166 | $this->{undef_count}++; | ||||
167 | |||||
168 | #print STDERR "---- discard $web . $topic\n"; | ||||
169 | |||||
170 | } | ||||
171 | 26366 | 11.6ms | unless ( $this->{cache}->{$web}{$topic} ) { | ||
172 | |||||
173 | #print STDERR "---- create new $web . $topic\n"; | ||||
174 | |||||
175 | 305 | 502µs | $this->{cache}->{$web}{$topic} = {}; | ||
176 | 305 | 119µs | if ( defined($meta) ) { | ||
177 | $this->{cache}->{$web}{$topic}->{tom} = $meta; | ||||
178 | } | ||||
179 | else { | ||||
180 | 305 | 1.45ms | 305 | 778ms | $this->{cache}->{$web}{$topic}->{tom} = # spent 778ms making 305 calls to Foswiki::Meta::load, avg 2.55ms/call |
181 | Foswiki::Meta->load( $this->{session}, $web, $topic ); | ||||
182 | } | ||||
183 | return | ||||
184 | 305 | 582µs | if ( !defined( $this->{cache}->{$web}{$topic}->{tom} ) | ||
185 | or $this->{cache}->{$web}{$topic}->{tom} eq '' ); | ||||
186 | |||||
187 | 305 | 103µs | $this->{new_count}++; | ||
188 | |||||
189 | #TODO: extract this to the Meta Class, or remove entirely | ||||
190 | # Extract sort fields | ||||
191 | 305 | 527µs | 305 | 4.46ms | my $ri = $this->{cache}->{$web}{$topic}->{tom}->getRevisionInfo(); # spent 4.46ms making 305 calls to Foswiki::Meta::getRevisionInfo, avg 15µs/call |
192 | |||||
193 | # Rename fields to match sorting criteria | ||||
194 | 305 | 375µs | $this->{cache}->{$web}{$topic}->{editby} = $ri->{author} || ''; | ||
195 | 305 | 317µs | $this->{cache}->{$web}{$topic}->{modified} = $ri->{date}; | ||
196 | 305 | 278µs | $this->{cache}->{$web}{$topic}->{revNum} = $ri->{version}; | ||
197 | |||||
198 | 305 | 919µs | 305 | 106ms | $this->{cache}->{$web}{$topic}->{allowView} = # spent 107ms making 305 calls to Foswiki::Meta::haveAccess, avg 351µs/call, recursion: max depth 1, sum of overlapping time 1.58ms |
199 | $this->{cache}->{$web}{$topic}->{tom}->haveAccess('VIEW'); | ||||
200 | 305 | 580µs | if ( $this->{session}->{user} ne $this->{meta_cache_session_user} ) { | ||
201 | 86 | 30µs | $this->{non_session_user_entries} = 1; | ||
202 | 86 | 118µs | $this->{cache}->{$web}{$topic}->{allowViewUser} = | ||
203 | $this->{session}->{user}; | ||||
204 | |||||
205 | #print STDERR "---- switched from ".$this->{meta_cache_session_user}." to ".$this->{session}->{user}." for $web . $topic\n"; | ||||
206 | } | ||||
207 | |||||
208 | } | ||||
209 | |||||
210 | 26366 | 24.9ms | 26366 | 20.8ms | ASSERT( $this->{cache}->{$web}{$topic}->{tom}->isa('Foswiki::Meta') ) # spent 20.8ms making 26366 calls to Assert::ASSERTS_OFF, avg 791ns/call |
211 | if DEBUG; | ||||
212 | |||||
213 | 26366 | 108ms | return $this->{cache}->{$web}{$topic}; | ||
214 | } | ||||
215 | |||||
216 | 1 | 2µs | 1; | ||
217 | __END__ |