mirror of
https://github.com/systemd/systemd.git
synced 2024-11-02 19:21:53 +03:00
journal: loop less in MATCH_AND_TERM conditionals
AND term usually don't have many subterms (4 seems to be the maximum sensible number, e.g. _BOOT_ID && _SYSTEMD_UNIT && _PID && MESSAGE_ID). Nevertheless, the cost of checking each subterm can be relatively high, especially when the nested terms are compound, and it makes sense to minimize the number of checks. Instead of looping to the end and then again over the whole list once again after at least one term changed the offset, start the loop at the term which caused the change. This way ½ terms in the AND match are not checked unnecessarily again.
This commit is contained in:
parent
3f3a438f58
commit
2bc8ca0ca2
@ -593,42 +593,35 @@ static int next_for_match(
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if (m->type == MATCH_AND_TERM) {
|
} else if (m->type == MATCH_AND_TERM) {
|
||||||
Match *i;
|
Match *i, *last_moved;
|
||||||
bool continue_looking;
|
|
||||||
|
|
||||||
/* Always jump to the next matching entry and repeat
|
/* Always jump to the next matching entry and repeat
|
||||||
* this until we fine and offset that matches for all
|
* this until we find an offset that matches for all
|
||||||
* matches. */
|
* matches. */
|
||||||
|
|
||||||
if (!m->matches)
|
if (!m->matches)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
np = 0;
|
r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np);
|
||||||
do {
|
if (r <= 0)
|
||||||
continue_looking = false;
|
return r;
|
||||||
|
|
||||||
LIST_FOREACH(matches, i, m->matches) {
|
assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset);
|
||||||
uint64_t cp, limit;
|
last_moved = m->matches;
|
||||||
|
|
||||||
if (np == 0)
|
LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) {
|
||||||
limit = after_offset;
|
uint64_t cp;
|
||||||
else if (direction == DIRECTION_DOWN)
|
|
||||||
limit = MAX(np, after_offset);
|
|
||||||
else
|
|
||||||
limit = MIN(np, after_offset);
|
|
||||||
|
|
||||||
r = next_for_match(j, i, f, limit, direction, NULL, &cp);
|
r = next_for_match(j, i, f, np, direction, NULL, &cp);
|
||||||
if (r <= 0)
|
if (r <= 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) &&
|
assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np);
|
||||||
(np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))) {
|
if (direction == DIRECTION_DOWN ? cp > np : cp < np) {
|
||||||
np = cp;
|
np = cp;
|
||||||
continue_looking = true;
|
last_moved = i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} while (continue_looking);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (np == 0)
|
if (np == 0)
|
||||||
|
@ -123,3 +123,10 @@
|
|||||||
|
|
||||||
#define LIST_FOREACH_AFTER(name,i,p) \
|
#define LIST_FOREACH_AFTER(name,i,p) \
|
||||||
for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
|
for ((i) = (p)->name##_next; (i); (i) = (i)->name##_next)
|
||||||
|
|
||||||
|
/* Loop starting from p->next until p->prev.
|
||||||
|
p can be adjusted meanwhile. */
|
||||||
|
#define LIST_LOOP_BUT_ONE(name,i,head,p) \
|
||||||
|
for ((i) = (p)->name##_next ? (p)->name##_next : (head); \
|
||||||
|
(i) != (p); \
|
||||||
|
(i) = (i)->name##_next ? (i)->name##_next : (head))
|
||||||
|
Loading…
Reference in New Issue
Block a user