Commit 8cc16e29 by Kirill A. Shutemov

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>
parent 17837602
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment