diff options
author | Kirill A. Shutemov <kirill@shutemov.name> | 2011-06-30 23:22:42 +0300 |
---|---|---|
committer | Kirill A. Shutemov <kirill@shutemov.name> | 2011-07-05 17:52:39 +0300 |
commit | 8cc16e29e88a02e26b16da66aca6fa589831b76c (patch) | |
tree | d613ce9e40f03bcd5974a5f5b2c5994cb6f2788d | |
parent | 178376025cc70cc8da3ca58699717f2cc8e495a7 (diff) | |
download | libgit2-8cc16e29e88a02e26b16da66aca6fa589831b76c.tar.gz |
index: speedup git_index_append()/git_index_append2()
git_index_find() in index_insert() is useless if replace is not
requested (append). Do not call it in this case.
It speedup git_index_append() *dramatically* on large indexes.
$ cat index_test.c
int main(int argc, char **argv)
{
git_index *index;
git_repository *repo;
git_odb *odb;
struct git_index_entry entry;
git_oid tree_oid;
char tree_hex[41];
int i;
git_repository_init(&repo, "/tmp/myrepo", 0);
odb = git_repository_database(repo);
git_repository_index(&index, repo);
memset(&entry, 0, sizeof(entry));
git_odb_write(&entry.oid, odb, "", 0, GIT_OBJ_BLOB);
entry.path = "test.file";
for (i = 0; i < 50000; i++)
git_index_append2(index, &entry);
git_tree_create_fromindex(&tree_oid, index);
git_oid_fmt(tree_hex, &tree_oid);
tree_hex[40] = '\0';
printf("tree: %s\n", tree_hex);
git_index_free(index);
git_repository_free(repo);
return 0;
}
Before:
$ time ./index_test
tree: 43f73659c43b651588cc81459d9e25b08721b95d
./index_test 151.19s user 0.05s system 99% cpu 2:31.78 total
After:
$ time ./index_test
tree: 43f73659c43b651588cc81459d9e25b08721b95d
./index_test 0.05s user 0.00s system 94% cpu 0.059 total
About 2573 times speedup on this test :)
Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name>
-rw-r--r-- | src/index.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/src/index.c b/src/index.c index 06fa95c7b..fd905d007 100644 --- a/src/index.c +++ b/src/index.c @@ -348,6 +348,7 @@ static int index_insert(git_index *index, const git_index_entry *source_entry, i git_index_entry *entry; size_t path_length; int position; + git_index_entry **entry_array; assert(index && source_entry); @@ -375,27 +376,28 @@ static int index_insert(git_index *index, const git_index_entry *source_entry, i else entry->flags |= GIT_IDXENTRY_NAMEMASK;; + /* + * replacing is not requested: just insert entry at the end; + * the index is no longer sorted + */ + if (!replace) + return git_vector_insert(&index->entries, entry); /* look if an entry with this path already exists */ position = git_index_find(index, source_entry->path); - /* if no entry exists and replace is not set, - * add the entry at the end; - * the index is no longer sorted */ - if (!replace || position == GIT_ENOTFOUND) { - if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS) - return GIT_ENOMEM; - - /* if a previous entry exists and replace is set, - * replace it */ - } else { - git_index_entry **entry_array = (git_index_entry **)index->entries.contents; - - free((char *)entry_array[position]->path); - free(entry_array[position]); - - entry_array[position] = entry; - } + /* + * if no entry exists add the entry at the end; + * the index is no longer sorted + */ + if (position == GIT_ENOTFOUND) + return git_vector_insert(&index->entries, entry); + + /* exists, replace it */ + entry_array = (git_index_entry **) index->entries.contents; + free((char *)entry_array[position]->path); + free(entry_array[position]); + entry_array[position] = entry; return GIT_SUCCESS; } |