Code

vcs-svn: implement perfect hash for node-prop keys
authorDavid Barr <david.barr@cordelta.com>
Mon, 13 Dec 2010 08:13:24 +0000 (19:13 +1100)
committerJonathan Nieder <jrnieder@gmail.com>
Tue, 22 Mar 2011 23:09:02 +0000 (18:09 -0500)
Instead of interning property names and comparing their string_pool
keys, look them up in a table by string length, which should be about
as fast.

This is a small step towards removing dependence on string_pool.

Signed-off-by: David Barr <david.barr@cordelta.com>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
vcs-svn/svndump.c

index 15f822ea844ba64a12d19e02e12f244b2f99d4cb..322d1cd305868c5d4eef910b729aeaeeab899b01 100644 (file)
 #include "obj_pool.h"
 #include "string_pool.h"
 
+/*
+ * Compare start of string to literal of equal length;
+ * must be guarded by length test.
+ */
+#define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1)
+
 #define NODEACT_REPLACE 4
 #define NODEACT_DELETE 3
 #define NODEACT_ADD 2
@@ -58,8 +64,7 @@ static struct {
 } dump_ctx;
 
 static struct {
-       uint32_t svn_log, svn_author, svn_date, svn_executable, svn_special, uuid,
-               revision_number, node_path, node_kind, node_action,
+       uint32_t uuid, revision_number, node_path, node_kind, node_action,
                node_copyfrom_path, node_copyfrom_rev, text_content_length,
                prop_content_length, content_length, svn_fs_dump_format_version,
                /* version 3 format */
@@ -96,11 +101,6 @@ static void reset_dump_ctx(uint32_t url)
 
 static void init_keys(void)
 {
-       keys.svn_log = pool_intern("svn:log");
-       keys.svn_author = pool_intern("svn:author");
-       keys.svn_date = pool_intern("svn:date");
-       keys.svn_executable = pool_intern("svn:executable");
-       keys.svn_special = pool_intern("svn:special");
        keys.uuid = pool_intern("UUID");
        keys.revision_number = pool_intern("Revision-number");
        keys.node_path = pool_intern("Node-path");
@@ -117,22 +117,43 @@ static void init_keys(void)
        keys.prop_delta = pool_intern("Prop-delta");
 }
 
-static void handle_property(uint32_t key, const char *val, uint32_t len,
+static void handle_property(const struct strbuf *key_buf,
+                               const char *val, uint32_t len,
                                uint32_t *type_set)
 {
-       if (key == keys.svn_log) {
+       const char *key = key_buf->buf;
+       size_t keylen = key_buf->len;
+
+       switch (keylen + 1) {
+       case sizeof("svn:log"):
+               if (constcmp(key, "svn:log"))
+                       break;
                if (!val)
                        die("invalid dump: unsets svn:log");
                /* Value length excludes terminating nul. */
                rev_ctx.log = log_copy(len + 1, val);
-       } else if (key == keys.svn_author) {
+               break;
+       case sizeof("svn:author"):
+               if (constcmp(key, "svn:author"))
+                       break;
                rev_ctx.author = pool_intern(val);
-       } else if (key == keys.svn_date) {
+               break;
+       case sizeof("svn:date"):
+               if (constcmp(key, "svn:date"))
+                       break;
                if (!val)
                        die("invalid dump: unsets svn:date");
                if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
                        warning("invalid timestamp: %s", val);
-       } else if (key == keys.svn_executable || key == keys.svn_special) {
+               break;
+       case sizeof("svn:executable"):
+       case sizeof("svn:special"):
+               if (keylen == strlen("svn:executable") &&
+                   constcmp(key, "svn:executable"))
+                       break;
+               if (keylen == strlen("svn:special") &&
+                   constcmp(key, "svn:special"))
+                       break;
                if (*type_set) {
                        if (!val)
                                return;
@@ -143,7 +164,7 @@ static void handle_property(uint32_t key, const char *val, uint32_t len,
                        return;
                }
                *type_set = 1;
-               node_ctx.type = key == keys.svn_executable ?
+               node_ctx.type = keylen == strlen("svn:executable") ?
                                REPO_MODE_EXE :
                                REPO_MODE_LNK;
        }
@@ -158,7 +179,7 @@ static void die_short_read(void)
 
 static void read_props(void)
 {
-       uint32_t key = ~0;
+       static struct strbuf key = STRBUF_INIT;
        const char *t;
        /*
         * NEEDSWORK: to support simple mode changes like
@@ -195,16 +216,19 @@ static void read_props(void)
 
                switch (type) {
                case 'K':
-                       key = pool_intern(val);
-                       continue;
                case 'D':
-                       key = pool_intern(val);
+                       strbuf_reset(&key);
+                       if (val)
+                               strbuf_add(&key, val, len);
+                       if (type == 'K')
+                               continue;
+                       assert(type == 'D');
                        val = NULL;
                        len = 0;
                        /* fall through */
                case 'V':
-                       handle_property(key, val, len, &type_set);
-                       key = ~0;
+                       handle_property(&key, val, len, &type_set);
+                       strbuf_reset(&key);
                        continue;
                default:
                        die("invalid property line: %s\n", t);