Zbigniew Jędrzejewski-Szmek d66047
From a460644e808ed7671e28ef8231ee590317371fed Mon Sep 17 00:00:00 2001
Zbigniew Jędrzejewski-Szmek d66047
From: Lennart Poettering <lennart@poettering.net>
Zbigniew Jędrzejewski-Szmek d66047
Date: Tue, 26 Nov 2013 20:37:53 +0100
Zbigniew Jędrzejewski-Szmek d66047
Subject: [PATCH] journal: optimize bisection logic a bit by caching the last
Zbigniew Jędrzejewski-Szmek d66047
 position
Zbigniew Jędrzejewski-Szmek d66047
Zbigniew Jędrzejewski-Szmek d66047
This way we can do a quick restart limiting a bit how wildly we need to
Zbigniew Jędrzejewski-Szmek d66047
jump around during the bisection process.
Zbigniew Jędrzejewski-Szmek d66047
Zbigniew Jędrzejewski-Szmek d66047
(cherry picked from commit f268980d2cee694fa4118a71402a47c316af0425)
Zbigniew Jędrzejewski-Szmek d66047
---
Zbigniew Jędrzejewski-Szmek d66047
 src/journal/journal-file.c | 134 +++++++++++++++++++++++++++++++++------------
Zbigniew Jędrzejewski-Szmek d66047
 1 file changed, 99 insertions(+), 35 deletions(-)
Zbigniew Jędrzejewski-Szmek d66047
Zbigniew Jędrzejewski-Szmek d66047
diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c
Zbigniew Jędrzejewski-Szmek d66047
index d3bdaea..02f7554 100644
Zbigniew Jędrzejewski-Szmek d66047
--- a/src/journal/journal-file.c
Zbigniew Jędrzejewski-Szmek d66047
+++ b/src/journal/journal-file.c
Zbigniew Jędrzejewski-Szmek d66047
@@ -1366,6 +1366,7 @@ typedef struct ChainCacheItem {
Zbigniew Jędrzejewski-Szmek d66047
         uint64_t array; /* the cached array */
Zbigniew Jędrzejewski-Szmek d66047
         uint64_t begin; /* the first item in the cached array */
Zbigniew Jędrzejewski-Szmek d66047
         uint64_t total; /* the total number of items in all arrays before this one in the chain */
Zbigniew Jędrzejewski-Szmek d66047
+        uint64_t last_index; /* the last index we looked at, to optimize locality when bisecting */
Zbigniew Jędrzejewski-Szmek d66047
 } ChainCacheItem;
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
 static void chain_cache_put(
Zbigniew Jędrzejewski-Szmek d66047
@@ -1374,7 +1375,8 @@ static void chain_cache_put(
Zbigniew Jędrzejewski-Szmek d66047
                 uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
                 uint64_t array,
Zbigniew Jędrzejewski-Szmek d66047
                 uint64_t begin,
Zbigniew Jędrzejewski-Szmek d66047
-                uint64_t total) {
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t total,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t last_index) {
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
         if (!ci) {
Zbigniew Jędrzejewski-Szmek d66047
                 /* If the chain item to cache for this chain is the
Zbigniew Jędrzejewski-Szmek d66047
@@ -1402,12 +1404,14 @@ static void chain_cache_put(
Zbigniew Jędrzejewski-Szmek d66047
         ci->array = array;
Zbigniew Jędrzejewski-Szmek d66047
         ci->begin = begin;
Zbigniew Jędrzejewski-Szmek d66047
         ci->total = total;
Zbigniew Jędrzejewski-Szmek d66047
+        ci->last_index = last_index;
Zbigniew Jędrzejewski-Szmek d66047
 }
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
-static int generic_array_get(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
-                             uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
-                             uint64_t i,
Zbigniew Jędrzejewski-Szmek d66047
-                             Object **ret, uint64_t *offset) {
Zbigniew Jędrzejewski-Szmek d66047
+static int generic_array_get(
Zbigniew Jędrzejewski-Szmek d66047
+                JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t i,
Zbigniew Jędrzejewski-Szmek d66047
+                Object **ret, uint64_t *offset) {
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
         Object *o;
Zbigniew Jędrzejewski-Szmek d66047
         uint64_t p = 0, a, t = 0;
Zbigniew Jędrzejewski-Szmek d66047
@@ -1448,7 +1452,7 @@ static int generic_array_get(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
 found:
Zbigniew Jędrzejewski-Szmek d66047
         /* Let's cache this item for the next invocation */
Zbigniew Jędrzejewski-Szmek d66047
-        chain_cache_put(f->chain_cache, ci, first, a, o->entry_array.items[0], t);
Zbigniew Jędrzejewski-Szmek d66047
+        chain_cache_put(f->chain_cache, ci, first, a, o->entry_array.items[0], t, i);
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
         r = journal_file_move_to_object(f, OBJECT_ENTRY, p, &o);
Zbigniew Jędrzejewski-Szmek d66047
         if (r < 0)
Zbigniew Jędrzejewski-Szmek d66047
@@ -1463,11 +1467,12 @@ found:
Zbigniew Jędrzejewski-Szmek d66047
         return 1;
Zbigniew Jędrzejewski-Szmek d66047
 }
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
-static int generic_array_get_plus_one(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
-                                      uint64_t extra,
Zbigniew Jędrzejewski-Szmek d66047
-                                      uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
-                                      uint64_t i,
Zbigniew Jędrzejewski-Szmek d66047
-                                      Object **ret, uint64_t *offset) {
Zbigniew Jędrzejewski-Szmek d66047
+static int generic_array_get_plus_one(
Zbigniew Jędrzejewski-Szmek d66047
+                JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t extra,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t i,
Zbigniew Jędrzejewski-Szmek d66047
+                Object **ret, uint64_t *offset) {
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
         Object *o;
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
@@ -1498,17 +1503,18 @@ enum {
Zbigniew Jędrzejewski-Szmek d66047
         TEST_RIGHT
Zbigniew Jędrzejewski-Szmek d66047
 };
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
-static int generic_array_bisect(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
-                                uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
-                                uint64_t n,
Zbigniew Jędrzejewski-Szmek d66047
-                                uint64_t needle,
Zbigniew Jędrzejewski-Szmek d66047
-                                int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
Zbigniew Jędrzejewski-Szmek d66047
-                                direction_t direction,
Zbigniew Jędrzejewski-Szmek d66047
-                                Object **ret,
Zbigniew Jędrzejewski-Szmek d66047
-                                uint64_t *offset,
Zbigniew Jędrzejewski-Szmek d66047
-                                uint64_t *idx) {
Zbigniew Jędrzejewski-Szmek d66047
-
Zbigniew Jędrzejewski-Szmek d66047
-        uint64_t a, p, t = 0, i = 0, last_p = 0;
Zbigniew Jędrzejewski-Szmek d66047
+static int generic_array_bisect(
Zbigniew Jędrzejewski-Szmek d66047
+                JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t n,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t needle,
Zbigniew Jędrzejewski-Szmek d66047
+                int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
Zbigniew Jędrzejewski-Szmek d66047
+                direction_t direction,
Zbigniew Jędrzejewski-Szmek d66047
+                Object **ret,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t *offset,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t *idx) {
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+        uint64_t a, p, t = 0, i = 0, last_p = 0, last_index = (uint64_t) -1;
Zbigniew Jędrzejewski-Szmek d66047
         bool subtract_one = false;
Zbigniew Jędrzejewski-Szmek d66047
         Object *o, *array = NULL;
Zbigniew Jędrzejewski-Szmek d66047
         int r;
Zbigniew Jędrzejewski-Szmek d66047
@@ -1533,7 +1539,7 @@ static int generic_array_bisect(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
                         return r;
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
                 if (r == TEST_LEFT) {
Zbigniew Jędrzejewski-Szmek d66047
-                        /* OK, what we are looking for is right of th
Zbigniew Jędrzejewski-Szmek d66047
+                        /* OK, what we are looking for is right of the
Zbigniew Jędrzejewski-Szmek d66047
                          * begin of this EntryArray, so let's jump
Zbigniew Jędrzejewski-Szmek d66047
                          * straight to previously cached array in the
Zbigniew Jędrzejewski-Szmek d66047
                          * chain */
Zbigniew Jędrzejewski-Szmek d66047
@@ -1541,6 +1547,7 @@ static int generic_array_bisect(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
                         a = ci->array;
Zbigniew Jędrzejewski-Szmek d66047
                         n -= ci->total;
Zbigniew Jędrzejewski-Szmek d66047
                         t = ci->total;
Zbigniew Jędrzejewski-Szmek d66047
+                        last_index = ci->last_index;
Zbigniew Jędrzejewski-Szmek d66047
                 }
Zbigniew Jędrzejewski-Szmek d66047
         }
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
@@ -1571,6 +1578,60 @@ static int generic_array_bisect(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
                 if (r == TEST_RIGHT) {
Zbigniew Jędrzejewski-Szmek d66047
                         left = 0;
Zbigniew Jędrzejewski-Szmek d66047
                         right -= 1;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                        if (last_index != (uint64_t) -1) {
Zbigniew Jędrzejewski-Szmek d66047
+                                assert(last_index <= right);
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                /* If we cached the last index we
Zbigniew Jędrzejewski-Szmek d66047
+                                 * looked at, let's try to not to jump
Zbigniew Jędrzejewski-Szmek d66047
+                                 * too wildly around and see if we can
Zbigniew Jędrzejewski-Szmek d66047
+                                 * limit the range to look at early to
Zbigniew Jędrzejewski-Szmek d66047
+                                 * the immediate neighbors of the last
Zbigniew Jędrzejewski-Szmek d66047
+                                 * index we looked at. */
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                if (last_index > 0) {
Zbigniew Jędrzejewski-Szmek d66047
+                                        uint64_t x = last_index - 1;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        p = le64toh(array->entry_array.items[x]);
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (p <= 0)
Zbigniew Jędrzejewski-Szmek d66047
+                                                return -EBADMSG;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        r = test_object(f, p, needle);
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (r < 0)
Zbigniew Jędrzejewski-Szmek d66047
+                                                return r;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (r == TEST_FOUND)
Zbigniew Jędrzejewski-Szmek d66047
+                                                r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (r == TEST_RIGHT)
Zbigniew Jędrzejewski-Szmek d66047
+                                                right = x;
Zbigniew Jędrzejewski-Szmek d66047
+                                        else
Zbigniew Jędrzejewski-Szmek d66047
+                                                left = x + 1;
Zbigniew Jędrzejewski-Szmek d66047
+                                }
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                if (last_index < right) {
Zbigniew Jędrzejewski-Szmek d66047
+                                        uint64_t y = last_index + 1;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        p = le64toh(array->entry_array.items[y]);
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (p <= 0)
Zbigniew Jędrzejewski-Szmek d66047
+                                                return -EBADMSG;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        r = test_object(f, p, needle);
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (r < 0)
Zbigniew Jędrzejewski-Szmek d66047
+                                                return r;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (r == TEST_FOUND)
Zbigniew Jędrzejewski-Szmek d66047
+                                                r = direction == DIRECTION_DOWN ? TEST_RIGHT : TEST_LEFT;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                        if (r == TEST_RIGHT)
Zbigniew Jędrzejewski-Szmek d66047
+                                                right = y;
Zbigniew Jędrzejewski-Szmek d66047
+                                        else
Zbigniew Jędrzejewski-Szmek d66047
+                                                left = y + 1;
Zbigniew Jędrzejewski-Szmek d66047
+                                }
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+                                last_index = (uint64_t) -1;
Zbigniew Jędrzejewski-Szmek d66047
+                        }
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
                         for (;;) {
Zbigniew Jędrzejewski-Szmek d66047
                                 if (left == right) {
Zbigniew Jędrzejewski-Szmek d66047
                                         if (direction == DIRECTION_UP)
Zbigniew Jędrzejewski-Szmek d66047
@@ -1581,8 +1642,8 @@ static int generic_array_bisect(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
                                 }
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
                                 assert(left < right);
Zbigniew Jędrzejewski-Szmek d66047
-
Zbigniew Jędrzejewski-Szmek d66047
                                 i = (left + right) / 2;
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
                                 p = le64toh(array->entry_array.items[i]);
Zbigniew Jędrzejewski-Szmek d66047
                                 if (p <= 0)
Zbigniew Jędrzejewski-Szmek d66047
                                         return -EBADMSG;
Zbigniew Jędrzejewski-Szmek d66047
@@ -1615,6 +1676,7 @@ static int generic_array_bisect(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
                 n -= k;
Zbigniew Jędrzejewski-Szmek d66047
                 t += k;
Zbigniew Jędrzejewski-Szmek d66047
+                last_index = (uint64_t) -1;
Zbigniew Jędrzejewski-Szmek d66047
                 a = le64toh(array->entry_array.next_entry_array_offset);
Zbigniew Jędrzejewski-Szmek d66047
         }
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
@@ -1625,7 +1687,7 @@ found:
Zbigniew Jędrzejewski-Szmek d66047
                 return 0;
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
         /* Let's cache this item for the next invocation */
Zbigniew Jędrzejewski-Szmek d66047
-        chain_cache_put(f->chain_cache, ci, first, a, array->entry_array.items[0], t);
Zbigniew Jędrzejewski-Szmek d66047
+        chain_cache_put(f->chain_cache, ci, first, a, array->entry_array.items[0], t, i + (subtract_one ? -1 : 0));
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
         if (subtract_one && i == 0)
Zbigniew Jędrzejewski-Szmek d66047
                 p = last_p;
Zbigniew Jędrzejewski-Szmek d66047
@@ -1650,16 +1712,18 @@ found:
Zbigniew Jędrzejewski-Szmek d66047
         return 1;
Zbigniew Jędrzejewski-Szmek d66047
 }
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
-static int generic_array_bisect_plus_one(JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
-                                         uint64_t extra,
Zbigniew Jędrzejewski-Szmek d66047
-                                         uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
-                                         uint64_t n,
Zbigniew Jędrzejewski-Szmek d66047
-                                         uint64_t needle,
Zbigniew Jędrzejewski-Szmek d66047
-                                         int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
Zbigniew Jędrzejewski-Szmek d66047
-                                         direction_t direction,
Zbigniew Jędrzejewski-Szmek d66047
-                                         Object **ret,
Zbigniew Jędrzejewski-Szmek d66047
-                                         uint64_t *offset,
Zbigniew Jędrzejewski-Szmek d66047
-                                         uint64_t *idx) {
Zbigniew Jędrzejewski-Szmek d66047
+
Zbigniew Jędrzejewski-Szmek d66047
+static int generic_array_bisect_plus_one(
Zbigniew Jędrzejewski-Szmek d66047
+                JournalFile *f,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t extra,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t first,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t n,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t needle,
Zbigniew Jędrzejewski-Szmek d66047
+                int (*test_object)(JournalFile *f, uint64_t p, uint64_t needle),
Zbigniew Jędrzejewski-Szmek d66047
+                direction_t direction,
Zbigniew Jędrzejewski-Szmek d66047
+                Object **ret,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t *offset,
Zbigniew Jędrzejewski-Szmek d66047
+                uint64_t *idx) {
Zbigniew Jędrzejewski-Szmek d66047
 
Zbigniew Jędrzejewski-Szmek d66047
         int r;
Zbigniew Jędrzejewski-Szmek d66047
         bool step_back = false;