eliminate strlen() calls during fileindex rb tree searches
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
diff --git a/include/got_path.h b/include/got_path.h
index 34114a2..929be76 100644
--- a/include/got_path.h
+++ b/include/got_path.h
@@ -51,9 +51,9 @@ int got_path_is_child(const char *, const char *, size_t);
/*
* Like strcmp() but orders children in subdirectories directly after
- * their parents.
+ * their parents. String lengths must also be passed in.
*/
-int got_path_cmp(const char *, const char *);
+int got_path_cmp(const char *, const char *, size_t, size_t);
/*
* Path lists allow for predictable concurrent iteration over multiple lists
diff --git a/lib/fileindex.c b/lib/fileindex.c
index 90e0c5f..ddcbf40 100644
--- a/lib/fileindex.c
+++ b/lib/fileindex.c
@@ -548,6 +548,8 @@ read_fileindex_entry(struct got_fileindex_entry **entryp, SHA1_CTX *ctx,
goto done;
err = read_fileindex_path(&entry->path, ctx, infile);
+ if (err == NULL)
+ entry->path_len = strlen(entry->path);
done:
if (err)
got_fileindex_entry_free(entry);
@@ -695,7 +697,8 @@ diff_fileindex_tree(struct got_fileindex *fileindex,
err = got_error_from_errno("asprintf");
break;
}
- cmp = got_path_cmp((*ie)->path, te_path);
+ cmp = got_path_cmp((*ie)->path, te_path,
+ (*ie)->path_len, strlen(te_path));
free(te_path);
if (cmp == 0) {
if (got_path_is_child((*ie)->path, path,
@@ -914,7 +917,8 @@ diff_fileindex_dir(struct got_fileindex *fileindex,
err = got_error_from_errno("asprintf");
break;
}
- cmp = got_path_cmp((*ie)->path, de_path);
+ cmp = got_path_cmp((*ie)->path, de_path,
+ (*ie)->path_len, strlen(path) + 1 + de->d_namlen);
free(de_path);
if (cmp == 0) {
err = cb->diff_old_new(cb_arg, *ie, de, path);
diff --git a/lib/got_lib_fileindex.h b/lib/got_lib_fileindex.h
index 3e7fc83..41f2dcd 100644
--- a/lib/got_lib_fileindex.h
+++ b/lib/got_lib_fileindex.h
@@ -55,6 +55,7 @@ struct got_fileindex_entry {
* Variable length, and NUL-padded to a multiple of 8 on disk.
*/
char *path;
+ size_t path_len; /* strlen(path) -- kept in memory only! */
/* More data could be here if F_EXTENDED is set; To be determined... */
};
@@ -73,7 +74,7 @@ static inline int
got_fileindex_cmp(const struct got_fileindex_entry *e1,
const struct got_fileindex_entry *e2)
{
- return got_path_cmp(e1->path, e2->path);
+ return got_path_cmp(e1->path, e2->path, e1->path_len, e2->path_len);
}
RB_PROTOTYPE(got_fileindex_tree, got_fileindex_entry, entry, got_fileindex_cmp);
diff --git a/lib/path.c b/lib/path.c
index a4c1a16..3605ef1 100644
--- a/lib/path.c
+++ b/lib/path.c
@@ -159,10 +159,8 @@ got_path_is_child(const char *child, const char *parent, size_t parent_len)
}
int
-got_path_cmp(const char *path1, const char *path2)
+got_path_cmp(const char *path1, const char *path2, size_t len1, size_t len2)
{
- size_t len1 = strlen(path1);
- size_t len2 = strlen(path2);
size_t min_len = MIN(len1, len2);
size_t i = 0;
@@ -234,7 +232,8 @@ got_pathlist_insert(struct got_pathlist_entry **inserted,
*/
pe = TAILQ_LAST(pathlist, got_pathlist_head);
while (pe) {
- int cmp = got_path_cmp(pe->path, path);
+ int cmp = got_path_cmp(pe->path, path,
+ strlen(pe->path), strlen(path));
if (cmp == 0) {
free(new); /* duplicate */
return NULL;
diff --git a/lib/reference.c b/lib/reference.c
index 9f0f7df..5f009d7 100644
--- a/lib/reference.c
+++ b/lib/reference.c
@@ -639,8 +639,10 @@ insert_ref(struct got_reflist_entry **newp, struct got_reflist_head *refs,
*/
re = SIMPLEQ_FIRST(refs);
while (re) {
- cmp = got_path_cmp(got_ref_get_name(re->ref),
- got_ref_get_name(new->ref));
+ const char *name = got_ref_get_name(re->ref);
+ const char *new_name = got_ref_get_name(new->ref);
+ cmp = got_path_cmp(name, new_name, strlen(name),
+ strlen(new_name));
if (cmp == 0) {
/* duplicate */
free(new->id);
diff --git a/lib/worktree.c b/lib/worktree.c
index 77022f3..b23c7b5 100644
--- a/lib/worktree.c
+++ b/lib/worktree.c
@@ -2207,7 +2207,8 @@ status_old_new(void *arg, struct got_fileindex_entry *ie,
if (a->cancel_cb && a->cancel_cb(a->cancel_arg))
return got_error(GOT_ERR_CANCELLED);
- if (got_path_cmp(parent_path, a->status_path) != 0 &&
+ if (got_path_cmp(parent_path, a->status_path,
+ strlen(parent_path), a->status_path_len) != 0 &&
!got_path_is_child(parent_path, a->status_path, a->status_path_len))
return NULL;
diff --git a/regress/path/path_test.c b/regress/path/path_test.c
index 951b0e5..07e0baa 100644
--- a/regress/path/path_test.c
+++ b/regress/path/path_test.c
@@ -84,7 +84,8 @@ path_cmp(void)
const char *path1 = test_data[i].path1;
const char *path2 = test_data[i].path2;
int expected = test_data[i].expected;
- int cmp = got_path_cmp(path1, path2);
+ int cmp = got_path_cmp(path1, path2,
+ strlen(path1), strlen(path2));
if (cmp != expected) {
test_printf("%d: '%s' vs '%s' == %d; expected %d\n",