Skip to content

Commit 8d2dfc4

Browse files
torvaldsgitster
authored andcommitted
process_{tree,blob}: show objects without buffering
Here's a less trivial thing, and slightly more dubious one. I was looking at that "struct object_array objects", and wondering why we do that. I have honestly totally forgotten. Why not just call the "show()" function as we encounter the objects? Rather than add the objects to the object_array, and then at the very end going through the array and doing a 'show' on all, just do things more incrementally. Now, there are possible downsides to this: - the "buffer using object_array" _can_ in theory result in at least better I-cache usage (two tight loops rather than one more spread out one). I don't think this is a real issue, but in theory.. - this _does_ change the order of the objects printed. Instead of doing a "process_tree(revs, commit->tree, &objects, NULL, "");" in the loop over the commits (which puts all the root trees _first_ in the object list, this patch just adds them to the list of pending objects, and then we'll traverse them in that order (and thus show each root tree object together with the objects we discover under it) I _think_ the new ordering actually makes more sense, but the object ordering is actually a subtle thing when it comes to packing efficiency, so any change in order is going to have implications for packing. Good or bad, I dunno. - There may be some reason why we did it that odd way with the object array, that I have simply forgotten. Anyway, now that we don't buffer up the objects before showing them that may actually result in lower memory usage during that whole traverse_commit_list() phase. This is seriously not very deeply tested. It makes sense to me, it seems to pass all the tests, it looks ok, but... Does anybody remember why we did that "object_array" thing? It used to be an "object_list" a long long time ago, but got changed into the array due to better memory usage patterns (those linked lists of obejcts are horrible from a memory allocation standpoint). But I wonder why we didn't do this back then. Maybe there's a reason for it. Or maybe there _used_ to be a reason, and no longer is. Signed-off-by: Junio C Hamano <[email protected]>
1 parent 2131526 commit 8d2dfc4

File tree

7 files changed

+48
-41
lines changed

7 files changed

+48
-41
lines changed

builtin-pack-objects.c

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,13 +1856,17 @@ static void show_commit(struct commit *commit)
18561856
commit->object.flags |= OBJECT_ADDED;
18571857
}
18581858

1859-
static void show_object(struct object_array_entry *p)
1859+
static void show_object(struct object *obj, const char *name)
18601860
{
1861-
add_preferred_base_object(p->name);
1862-
add_object_entry(p->item->sha1, p->item->type, p->name, 0);
1863-
p->item->flags |= OBJECT_ADDED;
1864-
free((char *)p->name);
1865-
p->name = NULL;
1861+
add_preferred_base_object(name);
1862+
add_object_entry(obj->sha1, obj->type, name, 0);
1863+
obj->flags |= OBJECT_ADDED;
1864+
1865+
/*
1866+
* We will have generated the hash from the name,
1867+
* but not saved a pointer to it - we can free it
1868+
*/
1869+
free((char *)name);
18661870
}
18671871

18681872
static void show_edge(struct commit *commit)

builtin-rev-list.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -169,27 +169,27 @@ static void finish_commit(struct commit *commit)
169169
commit->buffer = NULL;
170170
}
171171

172-
static void finish_object(struct object_array_entry *p)
172+
static void finish_object(struct object *obj, const char *name)
173173
{
174-
if (p->item->type == OBJ_BLOB && !has_sha1_file(p->item->sha1))
175-
die("missing blob object '%s'", sha1_to_hex(p->item->sha1));
174+
if (obj->type == OBJ_BLOB && !has_sha1_file(obj->sha1))
175+
die("missing blob object '%s'", sha1_to_hex(obj->sha1));
176176
}
177177

178-
static void show_object(struct object_array_entry *p)
178+
static void show_object(struct object *obj, const char *name)
179179
{
180180
/* An object with name "foo\n0000000..." can be used to
181181
* confuse downstream "git pack-objects" very badly.
182182
*/
183-
const char *ep = strchr(p->name, '\n');
183+
const char *ep = strchr(name, '\n');
184184

185-
finish_object(p);
185+
finish_object(obj, name);
186186
if (ep) {
187-
printf("%s %.*s\n", sha1_to_hex(p->item->sha1),
188-
(int) (ep - p->name),
189-
p->name);
187+
printf("%s %.*s\n", sha1_to_hex(obj->sha1),
188+
(int) (ep - name),
189+
name);
190190
}
191191
else
192-
printf("%s %s\n", sha1_to_hex(p->item->sha1), p->name);
192+
printf("%s %s\n", sha1_to_hex(obj->sha1), name);
193193
}
194194

195195
static void show_edge(struct commit *commit)

list-objects.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
static void process_blob(struct rev_info *revs,
1212
struct blob *blob,
13-
struct object_array *p,
13+
show_object_fn show,
1414
struct name_path *path,
1515
const char *name)
1616
{
@@ -23,7 +23,7 @@ static void process_blob(struct rev_info *revs,
2323
if (obj->flags & (UNINTERESTING | SEEN))
2424
return;
2525
obj->flags |= SEEN;
26-
add_object(obj, p, path, name);
26+
show(obj, path_name(path, name));
2727
}
2828

2929
/*
@@ -50,7 +50,7 @@ static void process_blob(struct rev_info *revs,
5050
*/
5151
static void process_gitlink(struct rev_info *revs,
5252
const unsigned char *sha1,
53-
struct object_array *p,
53+
show_object_fn show,
5454
struct name_path *path,
5555
const char *name)
5656
{
@@ -59,7 +59,7 @@ static void process_gitlink(struct rev_info *revs,
5959

6060
static void process_tree(struct rev_info *revs,
6161
struct tree *tree,
62-
struct object_array *p,
62+
show_object_fn show,
6363
struct name_path *path,
6464
const char *name)
6565
{
@@ -77,7 +77,7 @@ static void process_tree(struct rev_info *revs,
7777
if (parse_tree(tree) < 0)
7878
die("bad tree object %s", sha1_to_hex(obj->sha1));
7979
obj->flags |= SEEN;
80-
add_object(obj, p, path, name);
80+
show(obj, path_name(path, name));
8181
me.up = path;
8282
me.elem = name;
8383
me.elem_len = strlen(name);
@@ -88,14 +88,14 @@ static void process_tree(struct rev_info *revs,
8888
if (S_ISDIR(entry.mode))
8989
process_tree(revs,
9090
lookup_tree(entry.sha1),
91-
p, &me, entry.path);
91+
show, &me, entry.path);
9292
else if (S_ISGITLINK(entry.mode))
9393
process_gitlink(revs, entry.sha1,
94-
p, &me, entry.path);
94+
show, &me, entry.path);
9595
else
9696
process_blob(revs,
9797
lookup_blob(entry.sha1),
98-
p, &me, entry.path);
98+
show, &me, entry.path);
9999
}
100100
free(tree->buffer);
101101
tree->buffer = NULL;
@@ -134,16 +134,20 @@ void mark_edges_uninteresting(struct commit_list *list,
134134
}
135135
}
136136

137+
static void add_pending_tree(struct rev_info *revs, struct tree *tree)
138+
{
139+
add_pending_object(revs, &tree->object, "");
140+
}
141+
137142
void traverse_commit_list(struct rev_info *revs,
138143
void (*show_commit)(struct commit *),
139-
void (*show_object)(struct object_array_entry *))
144+
void (*show_object)(struct object *, const char *))
140145
{
141146
int i;
142147
struct commit *commit;
143-
struct object_array objects = { 0, 0, NULL };
144148

145149
while ((commit = get_revision(revs)) != NULL) {
146-
process_tree(revs, commit->tree, &objects, NULL, "");
150+
add_pending_tree(revs, commit->tree);
147151
show_commit(commit);
148152
}
149153
for (i = 0; i < revs->pending.nr; i++) {
@@ -154,25 +158,22 @@ void traverse_commit_list(struct rev_info *revs,
154158
continue;
155159
if (obj->type == OBJ_TAG) {
156160
obj->flags |= SEEN;
157-
add_object_array(obj, name, &objects);
161+
show_object(obj, name);
158162
continue;
159163
}
160164
if (obj->type == OBJ_TREE) {
161-
process_tree(revs, (struct tree *)obj, &objects,
165+
process_tree(revs, (struct tree *)obj, show_object,
162166
NULL, name);
163167
continue;
164168
}
165169
if (obj->type == OBJ_BLOB) {
166-
process_blob(revs, (struct blob *)obj, &objects,
170+
process_blob(revs, (struct blob *)obj, show_object,
167171
NULL, name);
168172
continue;
169173
}
170174
die("unknown pending object %s (%s)",
171175
sha1_to_hex(obj->sha1), name);
172176
}
173-
for (i = 0; i < objects.nr; i++)
174-
show_object(&objects.objects[i]);
175-
free(objects.objects);
176177
if (revs->pending.nr) {
177178
free(revs->pending.objects);
178179
revs->pending.nr = 0;

list-objects.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#define LIST_OBJECTS_H
33

44
typedef void (*show_commit_fn)(struct commit *);
5-
typedef void (*show_object_fn)(struct object_array_entry *);
5+
typedef void (*show_object_fn)(struct object *, const char *);
66
typedef void (*show_edge_fn)(struct commit *);
77

88
void traverse_commit_list(struct rev_info *revs, show_commit_fn, show_object_fn);

revision.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
volatile show_early_output_fn_t show_early_output;
1616

17-
static char *path_name(struct name_path *path, const char *name)
17+
char *path_name(struct name_path *path, const char *name)
1818
{
1919
struct name_path *p;
2020
char *n, *m;

revision.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ struct name_path {
141141
const char *elem;
142142
};
143143

144+
char *path_name(struct name_path *path, const char *name);
145+
144146
extern void add_object(struct object *obj,
145147
struct object_array *p,
146148
struct name_path *path,

upload-pack.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,20 @@ static void show_commit(struct commit *commit)
7878
commit->buffer = NULL;
7979
}
8080

81-
static void show_object(struct object_array_entry *p)
81+
static void show_object(struct object *obj, const char *name)
8282
{
8383
/* An object with name "foo\n0000000..." can be used to
8484
* confuse downstream git-pack-objects very badly.
8585
*/
86-
const char *ep = strchr(p->name, '\n');
86+
const char *ep = strchr(name, '\n');
8787
if (ep) {
88-
fprintf(pack_pipe, "%s %.*s\n", sha1_to_hex(p->item->sha1),
89-
(int) (ep - p->name),
90-
p->name);
88+
fprintf(pack_pipe, "%s %.*s\n", sha1_to_hex(obj->sha1),
89+
(int) (ep - name),
90+
name);
9191
}
9292
else
9393
fprintf(pack_pipe, "%s %s\n",
94-
sha1_to_hex(p->item->sha1), p->name);
94+
sha1_to_hex(obj->sha1), name);
9595
}
9696

9797
static void show_edge(struct commit *commit)

0 commit comments

Comments
 (0)