mirror of
https://git.proxmox.com/git/libgit2
synced 2025-08-11 12:09:07 +00:00
Convert revwalk to use git_pool
This removes the custom paged allocator from revwalk and replaces it with a `git_pool`.
This commit is contained in:
parent
19fa2bc111
commit
da3b391c32
14
src/pool.c
14
src/pool.c
@ -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)
|
|||||||
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);
|
|||||||
|
|
||||||
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 @@
|
|||||||
#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 {
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user