commit-reach: deduplicate queue entries in paint_down_to_common
paint_down_to_common() can enqueue the same commit multiple times when it is reached through different parents with different flag combinations. Add an ENQUEUED flag to track whether a commit is currently in the priority queue, and skip it if already present. Introduce prio_queue_put_dedup() and prio_queue_get_dedup() wrappers that manage the ENQUEUED flag on enqueue and dequeue. This change is performance-neutral on its own: the O(n) queue_has_nonstale() scan still dominates the per-iteration cost. However, the deduplication guarantee (each commit appears in the queue at most once) is a prerequisite for the next commit, which replaces that scan with O(1) tracking. Signed-off-by: Kristofer Karlsson <krka@spotify.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>main
parent
85a30b5b26
commit
f767dae3e6
|
|
@ -17,8 +17,9 @@
|
|||
#define PARENT2 (1u<<17)
|
||||
#define STALE (1u<<18)
|
||||
#define RESULT (1u<<19)
|
||||
#define ENQUEUED (1u<<20)
|
||||
|
||||
static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
|
||||
static const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT | ENQUEUED);
|
||||
|
||||
static int compare_commits_by_gen(const void *_a, const void *_b)
|
||||
{
|
||||
|
|
@ -39,6 +40,22 @@ static int compare_commits_by_gen(const void *_a, const void *_b)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void prio_queue_put_dedup(struct prio_queue *queue, struct commit *c)
|
||||
{
|
||||
if (c->object.flags & ENQUEUED)
|
||||
return;
|
||||
c->object.flags |= ENQUEUED;
|
||||
prio_queue_put(queue, c);
|
||||
}
|
||||
|
||||
static struct commit *prio_queue_get_dedup(struct prio_queue *queue)
|
||||
{
|
||||
struct commit *commit = prio_queue_get(queue);
|
||||
if (commit)
|
||||
commit->object.flags &= ~ENQUEUED;
|
||||
return commit;
|
||||
}
|
||||
|
||||
static int queue_has_nonstale(struct prio_queue *queue)
|
||||
{
|
||||
for (size_t i = 0; i < queue->nr; i++) {
|
||||
|
|
@ -70,15 +87,15 @@ static int paint_down_to_common(struct repository *r,
|
|||
commit_list_append(one, result);
|
||||
return 0;
|
||||
}
|
||||
prio_queue_put(&queue, one);
|
||||
prio_queue_put_dedup(&queue, one);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
twos[i]->object.flags |= PARENT2;
|
||||
prio_queue_put(&queue, twos[i]);
|
||||
prio_queue_put_dedup(&queue, twos[i]);
|
||||
}
|
||||
|
||||
while (queue_has_nonstale(&queue)) {
|
||||
struct commit *commit = prio_queue_get(&queue);
|
||||
struct commit *commit = prio_queue_get_dedup(&queue);
|
||||
struct commit_list *parents;
|
||||
int flags;
|
||||
timestamp_t generation = commit_graph_generation(commit);
|
||||
|
|
@ -124,7 +141,7 @@ static int paint_down_to_common(struct repository *r,
|
|||
oid_to_hex(&p->object.oid));
|
||||
}
|
||||
p->object.flags |= flags;
|
||||
prio_queue_put(&queue, p);
|
||||
prio_queue_put_dedup(&queue, p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue