Skip to content

Commit 99bf115

Browse files
stefanbellergitster
authored andcommitted
repository: introduce parsed objects field
Convert the existing global cache for parsed objects (obj_hash) into repository-specific parsed object caches. Existing code that uses obj_hash are modified to use the parsed object cache of the_repository; future patches will use the parsed object caches of other repositories. Another future use case for a pool of objects is ease of memory management in revision walking: If we can free the rev-list related memory early in pack-objects (e.g. part of repack operation) then it could lower memory pressure significantly when running on large repos. While this has been discussed on the mailing list lately, this series doesn't implement this. Signed-off-by: Stefan Beller <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9d98354 commit 99bf115

File tree

4 files changed

+64
-23
lines changed

4 files changed

+64
-23
lines changed

object.c

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,14 @@
88
#include "object-store.h"
99
#include "packfile.h"
1010

11-
static struct object **obj_hash;
12-
static int nr_objs, obj_hash_size;
13-
1411
unsigned int get_max_object_index(void)
1512
{
16-
return obj_hash_size;
13+
return the_repository->parsed_objects->obj_hash_size;
1714
}
1815

1916
struct object *get_indexed_object(unsigned int idx)
2017
{
21-
return obj_hash[idx];
18+
return the_repository->parsed_objects->obj_hash[idx];
2219
}
2320

2421
static const char *object_type_strings[] = {
@@ -90,15 +87,16 @@ struct object *lookup_object(const unsigned char *sha1)
9087
unsigned int i, first;
9188
struct object *obj;
9289

93-
if (!obj_hash)
90+
if (!the_repository->parsed_objects->obj_hash)
9491
return NULL;
9592

96-
first = i = hash_obj(sha1, obj_hash_size);
97-
while ((obj = obj_hash[i]) != NULL) {
93+
first = i = hash_obj(sha1,
94+
the_repository->parsed_objects->obj_hash_size);
95+
while ((obj = the_repository->parsed_objects->obj_hash[i]) != NULL) {
9896
if (!hashcmp(sha1, obj->oid.hash))
9997
break;
10098
i++;
101-
if (i == obj_hash_size)
99+
if (i == the_repository->parsed_objects->obj_hash_size)
102100
i = 0;
103101
}
104102
if (obj && i != first) {
@@ -107,7 +105,8 @@ struct object *lookup_object(const unsigned char *sha1)
107105
* that we do not need to walk the hash table the next
108106
* time we look for it.
109107
*/
110-
SWAP(obj_hash[i], obj_hash[first]);
108+
SWAP(the_repository->parsed_objects->obj_hash[i],
109+
the_repository->parsed_objects->obj_hash[first]);
111110
}
112111
return obj;
113112
}
@@ -124,19 +123,19 @@ static void grow_object_hash(void)
124123
* Note that this size must always be power-of-2 to match hash_obj
125124
* above.
126125
*/
127-
int new_hash_size = obj_hash_size < 32 ? 32 : 2 * obj_hash_size;
126+
int new_hash_size = the_repository->parsed_objects->obj_hash_size < 32 ? 32 : 2 * the_repository->parsed_objects->obj_hash_size;
128127
struct object **new_hash;
129128

130129
new_hash = xcalloc(new_hash_size, sizeof(struct object *));
131-
for (i = 0; i < obj_hash_size; i++) {
132-
struct object *obj = obj_hash[i];
130+
for (i = 0; i < the_repository->parsed_objects->obj_hash_size; i++) {
131+
struct object *obj = the_repository->parsed_objects->obj_hash[i];
133132
if (!obj)
134133
continue;
135134
insert_obj_hash(obj, new_hash, new_hash_size);
136135
}
137-
free(obj_hash);
138-
obj_hash = new_hash;
139-
obj_hash_size = new_hash_size;
136+
free(the_repository->parsed_objects->obj_hash);
137+
the_repository->parsed_objects->obj_hash = new_hash;
138+
the_repository->parsed_objects->obj_hash_size = new_hash_size;
140139
}
141140

142141
void *create_object(const unsigned char *sha1, void *o)
@@ -147,11 +146,12 @@ void *create_object(const unsigned char *sha1, void *o)
147146
obj->flags = 0;
148147
hashcpy(obj->oid.hash, sha1);
149148

150-
if (obj_hash_size - 1 <= nr_objs * 2)
149+
if (the_repository->parsed_objects->obj_hash_size - 1 <= the_repository->parsed_objects->nr_objs * 2)
151150
grow_object_hash();
152151

153-
insert_obj_hash(obj, obj_hash, obj_hash_size);
154-
nr_objs++;
152+
insert_obj_hash(obj, the_repository->parsed_objects->obj_hash,
153+
the_repository->parsed_objects->obj_hash_size);
154+
the_repository->parsed_objects->nr_objs++;
155155
return obj;
156156
}
157157

@@ -431,8 +431,8 @@ void clear_object_flags(unsigned flags)
431431
{
432432
int i;
433433

434-
for (i=0; i < obj_hash_size; i++) {
435-
struct object *obj = obj_hash[i];
434+
for (i=0; i < the_repository->parsed_objects->obj_hash_size; i++) {
435+
struct object *obj = the_repository->parsed_objects->obj_hash[i];
436436
if (obj)
437437
obj->flags &= ~flags;
438438
}
@@ -442,13 +442,20 @@ void clear_commit_marks_all(unsigned int flags)
442442
{
443443
int i;
444444

445-
for (i = 0; i < obj_hash_size; i++) {
446-
struct object *obj = obj_hash[i];
445+
for (i = 0; i < the_repository->parsed_objects->obj_hash_size; i++) {
446+
struct object *obj = the_repository->parsed_objects->obj_hash[i];
447447
if (obj && obj->type == OBJ_COMMIT)
448448
obj->flags &= ~flags;
449449
}
450450
}
451451

452+
struct parsed_object_pool *parsed_object_pool_new(void)
453+
{
454+
struct parsed_object_pool *o = xmalloc(sizeof(*o));
455+
memset(o, 0, sizeof(*o));
456+
return o;
457+
}
458+
452459
struct raw_object_store *raw_object_store_new(void)
453460
{
454461
struct raw_object_store *o = xmalloc(sizeof(*o));
@@ -488,3 +495,13 @@ void raw_object_store_clear(struct raw_object_store *o)
488495
close_all_packs(o);
489496
o->packed_git = NULL;
490497
}
498+
499+
void parsed_object_pool_clear(struct parsed_object_pool *o)
500+
{
501+
/*
502+
* TOOD free objects in o->obj_hash.
503+
*
504+
* As objects are allocated in slabs (see alloc.c), we do
505+
* not need to free each object, but each slab instead.
506+
*/
507+
}

object.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#ifndef OBJECT_H
22
#define OBJECT_H
33

4+
struct parsed_object_pool {
5+
struct object **obj_hash;
6+
int nr_objs, obj_hash_size;
7+
};
8+
9+
struct parsed_object_pool *parsed_object_pool_new(void);
10+
void parsed_object_pool_clear(struct parsed_object_pool *o);
11+
412
struct object_list {
513
struct object *item;
614
struct object_list *next;

repository.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "repository.h"
33
#include "object-store.h"
44
#include "config.h"
5+
#include "object.h"
56
#include "submodule-config.h"
67

78
/* The main repository */
@@ -14,6 +15,8 @@ void initialize_the_repository(void)
1415

1516
the_repo.index = &the_index;
1617
the_repo.objects = raw_object_store_new();
18+
the_repo.parsed_objects = parsed_object_pool_new();
19+
1720
repo_set_hash_algo(&the_repo, GIT_HASH_SHA1);
1821
}
1922

@@ -143,6 +146,7 @@ static int repo_init(struct repository *repo,
143146
memset(repo, 0, sizeof(*repo));
144147

145148
repo->objects = raw_object_store_new();
149+
repo->parsed_objects = parsed_object_pool_new();
146150

147151
if (repo_init_gitdir(repo, gitdir))
148152
goto error;
@@ -226,6 +230,9 @@ void repo_clear(struct repository *repo)
226230
raw_object_store_clear(repo->objects);
227231
FREE_AND_NULL(repo->objects);
228232

233+
parsed_object_pool_clear(repo->parsed_objects);
234+
FREE_AND_NULL(repo->parsed_objects);
235+
229236
if (repo->config) {
230237
git_configset_clear(repo->config);
231238
FREE_AND_NULL(repo->config);

repository.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,15 @@ struct repository {
2626
*/
2727
struct raw_object_store *objects;
2828

29+
/*
30+
* All objects in this repository that have been parsed. This structure
31+
* owns all objects it references, so users of "struct object *"
32+
* generally do not need to free them; instead, when a repository is no
33+
* longer used, call parsed_object_pool_clear() on this structure, which
34+
* is called by the repositories repo_clear on its desconstruction.
35+
*/
36+
struct parsed_object_pool *parsed_objects;
37+
2938
/* The store in which the refs are held. */
3039
struct ref_store *refs;
3140

0 commit comments

Comments
 (0)