Skip to content

Commit 8702b30

Browse files
peffgitster
authored andcommitted
mark_parents_uninteresting(): avoid most allocation
Commit 941ba8d (Eliminate recursion in setting/clearing marks in commit list, 2012-01-14) used a clever double-loop to avoid allocations for single-parent chains of history. However, it did so only when following parents of parents (which was an uncommon case), and _always_ incurred at least one allocation to populate the list of pending parents in the first place. We can turn this into zero-allocation in the common case by iterating directly over the initial parent list, and then following up on any pending items we might have discovered. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 43fc643 commit 8702b30

File tree

1 file changed

+25
-19
lines changed

1 file changed

+25
-19
lines changed

revision.c

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -114,32 +114,38 @@ static void commit_stack_clear(struct commit_stack *stack)
114114
stack->nr = stack->alloc = 0;
115115
}
116116

117-
void mark_parents_uninteresting(struct commit *commit)
117+
static void mark_one_parent_uninteresting(struct commit *commit,
118+
struct commit_stack *pending)
118119
{
119-
struct commit_stack pending = COMMIT_STACK_INIT;
120120
struct commit_list *l;
121121

122+
if (commit->object.flags & UNINTERESTING)
123+
return;
124+
commit->object.flags |= UNINTERESTING;
125+
126+
/*
127+
* Normally we haven't parsed the parent
128+
* yet, so we won't have a parent of a parent
129+
* here. However, it may turn out that we've
130+
* reached this commit some other way (where it
131+
* wasn't uninteresting), in which case we need
132+
* to mark its parents recursively too..
133+
*/
122134
for (l = commit->parents; l; l = l->next)
123-
commit_stack_push(&pending, l->item);
135+
commit_stack_push(pending, l->item);
136+
}
124137

125-
while (pending.nr > 0) {
126-
struct commit *commit = commit_stack_pop(&pending);
138+
void mark_parents_uninteresting(struct commit *commit)
139+
{
140+
struct commit_stack pending = COMMIT_STACK_INIT;
141+
struct commit_list *l;
127142

128-
if (commit->object.flags & UNINTERESTING)
129-
return;
130-
commit->object.flags |= UNINTERESTING;
143+
for (l = commit->parents; l; l = l->next)
144+
mark_one_parent_uninteresting(l->item, &pending);
131145

132-
/*
133-
* Normally we haven't parsed the parent
134-
* yet, so we won't have a parent of a parent
135-
* here. However, it may turn out that we've
136-
* reached this commit some other way (where it
137-
* wasn't uninteresting), in which case we need
138-
* to mark its parents recursively too..
139-
*/
140-
for (l = commit->parents; l; l = l->next)
141-
commit_stack_push(&pending, l->item);
142-
}
146+
while (pending.nr > 0)
147+
mark_one_parent_uninteresting(commit_stack_pop(&pending),
148+
&pending);
143149

144150
commit_stack_clear(&pending);
145151
}

0 commit comments

Comments
 (0)