Commit da3b391c by Russell Belfer

Convert revwalk to use git_pool

This removes the custom paged allocator from revwalk and
replaces it with a `git_pool`.
parent 19fa2bc1
...@@ -29,11 +29,8 @@ int git_pool_init( ...@@ -29,11 +29,8 @@ int git_pool_init(
else if (item_size == 3) else if (item_size == 3)
item_size = 4; item_size = 4;
if (!items_per_page) { if (!items_per_page)
uint32_t page_bytes = items_per_page = git_pool__suggest_items_per_page(item_size);
git_pool__system_page_size() - sizeof(git_pool_page);
items_per_page = page_bytes / item_size;
}
if (item_size * items_per_page < GIT_POOL_MIN_PAGESZ) if (item_size * items_per_page < GIT_POOL_MIN_PAGESZ)
items_per_page = (GIT_POOL_MIN_PAGESZ + item_size - 1) / item_size; items_per_page = (GIT_POOL_MIN_PAGESZ + item_size - 1) / item_size;
...@@ -288,3 +285,10 @@ uint32_t git_pool__system_page_size(void) ...@@ -288,3 +285,10 @@ uint32_t git_pool__system_page_size(void)
return size; 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;
}
...@@ -120,4 +120,6 @@ extern bool git_pool__ptr_in_pool(git_pool *pool, void *ptr); ...@@ -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__system_page_size(void);
extern uint32_t git_pool__suggest_items_per_page(uint32_t item_size);
#endif #endif
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "odb.h" #include "odb.h"
#include "hashtable.h" #include "hashtable.h"
#include "pqueue.h" #include "pqueue.h"
#include "pool.h"
#include "git2/revwalk.h" #include "git2/revwalk.h"
#include "git2/merge.h" #include "git2/merge.h"
...@@ -46,6 +47,7 @@ struct git_revwalk { ...@@ -46,6 +47,7 @@ struct git_revwalk {
git_odb *odb; git_odb *odb;
git_hashtable *commits; git_hashtable *commits;
git_pool commit_pool;
commit_list *iterator_topo; commit_list *iterator_topo;
commit_list *iterator_rand; commit_list *iterator_rand;
...@@ -55,9 +57,6 @@ struct git_revwalk { ...@@ -55,9 +57,6 @@ struct git_revwalk {
int (*get_next)(commit_object **, git_revwalk *); int (*get_next)(commit_object **, git_revwalk *);
int (*enqueue)(git_revwalk *, commit_object *); int (*enqueue)(git_revwalk *, commit_object *);
git_vector memory_alloc;
size_t chunk_size;
unsigned walking:1; unsigned walking:1;
unsigned int sorting; unsigned int sorting;
...@@ -133,42 +132,23 @@ static uint32_t object_table_hash(const void *key, int hash_id) ...@@ -133,42 +132,23 @@ static uint32_t object_table_hash(const void *key, int hash_id)
return r; return r;
} }
#define COMMITS_PER_CHUNK 128 #define PARENTS_PER_COMMIT 2
#define CHUNK_STEP 64 #define COMMIT_ALLOC \
#define PARENTS_PER_COMMIT ((CHUNK_STEP - sizeof(commit_object)) / sizeof(commit_object *)) (sizeof(commit_object) + PARENTS_PER_COMMIT * 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);
}
static commit_object *alloc_commit(git_revwalk *walk) static commit_object *alloc_commit(git_revwalk *walk)
{ {
unsigned char *chunk; return (commit_object *)git_pool_malloc(&walk->commit_pool, COMMIT_ALLOC);
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;
} }
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) 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) ...@@ -185,10 +165,8 @@ static commit_object *commit_lookup(git_revwalk *walk, const git_oid *oid)
git_oid_cpy(&commit->oid, oid); git_oid_cpy(&commit->oid, oid);
if (git_hashtable_insert(walk->commits, &commit->oid, commit) < 0) { if (git_hashtable_insert(walk->commits, &commit->oid, commit) < 0)
git__free(commit);
return NULL; return NULL;
}
return commit; return commit;
} }
...@@ -212,7 +190,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo ...@@ -212,7 +190,7 @@ static int commit_quick_parse(git_revwalk *walk, commit_object *commit, git_rawo
buffer += parent_len; buffer += parent_len;
} }
commit->parents = alloc_parents(commit, parents); commit->parents = alloc_parents(walk, commit, parents);
GITERR_CHECK_ALLOC(commit->parents); GITERR_CHECK_ALLOC(commit->parents);
buffer = parents_start; buffer = parents_start;
...@@ -756,9 +734,9 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo) ...@@ -756,9 +734,9 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
GITERR_CHECK_ALLOC(walk->commits); GITERR_CHECK_ALLOC(walk->commits);
if (git_pqueue_init(&walk->iterator_time, 8, commit_time_cmp) < 0 || 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 || 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; return -1;
walk->get_next = &revwalk_next_unsorted; walk->get_next = &revwalk_next_unsorted;
...@@ -777,30 +755,15 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo) ...@@ -777,30 +755,15 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo)
void git_revwalk_free(git_revwalk *walk) void git_revwalk_free(git_revwalk *walk)
{ {
unsigned int i;
commit_object *commit;
if (walk == NULL) if (walk == NULL)
return; return;
git_revwalk_reset(walk); git_revwalk_reset(walk);
git_odb_free(walk->odb); 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_hashtable_free(walk->commits);
git_pool_clear(&walk->commit_pool);
git_pqueue_free(&walk->iterator_time); 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_vector_free(&walk->twos);
git__free(walk); git__free(walk);
} }
......
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