vcs-svn: implement perfect hash for node-prop keys
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>
David Barr committed
Dec 13, 2010 at 19:13 UTC
044ad2906a5e4b805bc8c8d121466d8ff94ecbfb
1 file changed
+43
-19
vcs-svn/svndump.c
+43
-19
@@ -14,6 +14,12 @@
14
#include "obj_pool.h"
15
#include "string_pool.h"
16
17
+/*
18
+ * Compare start of string to literal of equal length;
19
+ * must be guarded by length test.
20
+ */
21
+#define constcmp(s, ref) memcmp(s, ref, sizeof(ref) - 1)
22
+
23
#define NODEACT_REPLACE 4
24
#define NODEACT_DELETE 3
25
#define NODEACT_ADD 2
@@ -58,8 +64,7 @@ static struct {
64
} dump_ctx;
65
66
static struct {
61
- uint32_t svn_log, svn_author, svn_date, svn_executable, svn_special, uuid,
62
- revision_number, node_path, node_kind, node_action,
67
+ uint32_t uuid, revision_number, node_path, node_kind, node_action,
68
node_copyfrom_path, node_copyfrom_rev, text_content_length,
69
prop_content_length, content_length, svn_fs_dump_format_version,
70
/* version 3 format */
@@ -96,11 +101,6 @@ static void reset_dump_ctx(uint32_t url)
101
102
static void init_keys(void)
103
{
99
- keys.svn_log = pool_intern("svn:log");
100
- keys.svn_author = pool_intern("svn:author");
101
- keys.svn_date = pool_intern("svn:date");
102
- keys.svn_executable = pool_intern("svn:executable");
103
- keys.svn_special = pool_intern("svn:special");
104
keys.uuid = pool_intern("UUID");
105
keys.revision_number = pool_intern("Revision-number");
106
keys.node_path = pool_intern("Node-path");
@@ -117,22 +117,43 @@ static void init_keys(void)
117
keys.prop_delta = pool_intern("Prop-delta");
118
}
119
120
-static void handle_property(uint32_t key, const char *val, uint32_t len,
120
+static void handle_property(const struct strbuf *key_buf,
121
+ const char *val, uint32_t len,
122
uint32_t *type_set)
123
{
123
- if (key == keys.svn_log) {
124
+ const char *key = key_buf->buf;
125
+ size_t keylen = key_buf->len;
126
+
127
+ switch (keylen + 1) {
128
+ case sizeof("svn:log"):
129
+ if (constcmp(key, "svn:log"))
130
+ break;
131
if (!val)
132
die("invalid dump: unsets svn:log");
133
/* Value length excludes terminating nul. */
134
rev_ctx.log = log_copy(len + 1, val);
128
- } else if (key == keys.svn_author) {
135
+ break;
136
+ case sizeof("svn:author"):
137
+ if (constcmp(key, "svn:author"))
138
+ break;
139
rev_ctx.author = pool_intern(val);
130
- } else if (key == keys.svn_date) {
140
+ break;
141
+ case sizeof("svn:date"):
142
+ if (constcmp(key, "svn:date"))
143
+ break;
144
if (!val)
145
die("invalid dump: unsets svn:date");
146
if (parse_date_basic(val, &rev_ctx.timestamp, NULL))
147
warning("invalid timestamp: %s", val);
135
- } else if (key == keys.svn_executable || key == keys.svn_special) {
148
+ break;
149
+ case sizeof("svn:executable"):
150
+ case sizeof("svn:special"):
151
+ if (keylen == strlen("svn:executable") &&
152
+ constcmp(key, "svn:executable"))
153
+ break;
154
+ if (keylen == strlen("svn:special") &&
155
+ constcmp(key, "svn:special"))
156
+ break;
157
if (*type_set) {
158
if (!val)
159
return;
@@ -143,7 +164,7 @@ static void handle_property(uint32_t key, const char *val, uint32_t len,
164
return;
165
}
166
*type_set = 1;
146
- node_ctx.type = key == keys.svn_executable ?
167
+ node_ctx.type = keylen == strlen("svn:executable") ?
168
REPO_MODE_EXE :
169
REPO_MODE_LNK;
170
}
@@ -158,7 +179,7 @@ static void die_short_read(void)
179
180
static void read_props(void)
181
{
161
- uint32_t key = ~0;
182
+ static struct strbuf key = STRBUF_INIT;
183
const char *t;
184
/*
185
* NEEDSWORK: to support simple mode changes like
@@ -195,16 +216,19 @@ static void read_props(void)
216
217
switch (type) {
218
case 'K':
198
- key = pool_intern(val);
199
- continue;
219
case 'D':
201
- key = pool_intern(val);
220
+ strbuf_reset(&key);
221
+ if (val)
222
+ strbuf_add(&key, val, len);
223
+ if (type == 'K')
224
+ continue;
225
+ assert(type == 'D');
226
val = NULL;
227
len = 0;
228
/* fall through */
229
case 'V':
206
- handle_property(key, val, len, &type_set);
207
- key = ~0;
230
+ handle_property(&key, val, len, &type_set);
231
+ strbuf_reset(&key);
232
continue;
233
default:
234
die("invalid property line: %s\n", t);