chiark / gitweb /
journal: replace contexts hashmap with a plain array
authorMichal Schmidt <mschmidt@redhat.com>
Wed, 3 Dec 2014 17:25:44 +0000 (18:25 +0100)
committerMichal Schmidt <mschmidt@redhat.com>
Fri, 12 Dec 2014 23:47:23 +0000 (00:47 +0100)
try_context() is such a hot path that the hashmap lookup is expensive.

The number of contexts is small - it is the number of object types.
Using a hashmap is overkill. A plain array will do.

Before:
$ time ./journalctl --since=2014-06-01 --until=2014-07-01 > /dev/null

real    0m9.445s
user    0m9.228s
sys     0m0.213s

After:
$ time ./journalctl --since=2014-06-01 --until=2014-07-01 > /dev/null
real    0m5.438s
user    0m5.266s
sys     0m0.170s

src/journal/journal-file.c
src/journal/mmap-cache.c
src/journal/mmap-cache.h

index 82e50fc..7cdaf29 100644 (file)
@@ -376,6 +376,7 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
 
 static unsigned type_to_context(ObjectType type) {
         /* One context for each type, plus one catch-all for the rest */
+        assert_cc(_OBJECT_TYPE_MAX <= MMAP_CACHE_MAX_CONTEXTS);
         return type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX ? type : 0;
 }
 
index 949f978..4c940aa 100644 (file)
@@ -76,7 +76,7 @@ struct MMapCache {
 
 
         Hashmap *fds;
-        Hashmap *contexts;
+        Context *contexts[MMAP_CACHE_MAX_CONTEXTS];
 
         LIST_HEAD(Window, unused);
         Window *last_unused;
@@ -231,18 +231,13 @@ static void context_attach_window(Context *c, Window *w) {
 
 static Context *context_add(MMapCache *m, unsigned id) {
         Context *c;
-        int r;
 
         assert(m);
 
-        c = hashmap_get(m->contexts, UINT_TO_PTR(id + 1));
+        c = m->contexts[id];
         if (c)
                 return c;
 
-        r = hashmap_ensure_allocated(&m->contexts, NULL);
-        if (r < 0)
-                return NULL;
-
         c = new0(Context, 1);
         if (!c)
                 return NULL;
@@ -250,11 +245,8 @@ static Context *context_add(MMapCache *m, unsigned id) {
         c->cache = m;
         c->id = id;
 
-        r = hashmap_put(m->contexts, UINT_TO_PTR(id + 1), c);
-        if (r < 0) {
-                free(c);
-                return NULL;
-        }
+        assert(!m->contexts[id]);
+        m->contexts[id] = c;
 
         return c;
 }
@@ -264,8 +256,10 @@ static void context_free(Context *c) {
 
         context_detach_window(c);
 
-        if (c->cache)
-                assert_se(hashmap_remove(c->cache->contexts, UINT_TO_PTR(c->id + 1)));
+        if (c->cache) {
+                assert(c->cache->contexts[c->id] == c);
+                c->cache->contexts[c->id] = NULL;
+        }
 
         free(c);
 }
@@ -314,15 +308,14 @@ static FileDescriptor* fd_add(MMapCache *m, int fd) {
 }
 
 static void mmap_cache_free(MMapCache *m) {
-        Context *c;
         FileDescriptor *f;
+        int i;
 
         assert(m);
 
-        while ((c = hashmap_first(m->contexts)))
-                context_free(c);
-
-        hashmap_free(m->contexts);
+        for (i = 0; i < MMAP_CACHE_MAX_CONTEXTS; i++)
+                if (m->contexts[i])
+                        context_free(m->contexts[i]);
 
         while ((f = hashmap_first(m->fds)))
                 fd_free(f);
@@ -374,7 +367,7 @@ static int try_context(
         assert(size > 0);
         assert(ret);
 
-        c = hashmap_get(m->contexts, UINT_TO_PTR(context+1));
+        c = m->contexts[context];
         if (!c)
                 return 0;
 
@@ -557,6 +550,7 @@ int mmap_cache_get(
         assert(fd >= 0);
         assert(size > 0);
         assert(ret);
+        assert(context < MMAP_CACHE_MAX_CONTEXTS);
 
         /* Check whether the current context is the right one already */
         r = try_context(m, fd, prot, context, keep_always, offset, size, ret);
index 543a2bf..fe2c83d 100644 (file)
@@ -25,6 +25,8 @@
 #include <stdbool.h>
 #include <sys/stat.h>
 
+#define MMAP_CACHE_MAX_CONTEXTS 8
+
 typedef struct MMapCache MMapCache;
 
 MMapCache* mmap_cache_new(void);