Commit d572f5860a456fe9ab48d8444dd4cbec28fcae6c

Stefan Sperling 2019-08-02T15:42:42

eliminate strlen() calls during fileindex rb tree searches

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",