Filename | /usr/local/src/github.com/foswiki/core/lib/Foswiki/Search/ResultSet.pm |
Statements | Executed 408 statements in 3.09ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
45 | 2 | 2 | 1.02ms | 2.14ms | hasNext | Foswiki::Search::ResultSet::
22 | 1 | 1 | 358µs | 471µs | next | Foswiki::Search::ResultSet::
1 | 1 | 1 | 47µs | 47µs | new | Foswiki::Search::ResultSet::
1 | 1 | 1 | 28µs | 38µs | BEGIN@17 | Foswiki::Search::ResultSet::
1 | 1 | 1 | 28µs | 34µs | sortResults | Foswiki::Search::ResultSet::
1 | 1 | 1 | 19µs | 42µs | BEGIN@18 | Foswiki::Search::ResultSet::
1 | 1 | 1 | 18µs | 62µs | BEGIN@24 | Foswiki::Search::ResultSet::
1 | 1 | 1 | 17µs | 17µs | BEGIN@23 | Foswiki::Search::ResultSet::
1 | 1 | 1 | 10µs | 10µs | BEGIN@20 | Foswiki::Search::ResultSet::
0 | 0 | 0 | 0s | 0s | filterByDate | Foswiki::Search::ResultSet::
0 | 0 | 0 | 0s | 0s | nextWeb | Foswiki::Search::ResultSet::
0 | 0 | 0 | 0s | 0s | numberOfTopics | Foswiki::Search::ResultSet::
0 | 0 | 0 | 0s | 0s | skip | Foswiki::Search::ResultSet::
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 | ---+ package Foswiki::Search::ResultSet | ||||
6 | |||||
7 | This class implements the ResultSet API - its basically a Sorted Aggregate Iterator for foswiki 1.1 | ||||
8 | * NOTE: does not implement the unique function - by its nature, the data is unique, and it would be a non-trivial drain on memory in this context | ||||
9 | |||||
10 | (due to the partially completed InfoCache removeal) | ||||
11 | |||||
12 | in future it will probably become more clever. | ||||
13 | |||||
14 | =cut | ||||
15 | |||||
16 | package Foswiki::Search::ResultSet; | ||||
17 | 2 | 48µs | 2 | 48µs | # spent 38µs (28+10) within Foswiki::Search::ResultSet::BEGIN@17 which was called:
# once (28µs+10µs) by Foswiki::Search::BEGIN@20 at line 17 # spent 38µs making 1 call to Foswiki::Search::ResultSet::BEGIN@17
# spent 10µs making 1 call to strict::import |
18 | 2 | 46µs | 2 | 65µs | # spent 42µs (19+23) within Foswiki::Search::ResultSet::BEGIN@18 which was called:
# once (19µs+23µs) by Foswiki::Search::BEGIN@20 at line 18 # spent 42µs making 1 call to Foswiki::Search::ResultSet::BEGIN@18
# spent 23µs making 1 call to warnings::import |
19 | |||||
20 | 2 | 71µs | 1 | 10µs | # spent 10µs within Foswiki::Search::ResultSet::BEGIN@20 which was called:
# once (10µs+0s) by Foswiki::Search::BEGIN@20 at line 20 # spent 10µs making 1 call to Foswiki::Search::ResultSet::BEGIN@20 |
21 | 1 | 10µs | our @ISA = ('Foswiki::Iterator'); | ||
22 | |||||
23 | 2 | 50µs | 1 | 17µs | # spent 17µs within Foswiki::Search::ResultSet::BEGIN@23 which was called:
# once (17µs+0s) by Foswiki::Search::BEGIN@20 at line 23 # spent 17µs making 1 call to Foswiki::Search::ResultSet::BEGIN@23 |
24 | 2 | 1.41ms | 2 | 106µs | # spent 62µs (18+44) within Foswiki::Search::ResultSet::BEGIN@24 which was called:
# once (18µs+44µs) by Foswiki::Search::BEGIN@20 at line 24 # spent 62µs making 1 call to Foswiki::Search::ResultSet::BEGIN@24
# spent 44µs making 1 call to Assert::import |
25 | |||||
26 | =begin TML | ||||
27 | |||||
28 | ---++ new(\@list) | ||||
29 | |||||
30 | Create a new iterator over the given list of iterators. The list is | ||||
31 | not damaged in any way. | ||||
32 | |||||
33 | =cut | ||||
34 | |||||
35 | # spent 47µs within Foswiki::Search::ResultSet::new which was called:
# once (47µs+0s) by Foswiki::Store::Interfaces::QueryAlgorithm::query at line 122 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm | ||||
36 | 3 | 49µs | my ( $class, $list, $partition, $sortby, $revSort ) = @_; | ||
37 | |||||
38 | my $this = bless( | ||||
39 | { | ||||
40 | Itr_list => $list, | ||||
41 | Itr_index => 0, | ||||
42 | next => undef, | ||||
43 | Itr_next => [], | ||||
44 | partition => $partition || 'web', | ||||
45 | sortby => $sortby || 'topic', | ||||
46 | revsort => $revSort || 0, | ||||
47 | }, | ||||
48 | $class | ||||
49 | ); | ||||
50 | |||||
51 | return $this; | ||||
52 | } | ||||
53 | |||||
54 | sub numberOfTopics { | ||||
55 | my $this = shift; | ||||
56 | |||||
57 | return $this->{count} if ( defined( $this->{count} ) ); | ||||
58 | |||||
59 | my $count = 0; | ||||
60 | foreach my $infocache ( @{ $this->{Itr_list} } ) { | ||||
61 | $count += $infocache->numberOfTopics(); | ||||
62 | } | ||||
63 | $this->{count} = $count; | ||||
64 | |||||
65 | return $count; | ||||
66 | } | ||||
67 | |||||
68 | =begin TML | ||||
69 | |||||
70 | ---++ hasNext() -> $boolean | ||||
71 | |||||
72 | Returns false when the iterator is exhausted. | ||||
73 | |||||
74 | =cut | ||||
75 | |||||
76 | # spent 2.14ms (1.02+1.11) within Foswiki::Search::ResultSet::hasNext which was called 45 times, avg 47µs/call:
# 23 times (911µs+1.11ms) by Foswiki::Iterator::FilterIterator::hasNext at line 64 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Iterator/FilterIterator.pm, avg 88µs/call
# 22 times (113µs+0s) by Foswiki::Search::ResultSet::next at line 228, avg 5µs/call | ||||
77 | 135 | 428µs | my ($this) = @_; | ||
78 | return 1 if $this->{next}; | ||||
79 | |||||
80 | #this is the 'normal' legacy way to iterate over the list of results (one web at a time) | ||||
81 | 68 | 132µs | if ( | ||
82 | ( $this->{partition} eq 'web' ) | ||||
83 | or ( | ||||
84 | scalar( @{ $this->{Itr_list} } ) <= 0 | ||||
85 | ) #no reason to got through the more complex case if there's only one itr | ||||
86 | ) | ||||
87 | { | ||||
88 | my $n; | ||||
89 | 47 | 297µs | do { | ||
90 | 2 | 9µs | unless ( $this->{list} ) { | ||
91 | 4 | 15µs | if ( $this->{Itr_index} < scalar( @{ $this->{Itr_list} } ) ) { | ||
92 | $this->{list} = $this->{Itr_list}->[ $this->{Itr_index}++ ]; | ||||
93 | } | ||||
94 | else { | ||||
95 | return 0; #no more iterators in list | ||||
96 | } | ||||
97 | } | ||||
98 | 23 | 145µs | 23 | 586µs | if ( $this->{list}->hasNext() ) { # spent 586µs making 23 calls to Foswiki::ListIterator::hasNext, avg 25µs/call |
99 | 22 | 525µs | $n = $this->{list}->next(); # spent 525µs making 22 calls to Foswiki::ListIterator::next, avg 24µs/call | ||
100 | } | ||||
101 | else { | ||||
102 | $this->{list} = undef; #goto next iterator | ||||
103 | } | ||||
104 | } while ( !$this->{list} ); | ||||
105 | $this->{next} = $n; | ||||
106 | } | ||||
107 | else { | ||||
108 | |||||
109 | #yes, this is innefficient, for now I'm looking only to get a functioning result. | ||||
110 | my $next = -1; | ||||
111 | for ( my $idx = 0 ; $idx < scalar( @{ $this->{Itr_list} } ) ; $idx++ ) { | ||||
112 | |||||
113 | #load the next element from each of the iterators | ||||
114 | if ( !defined( $this->{Itr_next}[$idx] ) | ||||
115 | and $this->{Itr_list}[$idx]->hasNext() ) | ||||
116 | { | ||||
117 | $this->{Itr_next}[$idx] = $this->{Itr_list}[$idx]->next(); | ||||
118 | } | ||||
119 | if ( defined( $this->{Itr_next}[$idx] ) ) { | ||||
120 | |||||
121 | #find the first one of them (works because each iterator is already sorted.. | ||||
122 | if ( $next == -1 ) { | ||||
123 | $next = $idx; | ||||
124 | next; | ||||
125 | } | ||||
126 | |||||
127 | #print STDERR "------ trying ($idx) ".$this->{Itr_next}[$idx]."\n"; | ||||
128 | #compare $next's elem with $idx's and rotate if needed | ||||
129 | my @two = ( $this->{Itr_next}[$next], $this->{Itr_next}[$idx] ); | ||||
130 | Foswiki::Search::InfoCache::sortTopics( \@two, $this->{sortby}, | ||||
131 | !$this->{revsort} ); | ||||
132 | if ( $two[0] ne $this->{Itr_next}[$next] ) { | ||||
133 | $next = $idx; | ||||
134 | } | ||||
135 | } | ||||
136 | } | ||||
137 | |||||
138 | #print STDERR "---getting result from $next\n"; | ||||
139 | if ( $next == -1 ) { | ||||
140 | return 0; | ||||
141 | } | ||||
142 | else { | ||||
143 | $this->{next} = $this->{Itr_next}[$next]; | ||||
144 | $this->{Itr_next}[$next] = undef; | ||||
145 | } | ||||
146 | |||||
147 | } | ||||
148 | return 1; | ||||
149 | } | ||||
150 | |||||
151 | =begin TML | ||||
152 | |||||
153 | ---++ skip(count) -> $countremaining | ||||
154 | |||||
155 | skip X elements (returns 0 if successful, or number of elements remaining to skip if there are not enough elements to skip) | ||||
156 | skip must set up next as though hasNext was called. | ||||
157 | |||||
158 | =cut | ||||
159 | |||||
160 | sub skip { | ||||
161 | my $this = shift; | ||||
162 | my $count = shift; | ||||
163 | |||||
164 | return 0 if ( $count <= 0 ); | ||||
165 | print STDERR | ||||
166 | "--------------------------------------------ResultSet::skip($count)\n" | ||||
167 | if Foswiki::Iterator::MONITOR; | ||||
168 | |||||
169 | #ask CAN skip() for faster path | ||||
170 | if ( | ||||
171 | ( | ||||
172 | ( $this->{partition} eq 'web' ) | ||||
173 | or ( scalar( @{ $this->{Itr_list} } ) == 0 ) | ||||
174 | ) | ||||
175 | and #no reason to got through the more complex case if there's only one itr | ||||
176 | ( $this->{Itr_list}->[0]->can('skip') | ||||
177 | ) #nasty assumption that all the itr's are a similar type (that happens to be true) | ||||
178 | ) | ||||
179 | { | ||||
180 | if ( not defined( $this->{list} ) ) { | ||||
181 | $this->{list} = $this->{Itr_list}->[ $this->{Itr_index}++ ]; | ||||
182 | } | ||||
183 | while ( $count > 0 ) { | ||||
184 | return $count if ( not defined( $this->{list} ) ); | ||||
185 | $count = $this->{list}->skip($count); | ||||
186 | $this->{next} = $this->{list}->{next}; | ||||
187 | if ( $count > 0 ) { | ||||
188 | $this->{list} = $this->{Itr_list}->[ $this->{Itr_index}++ ]; | ||||
189 | $this->{next} = undef; | ||||
190 | } | ||||
191 | } | ||||
192 | } | ||||
193 | else { | ||||
194 | |||||
195 | #brute force - | ||||
196 | while ( | ||||
197 | ( $count > 0 | ||||
198 | ) #must come first - don't want to advance the inner itr if count ==0 | ||||
199 | and $this->hasNext() | ||||
200 | ) | ||||
201 | { | ||||
202 | $count--; | ||||
203 | $this->next(); #drain next, so hasNext goes to next element | ||||
204 | } | ||||
205 | } | ||||
206 | |||||
207 | if ( $count >= 0 ) { | ||||
208 | |||||
209 | #finished. | ||||
210 | $this->{next} = undef; | ||||
211 | } | ||||
212 | print STDERR | ||||
213 | "--------------------------------------------ResultSet::skip() => $count\n" | ||||
214 | if Foswiki::Iterator::MONITOR; | ||||
215 | return $count; | ||||
216 | } | ||||
217 | |||||
218 | =begin TML | ||||
219 | |||||
220 | ---++ next() -> $data | ||||
221 | |||||
222 | Return the next entry in the list. | ||||
223 | |||||
224 | =cut | ||||
225 | |||||
226 | # spent 471µs (358+113) within Foswiki::Search::ResultSet::next which was called 22 times, avg 21µs/call:
# 22 times (358µs+113µs) by Foswiki::Iterator::FilterIterator::hasNext at line 65 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Iterator/FilterIterator.pm, avg 21µs/call | ||||
227 | 110 | 354µs | my $this = shift; | ||
228 | 22 | 113µs | $this->hasNext(); # spent 113µs making 22 calls to Foswiki::Search::ResultSet::hasNext, avg 5µs/call | ||
229 | my $n = $this->{next}; | ||||
230 | $this->{next} = undef; | ||||
231 | |||||
232 | return $n; | ||||
233 | } | ||||
234 | |||||
235 | =begin TML | ||||
236 | |||||
237 | ---++ nextWeb() -> $data | ||||
238 | |||||
239 | switch tot he next Web (only works on partition==web, and if we've already started iterating. | ||||
240 | =cut | ||||
241 | |||||
242 | sub nextWeb { | ||||
243 | my $this = shift; | ||||
244 | |||||
245 | ASSERT( $this->{partition} eq 'web' ) if DEBUG; | ||||
246 | ASSERT( $this->{list} ) if DEBUG; | ||||
247 | |||||
248 | $this->{list} = undef; | ||||
249 | $this->hasNext(); | ||||
250 | } | ||||
251 | |||||
252 | =begin TML | ||||
253 | ---++ sortResults | ||||
254 | |||||
255 | the implementation of %SORT{"" limit="" order="" reverse="" date=""}% | ||||
256 | |||||
257 | it should be possible for the search engine to pre-sort, making this a nop, or to | ||||
258 | delay evaluated, partially evaluated, or even delegated to the DB/SQL | ||||
259 | |||||
260 | =cut | ||||
261 | |||||
262 | # spent 34µs (28+6) within Foswiki::Search::ResultSet::sortResults which was called:
# once (28µs+6µs) by Foswiki::Store::Interfaces::QueryAlgorithm::query at line 130 of /usr/local/src/github.com/foswiki/core/lib/Foswiki/Store/Interfaces/QueryAlgorithm.pm | ||||
263 | 2 | 19µs | my ( $this, $params ) = @_; | ||
264 | |||||
265 | 1 | 2µs | foreach my $infocache ( @{ $this->{Itr_list} } ) { | ||
266 | 1 | 7µs | 1 | 7µs | $infocache->sortResults($params); # spent 7µs making 1 call to Foswiki::Search::InfoCache::sortResults |
267 | } | ||||
268 | } | ||||
269 | |||||
270 | sub filterByDate { | ||||
271 | my ( $this, $date ) = @_; | ||||
272 | |||||
273 | foreach my $infocache ( @{ $this->{Itr_list} } ) { | ||||
274 | $infocache->filterByDate($date); | ||||
275 | } | ||||
276 | } | ||||
277 | |||||
278 | 1 | 6µs | 1; | ||
279 | __END__ |