git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/4] mark_parents_uninteresting(): replace list with stack

From
Jeff King <peff@peff.net>
Date
May 11, 2018, 18:02 UTC
Message-ID
<20180511180227.GC12543@sigill.intra.peff.net>
In-Reply-To
<20180511180029.GA11290@sigill.intra.peff.net>

The mark_parents_uninteresting() function uses two loops: an outer one to process our queue of pending parents, and an inner one to process first-parent chains. This is a clever optimization from 941ba8db57 (Eliminate recursion in setting/clearing marks in commit list, 2012-01-14) to limit the number of linked-list allocations when following single-parent chains.

Unfortunately, this makes the result a little hard to read. Let's replace the list with a stack. Then we don't have to worry about doing this double-loop optimization, as we'll just reuse the top element of the stack as we pop/push.

Signed-off-by: Jeff King <peff@peff.net>
---
The diff makes a lot more sense with "-w".
 revision.c | 67 +++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 43 insertions(+), 24 deletions(-)
diff --git a/revision.c b/revision.c
index cee4f3a4b4..89ff9a99ce 100644
--- a/revision.c
+++ b/revision.c
@@ -92,38 +92,57 @@ void mark_tree_uninteresting(struct tree *tree)
 	mark_tree_contents_uninteresting(tree);
 }
 
-void mark_parents_uninteresting(struct commit *commit)
+struct commit_stack {
+	struct commit **items;
+	size_t nr, alloc;
+};
+#define COMMIT_STACK_INIT { NULL, 0, 0 }
+
+static void commit_stack_push(struct commit_stack *stack, struct commit *commit)
 {
-	struct commit_list *parents = NULL, *l;
+	ALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);
+	stack->items[stack->nr++] = commit;
+}
 
-	for (l = commit->parents; l; l = l->next)
-		commit_list_insert(l->item, &parents);
+static struct commit *commit_stack_pop(struct commit_stack *stack)
+{
+	return stack->nr ? stack->items[--stack->nr] : NULL;
+}
 
-	while (parents) {
-		struct commit *commit = pop_commit(&parents);
+static void commit_stack_clear(struct commit_stack *stack)
+{
+	FREE_AND_NULL(stack->items);
+	stack->nr = stack->alloc = 0;
+}
 
-		while (commit) {
-			if (commit->object.flags & UNINTERESTING)
-				break;
+void mark_parents_uninteresting(struct commit *commit)
+{
+	struct commit_stack pending = COMMIT_STACK_INIT;
+	struct commit_list *l;
 
-			commit->object.flags |= UNINTERESTING;
+	for (l = commit->parents; l; l = l->next)
+		commit_stack_push(&pending, l->item);
 
-			/*
-			 * Normally we haven't parsed the parent
-			 * yet, so we won't have a parent of a parent
-			 * here. However, it may turn out that we've
-			 * reached this commit some other way (where it
-			 * wasn't uninteresting), in which case we need
-			 * to mark its parents recursively too..
-			 */
-			if (!commit->parents)
-				break;
+	while (pending.nr > 0) {
+		struct commit *commit = commit_stack_pop(&pending);
 
-			for (l = commit->parents->next; l; l = l->next)
-				commit_list_insert(l->item, &parents);
-			commit = commit->parents->item;
-		}
+		if (commit->object.flags & UNINTERESTING)
+			return;
+		commit->object.flags |= UNINTERESTING;
+
+		/*
+		 * Normally we haven't parsed the parent
+		 * yet, so we won't have a parent of a parent
+		 * here. However, it may turn out that we've
+		 * reached this commit some other way (where it
+		 * wasn't uninteresting), in which case we need
+		 * to mark its parents recursively too..
+		 */
+		for (l = commit->parents; l; l = l->next)
+			commit_stack_push(&pending, l->item);
 	}
+
+	commit_stack_clear(&pending);
 }
 
 static void add_pending_object_with_path(struct rev_info *revs,
-- 
2.17.0.988.gec4b43b3e5
Previous: Junio C HamanoNext: Jeff King
Message 5 of 11 in “a few mark_parents_uninteresting cleanups”
  1. 0/4 a few mark_parents_uninteresting cleanupsJeff King, May 11, 2018
  2. 1/4 mark_tree_contents_uninteresting(): drop missing object checkJeff King, May 11, 2018
  3. 2/4 mark_parents_uninteresting(): drop missing object checkJeff King, May 11, 2018
  4. Junio C HamanoMay 13, 2018
  5. 3/4 mark_parents_uninteresting(): replace list with stackJeff King, May 11, 2018
  6. 4/4 mark_parents_uninteresting(): avoid most allocationJeff King, May 11, 2018
  7. Derrick StoleeMay 14, 2018
  8. Jeff KingMay 14, 2018
  9. Derrick StoleeMay 14, 2018
  10. Jeff KingMay 14, 2018
  11. Derrick StoleeMay 14, 2018

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.