Skip to content

Commit

Permalink
Shrink "struct object" a bit
Browse files Browse the repository at this point in the history
This shrinks "struct object" by a small amount, by getting rid of the
"struct type *" pointer and replacing it with a 3-bit bitfield instead.

In addition, we merge the bitfields and the "flags" field, which
incidentally should also remove a useless 4-byte padding from the object
when in 64-bit mode.

Now, our "struct object" is still too damn large, but it's now less
obviously bloated, and of the remaining fields, only the "util" (which is
not used by most things) is clearly something that should be eventually
discarded.

This shrinks the "git-rev-list --all" memory use by about 2.5% on the
kernel archive (and, perhaps more importantly, on the larger mozilla
archive). That may not sound like much, but I suspect it's more on a
64-bit platform.

There are other remaining inefficiencies (the parent lists, for example,
probably have horrible malloc overhead), but this was pretty obvious.

Most of the patch is just changing the comparison of the "type" pointer
from one of the constant string pointers to the appropriate new TYPE_xxx
small integer constant.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
Linus Torvalds authored and Junio C Hamano committed Jun 18, 2006
1 parent 210a0be commit 885a86a
Show file tree
Hide file tree
Showing 21 changed files with 113 additions and 96 deletions.
10 changes: 5 additions & 5 deletions blob.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ struct blob *lookup_blob(const unsigned char *sha1)
if (!obj) {
struct blob *ret = xcalloc(1, sizeof(struct blob));
created_object(sha1, &ret->object);
ret->object.type = blob_type;
ret->object.type = TYPE_BLOB;
return ret;
}
if (!obj->type)
obj->type = blob_type;
if (obj->type != blob_type) {
error("Object %s is a %s, not a blob",
sha1_to_hex(sha1), obj->type);
obj->type = TYPE_BLOB;
if (obj->type != TYPE_BLOB) {
error("Object %s is a %s, not a blob",
sha1_to_hex(sha1), typename(obj->type));
return NULL;
}
return (struct blob *) obj;
Expand Down
6 changes: 3 additions & 3 deletions builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,9 @@ int cmd_diff(int argc, const char **argv, char **envp)
obj = deref_tag(obj, NULL, 0);
if (!obj)
die("invalid object '%s' given.", name);
if (!strcmp(obj->type, commit_type))
if (obj->type == TYPE_COMMIT)
obj = &((struct commit *)obj)->tree->object;
if (!strcmp(obj->type, tree_type)) {
if (obj->type == TYPE_TREE) {
if (ARRAY_SIZE(ent) <= ents)
die("more than %d trees given: '%s'",
(int) ARRAY_SIZE(ent), name);
Expand All @@ -315,7 +315,7 @@ int cmd_diff(int argc, const char **argv, char **envp)
ents++;
continue;
}
if (!strcmp(obj->type, blob_type)) {
if (obj->type == TYPE_BLOB) {
if (2 <= blobs)
die("more than two blobs given: '%s'", name);
memcpy(blob[blobs].sha1, obj->sha1, 20);
Expand Down
7 changes: 3 additions & 4 deletions builtin-grep.c
Original file line number Diff line number Diff line change
Expand Up @@ -630,10 +630,9 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
static int grep_object(struct grep_opt *opt, const char **paths,
struct object *obj, const char *name)
{
if (!strcmp(obj->type, blob_type))
if (obj->type == TYPE_BLOB)
return grep_sha1(opt, obj->sha1, name);
if (!strcmp(obj->type, commit_type) ||
!strcmp(obj->type, tree_type)) {
if (obj->type == TYPE_COMMIT || obj->type == TYPE_TREE) {
struct tree_desc tree;
void *data;
int hit;
Expand All @@ -646,7 +645,7 @@ static int grep_object(struct grep_opt *opt, const char **paths,
free(data);
return hit;
}
die("unable to grep from object of type %s", obj->type);
die("unable to grep from object of type %s", typename(obj->type));
}

static const char builtin_grep_usage[] =
Expand Down
6 changes: 3 additions & 3 deletions builtin-rev-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,16 @@ static void show_commit_list(struct rev_info *revs)
const char *name = pending->name;
if (obj->flags & (UNINTERESTING | SEEN))
continue;
if (obj->type == tag_type) {
if (obj->type == TYPE_TAG) {
obj->flags |= SEEN;
p = add_object(obj, p, NULL, name);
continue;
}
if (obj->type == tree_type) {
if (obj->type == TYPE_TREE) {
p = process_tree((struct tree *)obj, p, NULL, name);
continue;
}
if (obj->type == blob_type) {
if (obj->type == TYPE_BLOB) {
p = process_blob((struct blob *)obj, p, NULL, name);
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion builtin-show-branch.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ static const char **default_arg = NULL;
#define UNINTERESTING 01

#define REV_SHIFT 2
#define MAX_REVS 29 /* should not exceed bits_per_int - REV_SHIFT */
#define MAX_REVS (FLAG_BITS - REV_SHIFT) /* should not exceed bits_per_int - REV_SHIFT */

static struct commit *interesting(struct commit_list *list)
{
Expand Down
8 changes: 4 additions & 4 deletions commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ static struct commit *check_commit(struct object *obj,
const unsigned char *sha1,
int quiet)
{
if (obj->type != commit_type) {
if (obj->type != TYPE_COMMIT) {
if (!quiet)
error("Object %s is a %s, not a commit",
sha1_to_hex(sha1), obj->type);
sha1_to_hex(sha1), typename(obj->type));
return NULL;
}
return (struct commit *) obj;
Expand All @@ -86,11 +86,11 @@ struct commit *lookup_commit(const unsigned char *sha1)
if (!obj) {
struct commit *ret = xcalloc(1, sizeof(struct commit));
created_object(sha1, &ret->object);
ret->object.type = commit_type;
ret->object.type = TYPE_COMMIT;
return ret;
}
if (!obj->type)
obj->type = commit_type;
obj->type = TYPE_COMMIT;
return check_commit(obj, sha1, 0);
}

Expand Down
2 changes: 1 addition & 1 deletion describe.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static int get_name(const char *path, const unsigned char *sha1)
* Otherwise only annotated tags are used.
*/
if (!strncmp(path, "refs/tags/", 10)) {
if (object->type == tag_type)
if (object->type == TYPE_TAG)
prio = 2;
else
prio = 1;
Expand Down
10 changes: 5 additions & 5 deletions fetch-pack.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static int rev_list_insert_ref(const char *path, const unsigned char *sha1)
{
struct object *o = deref_tag(parse_object(sha1), path, 0);

if (o && o->type == commit_type)
if (o && o->type == TYPE_COMMIT)
rev_list_push((struct commit *)o, SEEN);

return 0;
Expand Down Expand Up @@ -251,14 +251,14 @@ static int mark_complete(const char *path, const unsigned char *sha1)
{
struct object *o = parse_object(sha1);

while (o && o->type == tag_type) {
while (o && o->type == TYPE_TAG) {
struct tag *t = (struct tag *) o;
if (!t->tagged)
break; /* broken repository */
o->flags |= COMPLETE;
o = parse_object(t->tagged->sha1);
}
if (o && o->type == commit_type) {
if (o && o->type == TYPE_COMMIT) {
struct commit *commit = (struct commit *)o;
commit->object.flags |= COMPLETE;
insert_by_date(commit, &complete);
Expand Down Expand Up @@ -352,7 +352,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
* in sync with the other side at some time after
* that (it is OK if we guess wrong here).
*/
if (o->type == commit_type) {
if (o->type == TYPE_COMMIT) {
struct commit *commit = (struct commit *)o;
if (!cutoff || cutoff < commit->date)
cutoff = commit->date;
Expand All @@ -371,7 +371,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
struct object *o = deref_tag(lookup_object(ref->old_sha1),
NULL, 0);

if (!o || o->type != commit_type || !(o->flags & COMPLETE))
if (!o || o->type != TYPE_COMMIT || !(o->flags & COMPLETE))
continue;

if (!(o->flags & SEEN)) {
Expand Down
14 changes: 6 additions & 8 deletions fetch.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,27 +118,27 @@ static struct object_list **process_queue_end = &process_queue;

static int process_object(struct object *obj)
{
if (obj->type == commit_type) {
if (obj->type == TYPE_COMMIT) {
if (process_commit((struct commit *)obj))
return -1;
return 0;
}
if (obj->type == tree_type) {
if (obj->type == TYPE_TREE) {
if (process_tree((struct tree *)obj))
return -1;
return 0;
}
if (obj->type == blob_type) {
if (obj->type == TYPE_BLOB) {
return 0;
}
if (obj->type == tag_type) {
if (obj->type == TYPE_TAG) {
if (process_tag((struct tag *)obj))
return -1;
return 0;
}
return error("Unable to determine requirements "
"of type %s for %s",
obj->type, sha1_to_hex(obj->sha1));
typename(obj->type), sha1_to_hex(obj->sha1));
}

static int process(struct object *obj)
Expand Down Expand Up @@ -179,9 +179,7 @@ static int loop(void)
*/
if (! (obj->flags & TO_SCAN)) {
if (fetch(obj->sha1)) {
report_missing(obj->type
? obj->type
: "object", obj->sha1);
report_missing(typename(obj->type), obj->sha1);
return -1;
}
}
Expand Down
26 changes: 13 additions & 13 deletions fsck-objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ static void objreport(struct object *obj, const char *severity,
const char *err, va_list params)
{
fprintf(stderr, "%s in %s %s: ",
severity, obj->type, sha1_to_hex(obj->sha1));
severity, typename(obj->type), sha1_to_hex(obj->sha1));
vfprintf(stderr, err, params);
fputs("\n", stderr);
}
Expand Down Expand Up @@ -74,7 +74,7 @@ static void check_connectivity(void)
; /* it is in pack */
else
printf("missing %s %s\n",
obj->type, sha1_to_hex(obj->sha1));
typename(obj->type), sha1_to_hex(obj->sha1));
continue;
}

Expand All @@ -87,20 +87,20 @@ static void check_connectivity(void)
(has_sha1_file(ref->sha1)))
continue;
printf("broken link from %7s %s\n",
obj->type, sha1_to_hex(obj->sha1));
typename(obj->type), sha1_to_hex(obj->sha1));
printf(" to %7s %s\n",
ref->type, sha1_to_hex(ref->sha1));
typename(ref->type), sha1_to_hex(ref->sha1));
}
}

if (show_unreachable && !(obj->flags & REACHABLE)) {
printf("unreachable %s %s\n",
obj->type, sha1_to_hex(obj->sha1));
typename(obj->type), sha1_to_hex(obj->sha1));
continue;
}

if (!obj->used) {
printf("dangling %s %s\n", obj->type,
printf("dangling %s %s\n", typename(obj->type),
sha1_to_hex(obj->sha1));
}
}
Expand Down Expand Up @@ -282,7 +282,7 @@ static int fsck_tag(struct tag *tag)
if (!show_tags)
return 0;

printf("tagged %s %s", tagged->type, sha1_to_hex(tagged->sha1));
printf("tagged %s %s", typename(tagged->type), sha1_to_hex(tagged->sha1));
printf(" (%s) in %s\n", tag->tag, sha1_to_hex(tag->object.sha1));
return 0;
}
Expand All @@ -295,16 +295,16 @@ static int fsck_sha1(unsigned char *sha1)
if (obj->flags & SEEN)
return 0;
obj->flags |= SEEN;
if (obj->type == blob_type)
if (obj->type == TYPE_BLOB)
return 0;
if (obj->type == tree_type)
if (obj->type == TYPE_TREE)
return fsck_tree((struct tree *) obj);
if (obj->type == commit_type)
if (obj->type == TYPE_COMMIT)
return fsck_commit((struct commit *) obj);
if (obj->type == tag_type)
if (obj->type == TYPE_TAG)
return fsck_tag((struct tag *) obj);
/* By now, parse_object() would've returned NULL instead. */
return objerror(obj, "unknown type '%s' (internal fsck error)", obj->type);
return objerror(obj, "unknown type '%d' (internal fsck error)", obj->type);
}

/*
Expand Down Expand Up @@ -470,7 +470,7 @@ static int fsck_cache_tree(struct cache_tree *it)
}
mark_reachable(obj, REACHABLE);
obj->used = 1;
if (obj->type != tree_type)
if (obj->type != TYPE_TREE)
err |= objerror(obj, "non-tree in cache-tree");
}
for (i = 0; i < it->subtree_nr; i++)
Expand Down
12 changes: 6 additions & 6 deletions http-push.c
Original file line number Diff line number Diff line change
Expand Up @@ -1773,16 +1773,16 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock)

if (obj->flags & (UNINTERESTING | SEEN))
continue;
if (obj->type == tag_type) {
if (obj->type == TYPE_TAG) {
obj->flags |= SEEN;
p = add_object(obj, p, NULL, name);
continue;
}
if (obj->type == tree_type) {
if (obj->type == TYPE_TREE) {
p = process_tree((struct tree *)obj, p, NULL, name);
continue;
}
if (obj->type == blob_type) {
if (obj->type == TYPE_BLOB) {
p = process_blob((struct blob *)obj, p, NULL, name);
continue;
}
Expand Down Expand Up @@ -1949,12 +1949,12 @@ static int ref_newer(const unsigned char *new_sha1,
* old. Otherwise we require --force.
*/
o = deref_tag(parse_object(old_sha1), NULL, 0);
if (!o || o->type != commit_type)
if (!o || o->type != TYPE_COMMIT)
return 0;
old = (struct commit *) o;

o = deref_tag(parse_object(new_sha1), NULL, 0);
if (!o || o->type != commit_type)
if (!o || o->type != TYPE_COMMIT)
return 0;
new = (struct commit *) o;

Expand Down Expand Up @@ -2033,7 +2033,7 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
fwrite_buffer(ref_info, 1, len, buf);
free(ref_info);

if (o->type == tag_type) {
if (o->type == TYPE_TAG) {
o = deref_tag(o, ls->dentry_name, 0);
if (o) {
len = strlen(ls->dentry_name) + 45;
Expand Down
6 changes: 3 additions & 3 deletions name-rev.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@ static int name_ref(const char *path, const unsigned char *sha1)
if (tags_only && strncmp(path, "refs/tags/", 10))
return 0;

while (o && o->type == tag_type) {
while (o && o->type == TYPE_TAG) {
struct tag *t = (struct tag *) o;
if (!t->tagged)
break; /* broken repository */
o = parse_object(t->tagged->sha1);
deref = 1;
}
if (o && o->type == commit_type) {
if (o && o->type == TYPE_COMMIT) {
struct commit *commit = (struct commit *)o;

if (!strncmp(path, "refs/heads/", 11))
Expand Down Expand Up @@ -167,7 +167,7 @@ int main(int argc, char **argv)
}

o = deref_tag(parse_object(sha1), *argv, 0);
if (!o || o->type != commit_type) {
if (!o || o->type != TYPE_COMMIT) {
fprintf(stderr, "Could not get commit for %s. Skipping.\n",
*argv);
continue;
Expand Down
8 changes: 6 additions & 2 deletions object.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ struct object **objs;
static int nr_objs;
int obj_allocs;

const char *type_names[] = {
"none", "blob", "tree", "commit", "bad"
};

int track_object_refs = 0;

static int hashtable_index(const unsigned char *sha1)
Expand Down Expand Up @@ -50,7 +54,7 @@ void created_object(const unsigned char *sha1, struct object *obj)

obj->parsed = 0;
memcpy(obj->sha1, sha1, 20);
obj->type = NULL;
obj->type = TYPE_NONE;
obj->refs = NULL;
obj->used = 0;

Expand Down Expand Up @@ -179,7 +183,7 @@ struct object *lookup_unknown_object(const unsigned char *sha1)
if (!obj) {
union any_object *ret = xcalloc(1, sizeof(*ret));
created_object(sha1, &ret->object);
ret->object.type = NULL;
ret->object.type = TYPE_NONE;
return &ret->object;
}
return obj;
Expand Down
Loading

0 comments on commit 885a86a

Please sign in to comment.