← 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/Search/InfoCache.pm
StatementsExecuted 336138 statements in 1.03s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
5028011334ms334msFoswiki::Search::InfoCache::::__ANON__[:448]Foswiki::Search::InfoCache::__ANON__[:448]
876011257ms618msFoswiki::Search::InfoCache::::addTopicFoswiki::Search::InfoCache::addTopic
8011178ms178msFoswiki::Search::InfoCache::::sortTopicsFoswiki::Search::InfoCache::sortTopics
401179.1ms214msFoswiki::Search::InfoCache::::addTopicsFoswiki::Search::InfoCache::addTopics
80223.21ms219msFoswiki::Search::InfoCache::::newFoswiki::Search::InfoCache::new
80112.31ms181msFoswiki::Search::InfoCache::::sortResultsFoswiki::Search::InfoCache::sortResults
4011905µs1.71msFoswiki::Search::InfoCache::::getOptionFilterFoswiki::Search::InfoCache::getOptionFilter
4011803µs803µsFoswiki::Search::InfoCache::::convertTopicPatternToRegexFoswiki::Search::InfoCache::convertTopicPatternToRegex
4011758µs2.79sFoswiki::Search::InfoCache::::getTopicListIteratorFoswiki::Search::InfoCache::getTopicListIterator
111663µs750µsFoswiki::Search::InfoCache::::BEGIN@33Foswiki::Search::InfoCache::BEGIN@33
11113µs25µsFoswiki::Search::InfoCache::::BEGIN@3Foswiki::Search::InfoCache::BEGIN@3
11110µs34µsFoswiki::Search::InfoCache::::BEGIN@30Foswiki::Search::InfoCache::BEGIN@30
1118µs12µsFoswiki::Search::InfoCache::::BEGIN@4Foswiki::Search::InfoCache::BEGIN@4
1114µs4µsFoswiki::Search::InfoCache::::BEGIN@9Foswiki::Search::InfoCache::BEGIN@9
1114µs4µsFoswiki::Search::InfoCache::::BEGIN@32Foswiki::Search::InfoCache::BEGIN@32
1113µs3µsFoswiki::Search::InfoCache::::BEGIN@31Foswiki::Search::InfoCache::BEGIN@31
1113µs3µsFoswiki::Search::InfoCache::::BEGIN@6Foswiki::Search::InfoCache::BEGIN@6
0000s0sFoswiki::Search::InfoCache::::__ANON__[:258]Foswiki::Search::InfoCache::__ANON__[:258]
0000s0sFoswiki::Search::InfoCache::::_compareFoswiki::Search::InfoCache::_compare
0000s0sFoswiki::Search::InfoCache::::filterByDateFoswiki::Search::InfoCache::filterByDate
0000s0sFoswiki::Search::InfoCache::::isImmutableFoswiki::Search::InfoCache::isImmutable
0000s0sFoswiki::Search::InfoCache::::numberOfTopicsFoswiki::Search::InfoCache::numberOfTopics
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::Search::InfoCache;
3226µs237µs
# spent 25µs (13+12) within Foswiki::Search::InfoCache::BEGIN@3 which was called: # once (13µs+12µs) by Foswiki::Search::BEGIN@19 at line 3
use strict;
# spent 25µs making 1 call to Foswiki::Search::InfoCache::BEGIN@3 # spent 12µs making 1 call to strict::import
4222µs216µs
# spent 12µs (8+4) within Foswiki::Search::InfoCache::BEGIN@4 which was called: # once (8µs+4µs) by Foswiki::Search::BEGIN@19 at line 4
use warnings;
# spent 12µs making 1 call to Foswiki::Search::InfoCache::BEGIN@4 # spent 4µs making 1 call to warnings::import
5
6259µs13µs
# spent 3µs within Foswiki::Search::InfoCache::BEGIN@6 which was called: # once (3µs+0s) by Foswiki::Search::BEGIN@19 at line 6
use Foswiki::ListIterator ();
# spent 3µs making 1 call to Foswiki::Search::InfoCache::BEGIN@6
7110µsour @ISA = ('Foswiki::ListIterator');
8
9
# spent 4µs within Foswiki::Search::InfoCache::BEGIN@9 which was called: # once (4µs+0s) by Foswiki::Search::BEGIN@19 at line 14
BEGIN {
1014µs if ( $Foswiki::cfg{UseLocale} ) {
11 require locale;
12 import locale();
13 }
14125µs14µs}
# spent 4µs making 1 call to Foswiki::Search::InfoCache::BEGIN@9
15
16=begin TML
17
18---+ package Foswiki::Search::InfoCache
19
20Support package; cache of topic info. When information about search hits is
21compiled for output, this cache is used to avoid recovering the same info
22about the same topic more than once.
23
24=cut
25
26# TODO: this is going to transform from an ugly duckling into the
27# ResultSet Iterator
28# Sven has the feeling that we should make result sets immutable
29
30224µs259µs
# spent 34µs (10+24) within Foswiki::Search::InfoCache::BEGIN@30 which was called: # once (10µs+24µs) by Foswiki::Search::BEGIN@19 at line 30
use Assert;
# spent 34µs making 1 call to Foswiki::Search::InfoCache::BEGIN@30 # spent 24µs making 1 call to Exporter::import
31226µs13µs
# spent 3µs within Foswiki::Search::InfoCache::BEGIN@31 which was called: # once (3µs+0s) by Foswiki::Search::BEGIN@19 at line 31
use Foswiki::Func ();
# spent 3µs making 1 call to Foswiki::Search::InfoCache::BEGIN@31
32223µs14µs
# spent 4µs within Foswiki::Search::InfoCache::BEGIN@32 which was called: # once (4µs+0s) by Foswiki::Search::BEGIN@19 at line 32
use Foswiki::Meta ();
# spent 4µs making 1 call to Foswiki::Search::InfoCache::BEGIN@32
3321.87ms1750µs
# spent 750µs (663+87) within Foswiki::Search::InfoCache::BEGIN@33 which was called: # once (663µs+87µs) by Foswiki::Search::BEGIN@19 at line 33
use Foswiki::Iterator::FilterIterator ();
# spent 750µs making 1 call to Foswiki::Search::InfoCache::BEGIN@33
34
35#use Monitor ();
36#Monitor::MonitorMethod('Foswiki::Search::InfoCache', 'getTopicListIterator');
37
38=begin TML
39
40---++ ClassMethod new($session, $defaultWeb, \@topicList)
41Initialise a new list of topics, allowing their data to be lazy loaded
42if and when needed.
43
44$defaultWeb is used to qualify topics that do not have a web
45specifier - should expect it to be the same as BASEWEB in most cases.
46
47Because this Iterator can be created and filled dynamically, once the Iterator hasNext() and next() methods are called, it is immutable.
48
49=cut
50
51#TODO: duplicates??, what about topicExists?
52#TODO: remove the iterator code from this __container__ and make a $this->getIterator() which can then be used.
53#TODO: replace the Iterator->reset() function with a lightweight Iterator->copyConstructor?
54#TODO: or..... make reset() make the object mutable again, so we can change the elements in the list, but re-use the meta cache??
55#CONSIDER: convert the internals to a hash[tomAddress] = {matches->[list of resultint text bits], othermeta...} - except this does not give us order :/
56
57
# spent 219ms (3.21+216) within Foswiki::Search::InfoCache::new which was called 80 times, avg 2.73ms/call: # 40 times (2.49ms+215ms) by Foswiki::Store::SearchAlgorithms::Forking::_webQuery at line 279 of /var/www/foswikidev/core/lib/Foswiki/Store/SearchAlgorithms/Forking.pm, avg 5.45ms/call # 40 times (728µs+177µs) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 70 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 23µs/call
sub new {
5880281µs my ( $class, $session, $defaultWeb, $topicList ) = @_;
59
60801.30ms801.26ms my $this = $class->SUPER::new( [] );
# spent 1.26ms making 80 calls to Foswiki::ListIterator::new, avg 16µs/call
6180180µs $this->{_session} = $session;
6280180µs $this->{_defaultWeb} = $defaultWeb;
6380218µs $this->{count} = 0;
6480462µs40214ms if ( defined($topicList) ) {
# spent 214ms making 40 calls to Foswiki::Search::InfoCache::addTopics, avg 5.36ms/call
65 $this->addTopics( $defaultWeb, @$topicList );
66 }
67
6880330µs return $this;
69}
70
71sub isImmutable {
72 my $this = shift;
73 return ( $this->{index} != 0 );
74}
75
76
# spent 214ms (79.1+135) within Foswiki::Search::InfoCache::addTopics which was called 40 times, avg 5.36ms/call: # 40 times (79.1ms+135ms) by Foswiki::Search::InfoCache::new at line 64, avg 5.36ms/call
sub addTopics {
77401.75ms my ( $this, $defaultWeb, @list ) = @_;
78 ASSERT( !$this->isImmutable() )
79 if DEBUG; #cannot modify list once its being used as an iterator.
804016µs ASSERT( defined($defaultWeb) ) if DEBUG;
81
8240161µs foreach my $t (@list) {
83876022.1ms8760135ms my ( $web, $topic ) =
# spent 135ms making 8760 calls to Foswiki::Func::normalizeWebTopicName, avg 15µs/call
84 Foswiki::Func::normalizeWebTopicName( $defaultWeb, $t );
85876012.3ms push( @{ $this->{list} }, "$web.$topic" );
8687608.55ms $this->{count}++;
87 }
88401.00ms undef $this->{sorted};
89}
90
91#TODO: what if it isa Meta obj
92#TODO: or an infoCache obj..
93
# spent 618ms (257+362) within Foswiki::Search::InfoCache::addTopic which was called 8760 times, avg 71µs/call: # 8760 times (257ms+362ms) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 215 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 71µs/call
sub addTopic {
9487604.35ms my ( $this, $meta ) = @_;
95 ASSERT( !$this->isImmutable() )
96 if DEBUG; #cannot modify list once its being used as an iterator.
97
9887609.46ms876013.2ms my $web = $meta->web();
# spent 13.2ms making 8760 calls to Foswiki::Meta::web, avg 2µs/call
9987609.66ms876012.4ms my $topic = $meta->topic();
# spent 12.4ms making 8760 calls to Foswiki::Meta::topic, avg 1µs/call
100
101876015.2ms876097.6ms my ( $w, $t ) = Foswiki::Func::normalizeWebTopicName( $web, $topic );
# spent 97.6ms making 8760 calls to Foswiki::Func::normalizeWebTopicName, avg 11µs/call
10287609.68ms my $webtopic = "$w.$t";
10387606.92ms push( @{ $this->{list} }, $webtopic );
10487602.37ms $this->{count}++;
105876032.4ms26280239ms if ( defined($meta) ) {
# spent 211ms making 8760 calls to Foswiki::MetaCache::addMeta, avg 24µs/call # spent 14.7ms making 8760 calls to Foswiki::search, avg 2µs/call # spent 13.1ms making 8760 calls to Foswiki::Search::metacache, avg 1µs/call
106 $this->{_session}->search->metacache->addMeta( $web, $topic, $meta );
107 }
108876043.4ms undef $this->{sorted};
109}
110
111sub numberOfTopics {
112 my $this = shift;
113
114 #can't use this, as it lies once its gone through the 'sortResults' hack
115 #and lies more because the filterByDate is evaluated later.
116 #return scalar(@{ $this->{list} });
117 # when fixed, the count update in filterByDate should be removed
118
119 return $this->{count};
120}
121
122=begin TML
123
124---++ ObjectMethod sortResults($params)
125
126the implementation of %SORT{"" limit="" order="" reverse="" date=""}%
127
128it should be possible for the search engine to pre-sort, making this a nop, or to
129delay evaluated, partially evaluated, or even delegated to the DB/SQL
130
131can call repeatedly, the list will only be re-sorted if new elements are added.
132
133=cut
134
135
# spent 181ms (2.31+178) within Foswiki::Search::InfoCache::sortResults which was called 80 times, avg 2.26ms/call: # 80 times (2.31ms+178ms) by Foswiki::Search::ResultSet::sortResults at line 273 of /var/www/foswikidev/core/lib/Foswiki/Search/ResultSet.pm, avg 2.26ms/call
sub sortResults {
1368090µs my ( $this, $params ) = @_;
137
138 #TODO: for now assume we do not change the sort order later
1398069µs return if ( defined( $this->{sorted} ) );
1408039µs $this->{sorted} = 1;
141
1428043µs my $session = $this->{_session};
143
1448084µs my $sortOrder = $params->{order} || '';
14580259µs80228µs my $revSort = Foswiki::isTrue( $params->{reverse} );
# spent 228µs making 80 calls to Foswiki::isTrue, avg 3µs/call
14680127µs my $limit = $params->{limit} || '';
147
148 #SMELL: duplicated code - removeme
149 # Limit search results
15080147µs if ( $limit =~ m/(^\d+$)/ ) {
151
152 # only digits, all else is the same as
153 # an empty string. "+10" won't work.
154 $limit = $1;
155 }
156 else {
157
158 # change 'all' to 0, then to big number
1598059µs $limit = 0;
160 }
1618048µs $limit = 32000 unless ($limit);
162
163 # TODO: this is really an ugly hack to get around the rather
164 # horrible limit 'performance' hack
1658074µs if ( defined( $params->{showpage} )
166 and $params->{showpage} > 1 )
167 {
168 $limit = ( 2 + $params->{showpage} ) * $params->{pagesize};
169 }
170
171 # sort the topic list by date, author or topic name, and cache the
172 # info extracted to do the sorting
17380237µs if ( $sortOrder eq 'modified' ) {
174
175 # For performance:
176 # * sort by approx time (to get a rough list)
177 # * shorten list to the limit + some slack
178 # * sort by rev date on shortened list to get the accurate list
179 # SMELL: Cairo had efficient two stage handling of modified sort.
180 # SMELL: In Dakar this seems to be pointless since latest rev
181 # time is taken from topic instead of dir list.
182 my $slack = 10;
183 if ( $limit + 2 * $slack < scalar( @{ $this->{list} } ) ) {
184
185 # sort by approx latest rev time
186 my @tmpList =
187 map { $_->[1] }
188 sort { $a->[0] <=> $b->[0] }
189 map {
190 my ( $web, $topic ) =
191 Foswiki::Func::normalizeWebTopicName( $this->{_defaultWeb},
192 $_ );
193 [ $session->getApproxRevTime( $web, $topic ), $_ ]
194 } @{ $this->{list} };
195 @tmpList = reverse(@tmpList) if ($revSort);
196
197 # then shorten list and build the hashes for date and author
198 my $idx = $limit + $slack;
199 @{ $this->{list} } = ();
200 foreach (@tmpList) {
201 push( @{ $this->{list} }, $_ );
202 $idx -= 1;
203 last if $idx <= 0;
204 }
205 }
206
207 }
208 elsif (
209 $sortOrder =~ m/^creat/ || # topic creation time
210 $sortOrder eq 'editby' || # author
211 $sortOrder =~ s/^formfield\(([^\)]+)\)$/$1/ # form field
212 )
213 {
214 }
215 else {
216
217 #default to topic sorting
2188036µs $sortOrder = 'topic';
219 }
22080609µs80178ms sortTopics( $this->{list}, $sortOrder, !$revSort );
# spent 178ms making 80 calls to Foswiki::Search::InfoCache::sortTopics, avg 2.23ms/call
221}
222
223=begin TML
224
225---++ filterByDate( $date )
226
227Filter the list by date interval; see System.TimeSpecifications.
228
229This function adds a filter evaluator to the infocache that is evaluated
230as you iterate through the collection
231
232<verbatim>
233$infoCache->filterByDate( $date );
234</verbatim>
235
236=cut
237
238sub filterByDate {
239 my ( $this, $date ) = @_;
240 ASSERT( !defined( $this->{filter} ) ) if DEBUG;
241
242 my $session = $Foswiki::Plugins::SESSION;
243
244 require Foswiki::Time;
245 my @ends = Foswiki::Time::parseInterval($date);
246
247 $this->{filter} = sub {
248 my $webtopic = shift;
249
250 # if date falls out of interval: exclude topic from result
251 my ( $web, $topic ) =
252 Foswiki::Func::normalizeWebTopicName( $this->{_defaultWeb},
253 $webtopic );
254 my $topicdate = $session->getApproxRevTime( $web, $topic );
255
256 return !( $topicdate < $ends[0] || $topicdate > $ends[1] );
257
258 };
259
260 return;
261}
262
263######OLD methods
264
265# Sort a topic list using cached info
266
# spent 178ms within Foswiki::Search::InfoCache::sortTopics which was called 80 times, avg 2.23ms/call: # 80 times (178ms+0s) by Foswiki::Search::InfoCache::sortResults at line 220, avg 2.23ms/call
sub sortTopics {
26780139µs my ( $listRef, $sortfield, $revSort ) = @_;
268 ASSERT($sortfield) if DEBUG;
269
270 # don't spend time doing stuff to an empty list (or a list of one!)
2718075µs return if ( scalar(@$listRef) < 2 );
272
2738056µs if ( $sortfield eq 'topic' ) {
274
275 # simple sort
276 # note no extraction of topic info here, as not needed
277 # for the sort. Instead it will be read lazily, later on.
278 # TODO: need to remove the web portion
279 # mmm, need to profile if there is even a point to this -
280 # as all topics still need to be parsed to find permissions
281804.96ms if ($revSort) {
282 @{$listRef} = map { $_->[1] }
28317520116ms sort { $a->[0] cmp $b->[0] }
2841752016.5ms map { $_ =~ m/^(.*?)([^.]+)$/; [ $2, $_ ] } #quickhack to remove web
2858040.1ms @{$listRef};
286 }
287 else {
288 @{$listRef} = map { $_->[1] }
289 sort { $b->[0] cmp $a->[0] }
290 map { $_ =~ m/^(.*?)([^.]+)$/; [ $2, $_ ] } #quickhack to remove web
291 @{$listRef};
292 }
293 ASSERT( $listRef->[0] ) if DEBUG;
29480554µs return;
295 }
296
297 my $metacache = $Foswiki::Plugins::SESSION->search->metacache;
298
299 # populate the cache for each topic
300 foreach my $webtopic ( @{$listRef} ) {
301
302 my $info = $metacache->get($webtopic);
303
304 if ( $sortfield =~ m/^creat/ ) {
305
306 # The act of getting the info will cache it
307 #$metacache->getRev1Info( $webtopic, $sortfield );
308 $info->{$sortfield} = $info->{tom}->getRev1Info($sortfield);
309 }
310 else {
311
312 # SMELL: SD duplicated from above - I'd rather do it only here,
313 # but i'm not sure if i can.
314 $sortfield =~ s/^formfield\((.*)\)$/$1/; # form field
315
316 if ( !defined( $info->{$sortfield} ) ) {
317
318#under normal circumstances this code is not called, because the metacach has already filled it.
319 if ( $sortfield eq 'modified' ) {
320 my $ri = $info->{tom}->getRevisionInfo();
321 $info->{$sortfield} = $ri->{date};
322 }
323 else {
324 $info->{$sortfield} =
325 Foswiki::Search::displayFormField( $info->{tom},
326 $sortfield );
327 }
328 }
329 }
330
331 # SMELL: CDot isn't clear why this is needed, but it is otherwise
332 # we end up with the users all being identified as "undef"
333 $info->{editby} =
334 $info->{tom}->session->{users}->getWikiName( $info->{editby} );
335 }
336 @{$listRef} = map { $_->[1] }
337 sort { _compare( $b, $a, $revSort ) }
338 map { [ $metacache->get($_)->{$sortfield}, $_ ] } @{$listRef};
339}
340
341# RE for a full-spec floating-point number
34212µsour $NUMBER = qr/^[-+]?[0-9]+(\.[0-9]*)?([Ee][-+]?[0-9]+)?$/s;
343
344sub _compare {
345 my ( $a, $b, $reverse ) = @_;
346 my ( $x, $y );
347 if ($reverse) {
348 $x = $a->[0];
349 $y = $b->[0];
350 }
351 else {
352 $x = $b->[0];
353 $y = $a->[0];
354 }
355
356 ASSERT( defined($x) ) if DEBUG;
357 ASSERT( defined($y) ) if DEBUG;
358
359 my $comparison;
360 if ( $x =~ m/$NUMBER/ && $y =~ m/$NUMBER/ ) {
361
362 # when sorting numbers do it largest first; this is just because
363 # this is what date comparisons need.
364 $comparison = $y <=> $x;
365 }
366 else {
367
368 my $datex = undef;
369 my $datey = undef;
370
371 # parseTime can error if you give it a date out of range so we skip
372 # testing if pure number
373 # We skip testing for dates the first character is not a digit
374 # as all formats we recognise as dates are
375 if ( $x =~ m/^\d/
376 && $x !~ /$NUMBER/
377 && $y =~ m/^\d/
378 && $y !~ /$NUMBER/ )
379 {
380 $datex = Foswiki::Time::parseTime($x);
381 $datey = Foswiki::Time::parseTime($y) if $datex;
382 }
383
384 if ( $datex && $datey ) {
385 $comparison = $datey <=> $datex;
386 }
387 else {
388 $comparison = $y cmp $x;
389 }
390 }
391
392 # tie breaker if keys are equal
393 # reverse order will not apply to the secondary search key
394 if ( $comparison == 0 ) {
395 $comparison = $b->[1] cmp $a->[1];
396 }
397
398 return $comparison;
399}
400
401=begin TML
402
403---++ StaticMethod getOptionFilter(\%options) -> $code
404
405Analyse the options given in \%options and return a function that
406filters based on those options. \%options may include:
407 * =includeTopics= - a comma-separated wildcard list of topic names
408 * =excludeTopics= - do
409 * =casesensitive= - boolean
410
411=cut
412
413
# spent 1.71ms (905µs+803µs) within Foswiki::Search::InfoCache::getOptionFilter which was called 40 times, avg 43µs/call: # 40 times (905µs+803µs) by Foswiki::Search::InfoCache::getTopicListIterator at line 482, avg 43µs/call
sub getOptionFilter {
4144035µs my ($options) = @_;
415
4164056µs my $casesensitive =
417 defined( $options->{casesensitive} ) ? $options->{casesensitive} : 1;
418
419 # E.g. "Web*, FooBar" ==> "^(Web.*|FooBar)$"
4204010µs my $includeTopics;
421405µs my $topicFilter;
422406µs my $excludeTopics;
4234024µs $excludeTopics = convertTopicPatternToRegex( $options->{excludeTopics} )
424 if ( $options->{excludeTopics} );
425
4264035µs if ( $options->{includeTopics} ) {
427
428 # E.g. "Bug*, *Patch" ==> "^(Bug.*|.*Patch)$"
42940100µs40803µs $includeTopics =
# spent 803µs making 40 calls to Foswiki::Search::InfoCache::convertTopicPatternToRegex, avg 20µs/call
430 convertTopicPatternToRegex( $options->{includeTopics} );
431
4324031µs if ($casesensitive) {
433 $topicFilter = qr/$includeTopics/;
434 }
435 else {
43640201µs $topicFilter = qr/$includeTopics/i;
437 }
438 }
439
440
# spent 334ms within Foswiki::Search::InfoCache::__ANON__[/var/www/foswikidev/core/lib/Foswiki/Search/InfoCache.pm:448] which was called 50280 times, avg 7µs/call: # 50280 times (334ms+0s) by Foswiki::Iterator::FilterIterator::hasNext at line 73 of /var/www/foswikidev/core/lib/Foswiki/Iterator/FilterIterator.pm, avg 7µs/call
return sub {
4415028014.6ms my $item = shift;
44250280276ms return 0 unless !$topicFilter || $item =~ m/$topicFilter/;
443460408.80ms if ( defined $excludeTopics ) {
444 return 0 if $item =~ m/$excludeTopics/;
445 return 0 if !$casesensitive && $item =~ m/$excludeTopics/i;
446 }
44746040364ms return 1;
448 }
44940338µs}
450
451#########################################
452# TODO: this is _now_ a default utility method that can be used by
453# search&query algo's to brute force file a list of topics to search.
454# if you can avoid it, you should - as it needs to do an opendir on the
455# web, and if you have alot of topics, life gets slow
456# get a list of topics to search in the web, filtered by the $topic
457# spec
458
# spent 2.79s (758µs+2.79) within Foswiki::Search::InfoCache::getTopicListIterator which was called 40 times, avg 69.9ms/call: # 40 times (758µs+2.79s) by Foswiki::Store::QueryAlgorithms::BruteForce::_webQuery at line 141 of /var/www/foswikidev/core/lib/Foswiki/Store/QueryAlgorithms/BruteForce.pm, avg 69.9ms/call
sub getTopicListIterator {
4594036µs my ( $webObject, $options ) = @_;
460
4614058µs my $casesensitive =
462 defined( $options->{casesensitive} ) ? $options->{casesensitive} : 1;
463
464 # See if there's a list of topics to avoid having to do a web list
4654010µs my $it;
4664031µs if ( $casesensitive
467 && $options->{includeTopics}
468 && $options->{includeTopics} =~ m/^([[:alnum:]]+(,\s*|\|))+$/ )
469 {
470
471 # topic list without wildcards
472 # convert pattern into a topic list
473 my @list = grep {
474 $Foswiki::Plugins::SESSION->topicExists( $webObject->web, $_ )
475 } split( /,\s*|\|/, $options->{includeTopics} );
476 $it = new Foswiki::ListIterator( \@list );
477 }
478 else {
47940115µs402.79s $it = $webObject->eachTopic();
# spent 2.79s making 40 calls to Foswiki::Meta::eachTopic, avg 69.8ms/call
480 }
481
48240350µs801.93ms return Foswiki::Iterator::FilterIterator->new( $it,
# spent 1.71ms making 40 calls to Foswiki::Search::InfoCache::getOptionFilter, avg 43µs/call # spent 226µs making 40 calls to Foswiki::Iterator::FilterIterator::new, avg 6µs/call
483 getOptionFilter($options) );
484}
485
486
# spent 803µs within Foswiki::Search::InfoCache::convertTopicPatternToRegex which was called 40 times, avg 20µs/call: # 40 times (803µs+0s) by Foswiki::Search::InfoCache::getOptionFilter at line 429, avg 20µs/call
sub convertTopicPatternToRegex {
4874055µs my ($topic) = @_;
4884015µs return '' unless ($topic);
489
490 # 'Web*, FooBar' ==> ( 'Web*', 'FooBar' ) ==> ( 'Web.*', "FooBar" )
4914071µs my @arr =
492120502µs map { $_ = quotemeta($_); s/(^|(?<!\\))\\\*/\.\*/g; $_ }
493 split( /(?:,\s*|\|)/, $topic );
494
4954015µs return '' unless (@arr);
496
49740245µs return '^(' . join( '|', @arr ) . ')$';
498}
499
50014µs1;
501__END__