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

Filename/var/www/foswikidev/core/lib/Foswiki/MetaCache.pm
StatementsExecuted 1272669 statements in 1.68s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
61320441.39s78.8sFoswiki::MetaCache::::addMetaFoswiki::MetaCache::addMeta
2628022382ms1.03sFoswiki::MetaCache::::getFoswiki::MetaCache::get
9636341162ms162msFoswiki::MetaCache::::current_userFoswiki::MetaCache::current_user
87601158.0ms73.0msFoswiki::MetaCache::::getMetaFoswiki::MetaCache::getMeta
1116.03ms6.03msFoswiki::MetaCache::::finishFoswiki::MetaCache::finish
31128µs35µsFoswiki::MetaCache::::removeMetaFoswiki::MetaCache::removeMeta
11113µs26µsFoswiki::MetaCache::::BEGIN@3Foswiki::MetaCache::BEGIN@3
11111µs29µsFoswiki::MetaCache::::BEGIN@21Foswiki::MetaCache::BEGIN@21
1119µs33µsFoswiki::MetaCache::::BEGIN@20Foswiki::MetaCache::BEGIN@20
1119µs42µsFoswiki::MetaCache::::BEGIN@29Foswiki::MetaCache::BEGIN@29
1118µs8µsFoswiki::MetaCache::::newFoswiki::MetaCache::new
1118µs12µsFoswiki::MetaCache::::BEGIN@4Foswiki::MetaCache::BEGIN@4
1114µs4µsFoswiki::MetaCache::::BEGIN@22Foswiki::MetaCache::BEGIN@22
1114µs4µsFoswiki::MetaCache::::BEGIN@31Foswiki::MetaCache::BEGIN@31
1113µs3µsFoswiki::MetaCache::::BEGIN@24Foswiki::MetaCache::BEGIN@24
1113µs3µsFoswiki::MetaCache::::BEGIN@23Foswiki::MetaCache::BEGIN@23
0000s0sFoswiki::MetaCache::::DISABLED_insertFoswiki::MetaCache::DISABLED_insert
0000s0sFoswiki::MetaCache::::DISABLED_removeFoswiki::MetaCache::DISABLED_remove
0000s0sFoswiki::MetaCache::::DISABLED_updateFoswiki::MetaCache::DISABLED_update
0000s0sFoswiki::MetaCache::::hasCachedFoswiki::MetaCache::hasCached
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
2package Foswiki::MetaCache;
3226µs238µs
# spent 26µs (13+13) within Foswiki::MetaCache::BEGIN@3 which was called: # once (13µs+13µs) by Foswiki::Search::BEGIN@26 at line 3
use strict;
# spent 26µs making 1 call to Foswiki::MetaCache::BEGIN@3 # spent 13µs making 1 call to strict::import
4235µs216µs
# spent 12µs (8+4) within Foswiki::MetaCache::BEGIN@4 which was called: # once (8µs+4µs) by Foswiki::Search::BEGIN@26 at line 4
use warnings;
# spent 12µs making 1 call to Foswiki::MetaCache::BEGIN@4 # spent 4µs making 1 call to warnings::import
5
6=begin TML
7
8---+ package Foswiki::MetaCache
9
10A cache of Meta objects - initially used to speed up searching and sorting, but by foswiki 2.0 hopefully this
11will be used for all readonly accesses to the store.
12
13Replaces the mishmash of the Search InfoCache Support package; cache of topic info.
14When information about search hits is
15compiled for output, this cache is used to avoid recovering the same info
16about the same topic more than once.
17
18=cut
19
20227µs257µs
# spent 33µs (9+24) within Foswiki::MetaCache::BEGIN@20 which was called: # once (9µs+24µs) by Foswiki::Search::BEGIN@26 at line 20
use Assert;
# spent 33µs making 1 call to Foswiki::MetaCache::BEGIN@20 # spent 24µs making 1 call to Exporter::import
21225µs248µs
# spent 29µs (11+19) within Foswiki::MetaCache::BEGIN@21 which was called: # once (11µs+19µs) by Foswiki::Search::BEGIN@26 at line 21
use Scalar::Util qw(blessed);
# spent 29µs making 1 call to Foswiki::MetaCache::BEGIN@21 # spent 19µs making 1 call to Exporter::import
22218µs14µs
# spent 4µs within Foswiki::MetaCache::BEGIN@22 which was called: # once (4µs+0s) by Foswiki::Search::BEGIN@26 at line 22
use Foswiki::Func ();
# spent 4µs making 1 call to Foswiki::MetaCache::BEGIN@22
23217µs13µs
# spent 3µs within Foswiki::MetaCache::BEGIN@23 which was called: # once (3µs+0s) by Foswiki::Search::BEGIN@26 at line 23
use Foswiki::Meta ();
# spent 3µs making 1 call to Foswiki::MetaCache::BEGIN@23
24223µs13µs
# spent 3µs within Foswiki::MetaCache::BEGIN@24 which was called: # once (3µs+0s) by Foswiki::Search::BEGIN@26 at line 24
use Foswiki::Users::BaseUserMapping ();
# spent 3µs making 1 call to Foswiki::MetaCache::BEGIN@24
25
26#use Monitor ();
27#Monitor::MonitorMethod('Foswiki::MetaCache', 'getTopicListIterator');
28
29247µs274µs
# spent 42µs (9+33) within Foswiki::MetaCache::BEGIN@29 which was called: # once (9µs+33µs) by Foswiki::Search::BEGIN@26 at line 29
use constant TRACE => 0;
# spent 42µs making 1 call to Foswiki::MetaCache::BEGIN@29 # spent 33µs making 1 call to constant::import
30
31
# spent 4µs within Foswiki::MetaCache::BEGIN@31 which was called: # once (4µs+0s) by Foswiki::Search::BEGIN@26 at line 36
BEGIN {
3218µs if ( $Foswiki::cfg{UseLocale} ) {
33 require locale;
34 import locale();
35 }
3611.02ms14µs}
# spent 4µs making 1 call to Foswiki::MetaCache::BEGIN@31
37
38=begin TML
39
40---++ ClassMethod new($session)
41
42=cut
43
44
# spent 8µs within Foswiki::MetaCache::new which was called: # once (8µs+0s) by Foswiki::Search::metacache at line 94 of /var/www/foswikidev/core/lib/Foswiki/Search.pm
sub new {
451700ns my ( $class, $session ) = @_;
46
47 #my $this = $class->SUPER::new([]);
4816µs my $this = bless(
49 {
50 session => $session,
51 cache => {},
52 new_count => 0,
53 get_count => 0,
54 undef_count => 0,
55 meta_cache_session_user => $session->{user},
56 },
57 $class
58 );
59
6013µs return $this;
61}
62
63#need to delete from cache if the store saves / updates it :/
64#otherwise the Meta::load thing is busted.
65
66=begin TML
67
68---++ ObjectMethod finish()
69Break circular references.
70
71 Note to developers; please undef *all* fields in the object explicitly,
72 whether they are references or not. That way this method is "golden
73 documentation" of the live fields in the object.
74
75=cut
76
77
# spent 6.03ms within Foswiki::MetaCache::finish which was called: # once (6.03ms+0s) by Foswiki::Search::finish at line 78 of /var/www/foswikidev/core/lib/Foswiki/Search.pm
sub finish {
781400ns my $this = shift;
7911µs undef $this->{session};
80
81 #must clear cache every request until the cache is hooked up to Store's save
8215µs foreach my $cuid ( keys( %{ $this->{cache} } ) ) {
8312µs foreach my $web ( keys( %{ $this->{cache}->{$cuid} } ) ) {
841427µs foreach my $topic ( keys( %{ $this->{cache}->{$cuid}->{$web} } ) ) {
852195.44ms undef $this->{cache}->{$cuid}{$web}{$topic};
8621977µs $this->{undef_count}++;
87 }
88164µs undef $this->{cache}->{$cuid}{$web};
89 }
9012µs undef $this->{cache}->{$cuid};
91 }
921700ns undef $this->{cache};
93
94 if (TRACE) {
95 print STDERR
96"MetaCache: new: $this->{new_count} get: $this->{get_count} undef: $this->{undef_count} \n";
97 }
98
99111µs return;
100}
101
102=begin TML
103
104---++ ObjectMethod hasCached($webtopic) -> boolean
105
106returns true if the topic is already int he cache.
107
108=cut
109
110sub hasCached {
111 my ( $this, $web, $topic ) = @_;
112 ASSERT( defined($topic) ) if DEBUG;
113 return unless ( defined($topic) );
114
115 return ( $this->{session}->{user}
116 and
117 defined( $this->{cache}->{ $this->current_user() }{$web}{$topic} ) );
118}
119
120
# spent 35µs (28+7) within Foswiki::MetaCache::removeMeta which was called 3 times, avg 12µs/call: # 3 times (28µs+7µs) by Foswiki::Meta::unload at line 504 of /var/www/foswikidev/core/lib/Foswiki/Meta.pm, avg 12µs/call
sub removeMeta {
12134µs my ( $this, $web, $topic ) = @_;
12235µs37µs my $user = $this->current_user();
# spent 7µs making 3 calls to Foswiki::MetaCache::current_user, avg 2µs/call
123
12431µs if ( defined($topic) ) {
12536µs my $cached_userwebtopic = $this->{cache}->{$user}{$web}{$topic};
126
12731µs if ($cached_userwebtopic) {
128 $cached_userwebtopic->finish() if blessed($cached_userwebtopic);
129 delete $this->{cache}->{$user}{$web}{$topic};
130 }
131 }
132 elsif ( defined $web ) {
133 foreach my $topic ( keys( %{ $this->{cache}->{$user}{$web} } ) ) {
134 $this->removeMeta( $web, $topic );
135 }
136 delete $this->{cache}->{$user}{$web};
137 }
138
13938µs return;
140}
141
142#returns undef if the meta is not the latestRev, or if it failed to load
143#else returns the $meta
144
# spent 78.8s (1.39+77.4) within Foswiki::MetaCache::addMeta which was called 61320 times, avg 1.28ms/call: # 26280 times (464ms+134ms) by Foswiki::MetaCache::get at line 214, avg 23µs/call # 17520 times (543ms+51.5s) by Foswiki::Store::Interfaces::QueryAlgorithm::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm:194] at line 176 of /var/www/foswikidev/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm, avg 2.97ms/call # 8760 times (218ms+25.7s) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 203 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 2.95ms/call # 8760 times (163ms+47.6ms) by Foswiki::Search::InfoCache::addTopic at line 105 of /var/www/foswikidev/core/lib/Foswiki/Search/InfoCache.pm, avg 24µs/call
sub addMeta {
1456132032.5ms my ( $this, $web, $topic, $meta ) = @_;
146
1476132078.6ms2628077.0s if ( not defined($meta) ) {
# spent 77.0s making 26280 calls to Foswiki::Meta::load, avg 2.93ms/call
148 $meta = Foswiki::Meta->load( $this->{session}, $web, $topic );
149 }
15061320252ms183960220ms if ( ( defined($meta) and $meta ne '' )
# spent 138ms making 122640 calls to Foswiki::Meta::getLoadedRev, avg 1µs/call # spent 82.5ms making 61320 calls to Foswiki::Meta::latestIsLoaded, avg 1µs/call
151 and defined( $meta->latestIsLoaded )
152 and defined( $meta->getLoadedRev )
153 and ( $meta->getLoadedRev > 0 ) )
154 {
155 ASSERT( $meta->latestIsLoaded ) if DEBUG;
1566132010.0ms ASSERT( defined( $meta->getLoadedRev ) and ( $meta->getLoadedRev > 0 ) )
157 if DEBUG;
158 }
159 else {
160 return;
161 }
162
1636132078.6ms61320108ms my $user = $this->current_user();
# spent 108ms making 61320 calls to Foswiki::MetaCache::current_user, avg 2µs/call
164
1656132046.4ms unless ( $this->{cache}->{$user}{$web} ) {
166 $this->{cache}->{$user}{$web} = {};
167 }
1686132063.5ms unless ( $this->{cache}->{$user}{$web}{$topic} ) {
169 $this->{cache}->{$user}{$web}{$topic} = {};
170 }
1716132056.5ms unless ( defined( $this->{cache}->{$user}{$web}{$topic}->{tom} ) ) {
172219226µs $this->{cache}->{$user}{$web}{$topic}->{tom} = $meta;
17321979µs $this->{new_count}++;
174 }
17561320230ms return $meta;
176}
177
178
# spent 73.0ms (58.0+15.0) within Foswiki::MetaCache::getMeta which was called 8760 times, avg 8µs/call: # 8760 times (58.0ms+15.0ms) by Foswiki::Search::formatResults at line 775 of /var/www/foswikidev/core/lib/Foswiki/Search.pm, avg 8µs/call
sub getMeta {
17987605.10ms my ( $this, $web, $topic, $meta ) = @_;
18087608.43ms876015.0ms my $user = $this->current_user();
# spent 15.0ms making 8760 calls to Foswiki::MetaCache::current_user, avg 2µs/call
181
18287606.06ms return unless ( defined( $this->{cache}->{$user}{$web} ) );
18387605.57ms return unless ( defined( $this->{cache}->{$user}{$web}{$topic} ) );
184876030.3ms return $this->{cache}->{$user}{$web}{$topic}->{tom};
185}
186
187=begin TML
188
189---++ ObjectMethod get($web, $topic, $meta) -> a cache obj (sorry, needs to be refactored out to return a Foswiki::Meta obj only
190
191get a requested meta object - web or topic typically, might work for attachments too
192
193optionally the $meta parameter can be used to add that to the cache - useful if you've already loaded and parsed the topic.
194
195
196TODO: the non-meta SEARCH render specific bits need to be moved elsewhere
197and then, the MetaCache can only return Meta objects that actually exist
198
199=cut
200
201
# spent 1.03s (382ms+645ms) within Foswiki::MetaCache::get which was called 26280 times, avg 39µs/call: # 17520 times (256ms+425ms) by Foswiki::Store::Interfaces::QueryAlgorithm::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm:194] at line 186 of /var/www/foswikidev/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm, avg 39µs/call # 8760 times (126ms+220ms) by Foswiki::Search::formatResults at line 782 of /var/www/foswikidev/core/lib/Foswiki/Search.pm, avg 40µs/call
sub get {
2022628016.6ms my ( $this, $web, $topic, $meta ) = @_;
203262805.81ms ASSERT( $meta->isa('Foswiki::Meta') ) if ( defined($meta) and DEBUG );
204
205#sadly, Search.pm actually beleives that it can send out for info on Meta objects that do not exist
206#ASSERT( defined($meta->getLoadedRev) ) if ( defined($meta) and DEBUG );
207
208262802.95ms if ( !defined($topic) ) {
209
210#there are some instances - like the result set sorting, where we need to quickly pass "$web.$topic"
211 ( $web, $topic ) = Foswiki::Func::normalizeWebTopicName( '', $web );
212 }
213
2142628024.5ms26280598ms my $m = $this->addMeta( $web, $topic, $meta );
# spent 598ms making 26280 calls to Foswiki::MetaCache::addMeta, avg 23µs/call
215262807.33ms $meta = $m if ( defined($m) );
216 ASSERT( defined($meta) ) if DEBUG;
217
218262806.68ms $this->{get_count}++;
219
2202628028.0ms my $info = { tom => $meta };
2212628026.7ms2628039.2ms my $user = $this->current_user();
# spent 39.2ms making 26280 calls to Foswiki::MetaCache::current_user, avg 1µs/call
222
223 ASSERT( defined $user ) if DEBUG;
2242628052.9ms $info = $this->{cache}->{$user}{$web}{$topic}
225 if defined( $this->{cache}->{$user}{$web}{$topic} );
2262628013.6ms if ( not defined( $info->{editby} ) ) {
227
228 #TODO: extract this to the Meta Class, or remove entirely
229 # Extract sort fields
230219276µs2191.97ms my $ri = $info->{tom}->getRevisionInfo();
# spent 1.97ms making 219 calls to Foswiki::Meta::getRevisionInfo, avg 9µs/call
231
232 # Rename fields to match sorting criteria
233219165µs $info->{editby} = $ri->{author} || '';
234219135µs $info->{modified} = $ri->{date};
235219127µs $info->{revNum} = $ri->{version};
236
237#TODO: this is _not_ actually sufficient.. as there are other things that appear to be evaluated in turn
238#Ideally, the Store2::Meta object will _not_ contain any session info, and anything that is session / user oriented gets stored in another object that links to the 'database' object.
239#it'll probably be better to make the MetaCache know what
240#Item10097: make the cache multi-user safe by storing the haveAccess on a per user basis
241219205µs if ( not defined( $info->{ $this->{session}->{user} } ) ) {
242 $info->{ $this->{session}->{user} } = ();
243 }
244219615µs2195.56ms if ( not defined( $info->{ $this->{session}->{user} }{allowView} ) ) {
# spent 5.56ms making 219 calls to Foswiki::Meta::haveAccess, avg 25µs/call
245 $info->{ $this->{session}->{user} }{allowView} =
246 $info->{tom}->haveAccess('VIEW');
247 }
248
249 #use the cached permission
250219318µs $info->{allowView} = $info->{ $this->{session}->{user} }{allowView};
251 }
252
25326280101ms return $info;
254}
255
256
# spent 162ms within Foswiki::MetaCache::current_user which was called 96363 times, avg 2µs/call: # 61320 times (108ms+0s) by Foswiki::MetaCache::addMeta at line 163, avg 2µs/call # 26280 times (39.2ms+0s) by Foswiki::MetaCache::get at line 221, avg 1µs/call # 8760 times (15.0ms+0s) by Foswiki::MetaCache::getMeta at line 180, avg 2µs/call # 3 times (7µs+0s) by Foswiki::MetaCache::removeMeta at line 122, avg 2µs/call
sub current_user {
2579636318.1ms my $self = shift;
258
259 ASSERT( defined $self->{session} ) if DEBUG;
2609636347.2ms my $user = $self->{session}->{user};
2619636311.9ms if ( not defined $user ) {
262 $user = $Foswiki::Users::BaseUserMapping::UNKNOWN_USER_CUID;
263 }
264
26596363402ms return $user;
266}
267
268##########################################
269# this used to try to use the never-released listener API to flush the cache on changes.
270# Sven is not entirely sure it really worked, but the replacement for the listeners makes more
271# sense - it would move the MetaCache into the Store itself, allowing us to cache loaded topics
272# before ACL's are evaluated. however, I suspect this will require adding the readonly hash support
273# to Meta, which requires the Data::Foswiki work (post 2.0)
274
275sub DISABLED_insert {
276 my ( $self, %args ) = @_;
277
278 $self->removeMeta( $args{newmeta}->web, $args{newmeta}->topic );
279
280 return;
281}
282
283sub DISABLED_update {
284 my ( $self, %args ) = @_;
285
286 $self->removeMeta( $args{oldmeta}->web, $args{oldmeta}->topic )
287 if ( defined( $args{oldmeta} ) );
288 $self->removeMeta( $args{newmeta}->web, $args{newmeta}->topic );
289
290 return;
291}
292
293sub DISABLED_remove {
294 my ( $self, %args ) = @_;
295
296 ASSERT( $args{oldmeta} ) if DEBUG;
297
298 $self->removeMeta( $args{oldmeta}->web, $args{oldmeta}->topic )
299 if ( defined( $args{oldmeta} ) );
300
301 return;
302}
303
30412µs1;
305__END__