summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Belfer <rb@github.com>2012-04-18 10:57:08 -0700
committerRussell Belfer <rb@github.com>2012-04-25 11:14:34 -0700
commitda3b391c32b973d5c073951b6848eedd40434e5e (patch)
treee4fa76f5300ee4c698e3f0c9c2f6839f2f54aef0
parent19fa2bc111d50dc2bafb1393b87b5ba119615ae2 (diff)
downloadlibgit2-da3b391c32b973d5c073951b6848eedd40434e5e.tar.gz
Convert revwalk to use git_pool
This removes the custom paged allocator from revwalk and replaces it with a `git_pool`.
-rw-r--r--src/pool.c14
-rw-r--r--src/pool.h2
-rw-r--r--src/revwalk.c69
3 files changed, 27 insertions, 58 deletions
diff --git a/src/pool.c b/src/pool.c
index 2e64bde4a..8f5c7e75a 100644
--- a/src/pool.c
+++ b/src/pool.c
@@ -29,11 +29,8 @@ int git_pool_init(
else if (item_size == 3)
item_size = 4;
- if (!items_per_page) {
- uint32_t page_bytes =
- git_pool__system_page_size() - sizeof(git_pool_page);
- items_per_page = page_bytes / item_size;
- }
+ if (!items_per_page)
+ items_per_page = git_pool__suggest_items_per_page(item_size);
if (item_size * items_per_page < GIT_POOL_MIN_PAGESZ)
items_per_page = (GIT_POOL_MIN_PAGESZ + item_size - 1) / item_size;
@@ -288,3 +285,10 @@ uint32_t git_pool__system_page_size(void)
return size;
}
+uint32_t git_pool__suggest_items_per_page(uint32_t item_size)
+{
+ uint32_t page_bytes =
+ git_pool__system_page_size() - sizeof(git_pool_page);
+ return page_bytes / item_size;
+}
+
diff --git a/src/pool.h b/src/pool.h
index a92589087..54a2861ed 100644
--- a/src/pool.h
+++ b/src/pool.h
@@ -120,4 +120,6 @@ extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr);
extern uint32_t git_pool__system_page_size(void);
+extern uint32_t git_pool__suggest_items_per_page(uint32_t item_size);
+
#endif
diff --git a/src/revwalk.c b/src/revwalk.c
index a62576038..557966b94 100644
--- a/src/revwalk.c
+++ b/src/revwalk.c
@@ -10,6 +10,7 @@
#include "odb.h"
#include "hashtable.h"
#include "pqueue.h"
+#include "pool.h"
#include "git2/revwalk.h"
#include "git2/merge.h"
@@ -46,6 +47,7 @@ struct git_revwalk {
git_odb *odb;
git_hashtable *commits;
+ git_pool commit_pool;
commit_list *iterator_topo;
commit_list *iterator_rand;
@@ -55,9 +57,6 @@ struct git_revwalk {
int (*get_next)(commit_object **, git_revwalk *);
int (*enqueue)(git_revwalk *, commit_object *);
- git_vector memory_alloc;
- size_t chunk_size;
-
unsigned walking:1;
unsigned int sorting;
@@ -133,42 +132,23 @@ static uint32_t object_table_hash(const void *key, int hash_id)
return r;
}
-#define COMMITS_PER_CHUNK 128
-#define CHUNK_STEP 64
-#define PARENTS_PER_COMMIT ((CHUNK_STEP - sizeof(commit_object)) / sizeof(commit_object *))
-
-static int alloc_chunk(git_revwalk *walk)
-{
- void *chunk;
-
- chunk = git__calloc(COMMITS_PER_CHUNK, CHUNK_STEP);
- GITERR_CHECK_ALLOC(chunk);
-
- walk->chunk_size = 0;
- return git_vector_insert(&walk->memory_alloc, chunk);
-}
+#define PARENTS_PER_COMMIT 2
+#define COMMIT_ALLOC \
+ (sizeof(commit_object) + PARENTS_PER_COMMIT * sizeof(commit_object *))
static commit_object *alloc_commit(git_revwalk *walk)
{
- unsigned char *chunk;
-
- if (walk->chunk_size == COMMITS_PER_CHUNK)
- if (alloc_chunk(walk) < 0)
- return NULL;
-
- chunk = git_vector_get(&walk->memory_alloc, walk->memory_alloc.length - 1);
- chunk += (walk->chunk_size * CHUNK_STEP);
- walk->chunk_size++;
-
- return (commit_object *)chunk;
+ return (commit_object *)git_pool_malloc(&walk->commit_pool, COMMIT_ALLOC);
}
-static commit_object **alloc_parents(commit_object *commit, size_t n_parents)
+static commit_object **alloc_parents(
+ git_revwalk *walk, commit_object *commit, size_t n_parents)
{
if (n_parents <= PARENTS_PER_COMMIT)
- return (commit_object **)((unsigned char *)commit + sizeof(commit_object));
+ return (commit_object **)((char *)commit + sizeof(commit_object));
- return git__malloc(n_parents * sizeof(commit_object *));
+ return (commit_object **)git_pool_malloc(
+ &walk->commit_pool, n_parents * sizeof(commit_object *));
}
@@ -185,10 +165,8 @@ static commit_object *commit_lookup(git_revwalk *walk, const git_oid *oid)
git_oid_cpy(&commit->oid, oid);
- if (git_hashtable_insert(walk->commits, &commit->oid, commit) < 0) {
- git__free(commit);
+ if (git_hashtable_insert(walk->commits, &commit->oid, commit) < 0)
return NULL;
- }
return commit;
}
@@ -212,7 +190,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
buffer += parent_len;
}
- commit->parents = alloc_parents(commit, parents);
+ commit->parents = alloc_parents(walk, commit, parents);
GITERR_CHECK_ALLOC(commit->parents);
buffer = parents_start;
@@ -756,9 +734,9 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
GITERR_CHECK_ALLOC(walk->commits);
if (git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp) < 0 ||
- git_vector_init(&walk->memory_alloc, 8, NULL) < 0 ||
git_vector_init(&walk->twos, 4, NULL) < 0 ||
- alloc_chunk(walk) < 0)
+ git_pool_init(&walk->commit_pool, 1,
+ git_pool__suggest_items_per_page(COMMIT_ALLOC) * COMMIT_ALLOC) < 0)
return -1;
walk->get_next = &revwalk_next_unsorted;
@@ -777,30 +755,15 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
void git_revwalk_free(git_revwalk *walk)
{
- unsigned int i;
- commit_object *commit;
-
if (walk == NULL)
return;
git_revwalk_reset(walk);
git_odb_free(walk->odb);
- /* if the parent has more than PARENTS_PER_COMMIT parents,
- * we had to allocate a separate array for those parents.
- * make sure it's being free'd */
- GIT_HASHTABLE_FOREACH_VALUE(walk->commits, commit, {
- if (commit->out_degree > PARENTS_PER_COMMIT)
- git__free(commit->parents);
- });
-
git_hashtable_free(walk->commits);
+ git_pool_clear(&walk->commit_pool);
git_pqueue_free(&walk->iterator_time);
-
- for (i = 0; i < walk->memory_alloc.length; ++i)
- git__free(git_vector_get(&walk->memory_alloc, i));
-
- git_vector_free(&walk->memory_alloc);
git_vector_free(&walk->twos);
git__free(walk);
}