Speedup OrderIntervalsSource some more (#13937)

Follow-up to #13871, getting another speedup from relatively trivial changes:

* avoid redundant `end()` call by directly storing the end value for sub-iterator that we don't use for anything else
    * also save most `get(...)` calls for this sub-iterator
* avoid redundant `start()` call by grabbing `start()` directly from `nextInterval`
* replace `getFirst()` with `get(0)`, it looks nice but has needless overhead in my testing (not sure why, but profiling clearly shows it to be slower, maybe just a result of having `get()`'s code hot in the cache with a higher likelihood or something esoteric like that)
* avoid using an iterator for loop for a random access list, this is probably the biggest win in this PR
This commit is contained in:
Armin Braun 2024-10-21 16:38:12 +02:00 committed by GitHub
parent 66f22fa0fd
commit d1e017f192
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 12 additions and 8 deletions

View File

@ -127,9 +127,9 @@ class OrderedIntervalsSource extends MinimizingConjunctionIntervalsSource {
final var subIterators = this.subIterators; final var subIterators = this.subIterators;
int currentIndex = i; int currentIndex = i;
while (true) { while (true) {
int prevEnd = subIterators.get(currentIndex - 1).end();
while (true) { while (true) {
var prev = subIterators.get(currentIndex - 1); if (prevEnd >= lastStart) {
if (prev.end() >= lastStart) {
i = currentIndex; i = currentIndex;
return start; return start;
} }
@ -137,19 +137,21 @@ class OrderedIntervalsSource extends MinimizingConjunctionIntervalsSource {
break; break;
} }
final IntervalIterator current = subIterators.get(currentIndex); final IntervalIterator current = subIterators.get(currentIndex);
if (minimizing && (current.start() > prev.end())) { if (minimizing && (current.start() > prevEnd)) {
break; break;
} }
int currentStart;
do { do {
if (current.end() >= lastStart if (current.end() >= lastStart
|| current.nextInterval() == IntervalIterator.NO_MORE_INTERVALS) { || (currentStart = current.nextInterval()) == IntervalIterator.NO_MORE_INTERVALS) {
i = currentIndex; i = currentIndex;
return start; return start;
} }
} while (current.start() <= prev.end()); } while (currentStart <= prevEnd);
currentIndex++; currentIndex++;
prevEnd = current.end();
} }
var first = subIterators.getFirst(); var first = subIterators.get(0);
final int start = first.start(); final int start = first.start();
this.start = start; this.start = start;
if (start == NO_MORE_INTERVALS) { if (start == NO_MORE_INTERVALS) {
@ -161,8 +163,10 @@ class OrderedIntervalsSource extends MinimizingConjunctionIntervalsSource {
final int end = last.end(); final int end = last.end();
this.end = end; this.end = end;
int slop = end - start + 1; int slop = end - start + 1;
for (IntervalIterator subIterator : subIterators) { // use indexed loop since this is always a random access capable list to avoid allocations
slop -= subIterator.width(); // in a hot nested loop
for (int j = 0, n = subIterators.size(); j < n; j++) {
slop -= subIterators.get(j).width();
} }
this.slop = slop; this.slop = slop;
onMatch.onMatch(); onMatch.onMatch();