From 136f2e548a34f1f504b0f062f87ddf33e8d6e83b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 29 May 2006 12:16:12 -0700 Subject: Make "struct tree" contain the pointer to the tree buffer This allows us to avoid allocating information for names etc, because we can just use the information from the tree buffer directly. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-rev-list.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'builtin-rev-list.c') diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 5277d3cf12..72c1549c70 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -136,10 +136,11 @@ static struct object_list **process_tree(struct tree *tree, p = process_tree(entry->item.tree, p, &me, entry->name); else p = process_blob(entry->item.blob, p, &me, entry->name); - free(entry->name); free(entry); entry = next; } + free(tree->buffer); + tree->buffer = NULL; return p; } -- cgit v1.2.3 From 3a7c352bd0ecac4b4c96c0995d61de9ef8d814f9 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 29 May 2006 12:16:46 -0700 Subject: Make "tree_entry" have a SHA1 instead of a union of object pointers This is preparatory work for further cleanups, where we try to make tree_entry look more like the more efficient tree-walk descriptor. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-rev-list.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'builtin-rev-list.c') diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 72c1549c70..94f520b908 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -133,9 +133,9 @@ static struct object_list **process_tree(struct tree *tree, while (entry) { struct tree_entry_list *next = entry->next; if (entry->directory) - p = process_tree(entry->item.tree, p, &me, entry->name); + p = process_tree(lookup_tree(entry->sha1), p, &me, entry->name); else - p = process_blob(entry->item.blob, p, &me, entry->name); + p = process_blob(lookup_blob(entry->sha1), p, &me, entry->name); free(entry); entry = next; } -- cgit v1.2.3 From 2d9c58c69d1bab601e67b036d0546e85abcee7eb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 29 May 2006 12:18:33 -0700 Subject: Remove "tree->entries" tree-entry list from tree parser Instead, just use the tree buffer directly, and use the tree-walk infrastructure to walk the buffers instead of the tree-entry list. The tree-entry list is inefficient, and generates tons of small allocations for no good reason. The tree-walk infrastructure is generally no harder to use than following a linked list, and allows us to do most tree parsing in-place. Some programs still use the old tree-entry lists, and are a bit painful to convert without major surgery. For them we have a helper function that creates a temporary tree-entry list on demand. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-rev-list.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'builtin-rev-list.c') diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 94f520b908..6e2b898cca 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -113,7 +113,7 @@ static struct object_list **process_tree(struct tree *tree, const char *name) { struct object *obj = &tree->object; - struct tree_entry_list *entry; + struct tree_desc desc; struct name_path me; if (!revs.tree_objects) @@ -128,16 +128,22 @@ static struct object_list **process_tree(struct tree *tree, me.up = path; me.elem = name; me.elem_len = strlen(name); - entry = tree->entries; - tree->entries = NULL; - while (entry) { - struct tree_entry_list *next = entry->next; - if (entry->directory) - p = process_tree(lookup_tree(entry->sha1), p, &me, entry->name); + + desc.buf = tree->buffer; + desc.size = tree->size; + + while (desc.size) { + unsigned mode; + const char *name; + const unsigned char *sha1; + + sha1 = tree_entry_extract(&desc, &name, &mode); + update_tree_entry(&desc); + + if (S_ISDIR(mode)) + p = process_tree(lookup_tree(sha1), p, &me, name); else - p = process_blob(lookup_blob(entry->sha1), p, &me, entry->name); - free(entry); - entry = next; + p = process_blob(lookup_blob(sha1), p, &me, name); } free(tree->buffer); tree->buffer = NULL; -- cgit v1.2.3 From 4c068a983150b740c3fcf6a33f342ac923abd3f4 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 30 May 2006 09:45:45 -0700 Subject: tree_entry(): new tree-walking helper function This adds a "tree_entry()" function that combines the common operation of doing a "tree_entry_extract()" + "update_tree_entry()". It also has a simplified calling convention, designed for simple loops that traverse over a whole tree: the arguments are pointers to the tree descriptor and a name_entry structure to fill in, and it returns a boolean "true" if there was an entry left to be gotten in the tree. This allows tree traversal with struct tree_desc desc; struct name_entry entry; desc.buf = tree->buffer; desc.size = tree->size; while (tree_entry(&desc, &entry) { ... use "entry.{path, sha1, mode, pathlen}" ... } which is not only shorter than writing it out in full, it's hopefully less error prone too. [ It's actually a tad faster too - we don't need to recalculate the entry pathlength in both extract and update, but need to do it only once. Also, some callers can avoid doing a "strlen()" on the result, since it's returned as part of the name_entry structure. However, by now we're talking just 1% speedup on "git-rev-list --objects --all", and we're definitely at the point where tree walking is no longer the issue any more. ] NOTE! Not everybody wants to use this new helper function, since some of the tree walkers very much on purpose do the descriptor update separately from the entry extraction. So the "extract + update" sequence still remains as the core sequence, this is just a simplified interface. We should probably add a silly two-line inline helper function for initializing the descriptor from the "struct tree" too, just to cut down on the noise from that common "desc" initializer. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-rev-list.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'builtin-rev-list.c') diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 6e2b898cca..17c04b962d 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -114,6 +114,7 @@ static struct object_list **process_tree(struct tree *tree, { struct object *obj = &tree->object; struct tree_desc desc; + struct name_entry entry; struct name_path me; if (!revs.tree_objects) @@ -132,18 +133,11 @@ static struct object_list **process_tree(struct tree *tree, desc.buf = tree->buffer; desc.size = tree->size; - while (desc.size) { - unsigned mode; - const char *name; - const unsigned char *sha1; - - sha1 = tree_entry_extract(&desc, &name, &mode); - update_tree_entry(&desc); - - if (S_ISDIR(mode)) - p = process_tree(lookup_tree(sha1), p, &me, name); + while (tree_entry(&desc, &entry)) { + if (S_ISDIR(entry.mode)) + p = process_tree(lookup_tree(entry.sha1), p, &me, name); else - p = process_blob(lookup_blob(sha1), p, &me, name); + p = process_blob(lookup_blob(entry.sha1), p, &me, name); } free(tree->buffer); tree->buffer = NULL; -- cgit v1.2.3