chiark / gitweb /
journal: loop less in MATCH_AND_TERM conditionals
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 5 Jun 2013 04:56:03 +0000 (00:56 -0400)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 10 Jun 2013 14:10:06 +0000 (10:10 -0400)
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.

src/journal/sd-journal.c
src/shared/list.h

index 46511df6be0dfc145ed98cd264b263c64a48d66c..8b9a589cd36425d4e45f438c9e8e55035af9f10e 100644 (file)
@@ -593,42 +593,35 @@ static int next_for_match(
                 }
 
         } else if (m->type == MATCH_AND_TERM) {
-                Match *i;
-                bool continue_looking;
+                Match *i, *last_moved;
 
                 /* 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. */
 
                 if (!m->matches)
                         return 0;
 
-                np = 0;
-                do {
-                        continue_looking = false;
+                r = next_for_match(j, m->matches, f, after_offset, direction, NULL, &np);
+                if (r <= 0)
+                        return r;
 
-                        LIST_FOREACH(matches, i, m->matches) {
-                                uint64_t cp, limit;
+                assert(direction == DIRECTION_DOWN ? np >= after_offset : np <= after_offset);
+                last_moved = m->matches;
 
-                                if (np == 0)
-                                        limit = after_offset;
-                                else if (direction == DIRECTION_DOWN)
-                                        limit = MAX(np, after_offset);
-                                else
-                                        limit = MIN(np, after_offset);
+                LIST_LOOP_BUT_ONE(matches, i, m->matches, last_moved) {
+                        uint64_t cp;
 
-                                r = next_for_match(j, i, f, limit, direction, NULL, &cp);
-                                if (r <= 0)
-                                        return r;
+                        r = next_for_match(j, i, f, np, direction, NULL, &cp);
+                        if (r <= 0)
+                                return r;
 
-                                if ((direction == DIRECTION_DOWN ? cp >= after_offset : cp <= after_offset) &&
-                                    (np == 0 || (direction == DIRECTION_DOWN ? cp > np : cp < np))) {
-                                        np = cp;
-                                        continue_looking = true;
-                                }
+                        assert(direction == DIRECTION_DOWN ? cp >= np : cp <= np);
+                        if (direction == DIRECTION_DOWN ? cp > np : cp < np) {
+                                np = cp;
+                                last_moved = i;
                         }
-
-                } while (continue_looking);
+                }
         }
 
         if (np == 0)
index 47f275a019403c873d0d52341f7ab93fdb120d48..96d6237974726693512b71cbc12c12e9df7bcf4e 100644 (file)
 
 #define LIST_FOREACH_AFTER(name,i,p)                                    \
         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))