Skip to content

Commit 30598cc

Browse files
rscharfegitster
authored andcommitted
describe: use oidset in finish_depth_computation()
Depth computation can end early if all remaining commits are flagged. The current code determines if that's the case by checking all queue items each time it dequeues a flagged commit. This can cause quadratic complexity. We could simply count the flagged items in the queue and then update that number as we add and remove items. That would provide a general speedup, but leave one case where we have to scan the whole queue: When we flag a previously seen, but unflagged commit. It could be on the queue and then we'd have to decrease our count. We could dedicate an object flag to track queue membership, but that would leave less for candidate tags, affecting the results. So use a hash table, specifically an oidset of commit hashes, to track that. This avoids quadratic behaviour in all cases and provides a nice performance boost over the previous commit, 08bb69d (describe: use prio_queue_replace(), 2025-08-03): Benchmark 1: ./git_08bb69d70f describe $(git rev-list v2.41.0..v2.47.0) Time (mean ± σ): 855.3 ms ± 1.3 ms [User: 790.8 ms, System: 49.9 ms] Range (min … max): 853.7 ms … 857.8 ms 10 runs Benchmark 2: ./git describe $(git rev-list v2.41.0..v2.47.0) Time (mean ± σ): 610.8 ms ± 1.7 ms [User: 546.9 ms, System: 49.3 ms] Range (min … max): 608.9 ms … 613.3 ms 10 runs Summary ./git describe $(git rev-list v2.41.0..v2.47.0) ran 1.40 ± 0.00 times faster than ./git_08bb69d70f describe $(git rev-list v2.41.0..v2.47.0) Helped-by: Jeff King <[email protected]> Signed-off-by: René Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 08bb69d commit 30598cc

File tree

1 file changed

+22
-12
lines changed

1 file changed

+22
-12
lines changed

builtin/describe.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "commit-slab.h"
2525
#include "wildmatch.h"
2626
#include "prio-queue.h"
27+
#include "oidset.h"
2728

2829
#define MAX_TAGS (FLAG_BITS - 1)
2930
#define DEFAULT_CANDIDATES 10
@@ -286,38 +287,47 @@ static void lazy_queue_clear(struct lazy_queue *queue)
286287
queue->get_pending = false;
287288
}
288289

289-
static bool all_have_flag(const struct lazy_queue *queue, unsigned flag)
290+
static unsigned long finish_depth_computation(struct lazy_queue *queue,
291+
struct possible_tag *best)
290292
{
293+
unsigned long seen_commits = 0;
294+
struct oidset unflagged = OIDSET_INIT;
295+
291296
for (size_t i = queue->get_pending ? 1 : 0; i < queue->queue.nr; i++) {
292297
struct commit *commit = queue->queue.array[i].data;
293-
if (!(commit->object.flags & flag))
294-
return false;
298+
if (!(commit->object.flags & best->flag_within))
299+
oidset_insert(&unflagged, &commit->object.oid);
295300
}
296-
return true;
297-
}
298301

299-
static unsigned long finish_depth_computation(struct lazy_queue *queue,
300-
struct possible_tag *best)
301-
{
302-
unsigned long seen_commits = 0;
303302
while (!lazy_queue_empty(queue)) {
304303
struct commit *c = lazy_queue_get(queue);
305304
struct commit_list *parents = c->parents;
306305
seen_commits++;
307306
if (c->object.flags & best->flag_within) {
308-
if (all_have_flag(queue, best->flag_within))
307+
if (!oidset_size(&unflagged))
309308
break;
310-
} else
309+
} else {
310+
oidset_remove(&unflagged, &c->object.oid);
311311
best->depth++;
312+
}
312313
while (parents) {
314+
unsigned seen, flag_before, flag_after;
313315
struct commit *p = parents->item;
314316
repo_parse_commit(the_repository, p);
315-
if (!(p->object.flags & SEEN))
317+
seen = p->object.flags & SEEN;
318+
if (!seen)
316319
lazy_queue_put(queue, p);
320+
flag_before = p->object.flags & best->flag_within;
317321
p->object.flags |= c->object.flags;
322+
flag_after = p->object.flags & best->flag_within;
323+
if (!seen && !flag_after)
324+
oidset_insert(&unflagged, &p->object.oid);
325+
if (seen && !flag_before && flag_after)
326+
oidset_remove(&unflagged, &p->object.oid);
318327
parents = parents->next;
319328
}
320329
}
330+
oidset_clear(&unflagged);
321331
return seen_commits;
322332
}
323333

0 commit comments

Comments
 (0)