Skip to content

Commit 3c775ab

Browse files
committed
Merge branch 'kk/prio-queue-get-put-fusion'
The lazy priority queue optimization pattern (deferring actual removal in 'prio_queue_get()' to allow get+put fusion) has been folded directly into 'prio_queue' itself, speeding up commit traversal workflows and simplifying callers. * kk/prio-queue-get-put-fusion: prio-queue: fold lazy_queue into prio_queue for automatic get+put fusion prio-queue: rename .nr to .nr_ and add accessor helpers
2 parents 6d6939a + 9f75e7a commit 3c775ab

16 files changed

Lines changed: 139 additions & 177 deletions

builtin/describe.c

Lines changed: 16 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -251,56 +251,19 @@ static int compare_pt(const void *a_, const void *b_)
251251
return 0;
252252
}
253253

254-
struct lazy_queue {
255-
struct prio_queue queue;
256-
bool get_pending;
257-
};
258-
259-
#define LAZY_QUEUE_INIT { { compare_commits_by_commit_date }, false }
260-
261-
static void *lazy_queue_get(struct lazy_queue *queue)
262-
{
263-
if (queue->get_pending)
264-
prio_queue_get(&queue->queue);
265-
else
266-
queue->get_pending = true;
267-
return prio_queue_peek(&queue->queue);
268-
}
269-
270-
static void lazy_queue_put(struct lazy_queue *queue, void *thing)
271-
{
272-
if (queue->get_pending)
273-
prio_queue_replace(&queue->queue, thing);
274-
else
275-
prio_queue_put(&queue->queue, thing);
276-
queue->get_pending = false;
277-
}
278-
279-
static bool lazy_queue_empty(const struct lazy_queue *queue)
280-
{
281-
return queue->queue.nr == (queue->get_pending ? 1 : 0);
282-
}
283-
284-
static void lazy_queue_clear(struct lazy_queue *queue)
285-
{
286-
clear_prio_queue(&queue->queue);
287-
queue->get_pending = false;
288-
}
289-
290-
static unsigned long finish_depth_computation(struct lazy_queue *queue,
254+
static unsigned long finish_depth_computation(struct prio_queue *queue,
291255
struct possible_tag *best)
292256
{
293257
unsigned long seen_commits = 0;
294258
struct oidset unflagged = OIDSET_INIT;
259+
struct commit *c;
295260

296-
for (size_t i = queue->get_pending ? 1 : 0; i < queue->queue.nr; i++) {
297-
struct commit *commit = queue->queue.array[i].data;
298-
if (!(commit->object.flags & best->flag_within))
299-
oidset_insert(&unflagged, &commit->object.oid);
261+
prio_queue_for_each(queue, c) {
262+
if (!(c->object.flags & best->flag_within))
263+
oidset_insert(&unflagged, &c->object.oid);
300264
}
301265

302-
while (!lazy_queue_empty(queue)) {
303-
struct commit *c = lazy_queue_get(queue);
266+
while ((c = prio_queue_get(queue))) {
304267
struct commit_list *parents = c->parents;
305268
seen_commits++;
306269
if (c->object.flags & best->flag_within) {
@@ -316,7 +279,7 @@ static unsigned long finish_depth_computation(struct lazy_queue *queue,
316279
repo_parse_commit(the_repository, p);
317280
seen = p->object.flags & SEEN;
318281
if (!seen)
319-
lazy_queue_put(queue, p);
282+
prio_queue_put(queue, p);
320283
flag_before = p->object.flags & best->flag_within;
321284
p->object.flags |= c->object.flags;
322285
flag_after = p->object.flags & best->flag_within;
@@ -364,8 +327,8 @@ static void append_suffix(int depth, const struct object_id *oid, struct strbuf
364327

365328
static void describe_commit(struct commit *cmit, struct strbuf *dst)
366329
{
367-
struct commit *gave_up_on = NULL;
368-
struct lazy_queue queue = LAZY_QUEUE_INIT;
330+
struct commit *c, *gave_up_on = NULL;
331+
struct prio_queue queue = { compare_commits_by_commit_date };
369332
struct commit_name *n;
370333
struct possible_tag all_matches[MAX_TAGS];
371334
unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
@@ -407,9 +370,8 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
407370
}
408371

409372
cmit->object.flags = SEEN;
410-
lazy_queue_put(&queue, cmit);
411-
while (!lazy_queue_empty(&queue)) {
412-
struct commit *c = lazy_queue_get(&queue);
373+
prio_queue_put(&queue, cmit);
374+
while ((c = prio_queue_get(&queue))) {
413375
struct commit_list *parents = c->parents;
414376
struct commit_name **slot;
415377

@@ -443,7 +405,7 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
443405
t->depth++;
444406
}
445407
/* Stop if last remaining path already covered by best candidate(s) */
446-
if (annotated_cnt && lazy_queue_empty(&queue)) {
408+
if (annotated_cnt && !prio_queue_size(&queue)) {
447409
int best_depth = INT_MAX;
448410
unsigned best_within = 0;
449411
for (cur_match = 0; cur_match < match_cnt; cur_match++) {
@@ -466,7 +428,7 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
466428
struct commit *p = parents->item;
467429
repo_parse_commit(the_repository, p);
468430
if (!(p->object.flags & SEEN))
469-
lazy_queue_put(&queue, p);
431+
prio_queue_put(&queue, p);
470432
p->object.flags |= c->object.flags;
471433
parents = parents->next;
472434

@@ -481,7 +443,7 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
481443
strbuf_add_unique_abbrev(dst, cmit_oid, abbrev);
482444
if (suffix)
483445
strbuf_addstr(dst, suffix);
484-
lazy_queue_clear(&queue);
446+
clear_prio_queue(&queue);
485447
return;
486448
}
487449
if (unannotated_cnt)
@@ -497,11 +459,11 @@ static void describe_commit(struct commit *cmit, struct strbuf *dst)
497459
QSORT(all_matches, match_cnt, compare_pt);
498460

499461
if (gave_up_on) {
500-
lazy_queue_put(&queue, gave_up_on);
462+
prio_queue_put(&queue, gave_up_on);
501463
seen_commits--;
502464
}
503465
seen_commits += finish_depth_computation(&queue, &all_matches[0]);
504-
lazy_queue_clear(&queue);
466+
clear_prio_queue(&queue);
505467

506468
if (debug) {
507469
static int label_width = -1;

builtin/last-modified.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ static void process_parent(struct last_modified *lm,
344344
static int last_modified_run(struct last_modified *lm)
345345
{
346346
int max_count, queue_popped = 0;
347+
struct commit *c, *n;
347348
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
348349
struct prio_queue not_queue = { compare_commits_by_gen_then_commit_date };
349350
struct commit_list *list;
@@ -389,10 +390,9 @@ static int last_modified_run(struct last_modified *lm)
389390
}
390391
}
391392

392-
while (queue.nr) {
393+
while ((c = prio_queue_get(&queue))) {
393394
int parent_i;
394395
struct commit_list *p;
395-
struct commit *c = prio_queue_get(&queue);
396396
struct bitmap *active_c = active_paths_for(lm, c);
397397

398398
if ((0 <= max_count && max_count < ++queue_popped) ||
@@ -416,9 +416,8 @@ static int last_modified_run(struct last_modified *lm)
416416
*/
417417
repo_parse_commit(lm->rev.repo, c);
418418

419-
while (not_queue.nr) {
419+
while ((n = prio_queue_get(&not_queue))) {
420420
struct commit_list *np;
421-
struct commit *n = prio_queue_get(&not_queue);
422421

423422
repo_parse_commit(lm->rev.repo, n);
424423

builtin/show-branch.c

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,10 @@ static const char *get_color_reset_code(void)
6262

6363
static struct commit *interesting(struct prio_queue *queue)
6464
{
65-
for (size_t i = 0; i < queue->nr; i++) {
66-
struct commit *commit = queue->array[i].data;
67-
if (commit->object.flags & UNINTERESTING)
68-
continue;
69-
return commit;
65+
struct commit *commit;
66+
prio_queue_for_each(queue, commit) {
67+
if (!(commit->object.flags & UNINTERESTING))
68+
return commit;
7069
}
7170
return NULL;
7271
}
@@ -228,17 +227,18 @@ static void join_revs(struct prio_queue *queue,
228227
{
229228
int all_mask = ((1u << (REV_SHIFT + num_rev)) - 1);
230229
int all_revs = all_mask & ~((1u << REV_SHIFT) - 1);
230+
struct commit *commit;
231231

232-
while (queue->nr) {
232+
while ((commit = prio_queue_peek(queue))) {
233233
struct commit_list *parents;
234234
int still_interesting = !!interesting(queue);
235-
struct commit *commit = prio_queue_peek(queue);
236-
bool get_pending = true;
237235
int flags = commit->object.flags & all_mask;
238236

239237
if (!still_interesting && extra <= 0)
240238
break;
241239

240+
prio_queue_get(queue);
241+
242242
mark_seen(commit, seen_p);
243243
if ((flags & all_revs) == all_revs)
244244
flags |= UNINTERESTING;
@@ -254,14 +254,8 @@ static void join_revs(struct prio_queue *queue,
254254
if (mark_seen(p, seen_p) && !still_interesting)
255255
extra--;
256256
p->object.flags |= flags;
257-
if (get_pending)
258-
prio_queue_replace(queue, p);
259-
else
260-
prio_queue_put(queue, p);
261-
get_pending = false;
257+
prio_queue_put(queue, p);
262258
}
263-
if (get_pending)
264-
prio_queue_get(queue);
265259
}
266260

267261
/*

commit-reach.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ void ahead_behind(struct repository *r,
11211121
struct nonstale_queue queue = {
11221122
{ .compare = compare_commits_by_gen_then_commit_date }
11231123
};
1124+
void *entry;
11241125
size_t width = DIV_ROUND_UP(commits_nr, BITS_IN_EWORD);
11251126

11261127
if (!commits_nr || !counts_nr)
@@ -1186,8 +1187,8 @@ void ahead_behind(struct repository *r,
11861187

11871188
/* STALE is used here, PARENT2 is used by insert_no_dup(). */
11881189
repo_clear_commit_marks(r, PARENT2 | STALE);
1189-
for (size_t i = 0; i < queue.pq.nr; i++)
1190-
free_bit_array(queue.pq.array[i].data);
1190+
prio_queue_for_each(&queue.pq, entry)
1191+
free_bit_array(entry);
11911192
clear_bit_arrays(&bit_arrays);
11921193
clear_nonstale_queue(&queue);
11931194
}
@@ -1320,7 +1321,7 @@ int get_branch_base_for_tip(struct repository *r,
13201321
size_t bases_nr)
13211322
{
13221323
int best_index = -1;
1323-
struct commit *branch_point = NULL;
1324+
struct commit *c, *branch_point = NULL;
13241325
struct prio_queue queue = { compare_commits_by_gen_then_commit_date };
13251326
int found_missing_gen = 0;
13261327

@@ -1373,8 +1374,7 @@ int get_branch_base_for_tip(struct repository *r,
13731374
prio_queue_put(&queue, c);
13741375
}
13751376

1376-
while (queue.nr) {
1377-
struct commit *c = prio_queue_get(&queue);
1377+
while ((c = prio_queue_get(&queue))) {
13781378
int best_for_c = get_best(c);
13791379
int best_for_p, positive;
13801380
struct commit *parent;

commit.c

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -782,24 +782,17 @@ void commit_list_sort_by_date(struct commit_list **list)
782782
struct commit *pop_most_recent_commit(struct prio_queue *queue,
783783
unsigned int mark)
784784
{
785-
struct commit *ret = prio_queue_peek(queue);
786-
int get_pending = 1;
785+
struct commit *ret = prio_queue_get(queue);
787786
struct commit_list *parents = ret->parents;
788787

789788
while (parents) {
790789
struct commit *commit = parents->item;
791790
if (!repo_parse_commit(the_repository, commit) && !(commit->object.flags & mark)) {
792791
commit->object.flags |= mark;
793-
if (get_pending)
794-
prio_queue_replace(queue, commit);
795-
else
796-
prio_queue_put(queue, commit);
797-
get_pending = 0;
792+
prio_queue_put(queue, commit);
798793
}
799794
parents = parents->next;
800795
}
801-
if (get_pending)
802-
prio_queue_get(queue);
803796
return ret;
804797
}
805798

fetch-pack.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,8 @@ static int mark_complete_oid(const struct reference *ref, void *cb_data UNUSED)
662662
static void mark_recent_complete_commits(struct fetch_pack_args *args,
663663
timestamp_t cutoff)
664664
{
665-
while (complete.nr) {
666-
struct commit *item = prio_queue_peek(&complete);
665+
struct commit *item;
666+
while ((item = prio_queue_peek(&complete))) {
667667
if (item->date < cutoff)
668668
break;
669669
print_verbose(args, _("Marking %s as complete"),

negotiator/default.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,12 @@ static const struct object_id *get_rev(struct negotiation_state *ns)
113113
unsigned int mark;
114114
struct commit_list *parents;
115115

116-
if (ns->rev_list.nr == 0 || ns->non_common_revs == 0)
116+
if (ns->non_common_revs == 0)
117117
return NULL;
118118

119119
commit = prio_queue_get(&ns->rev_list);
120+
if (!commit)
121+
return NULL;
120122
repo_parse_commit(the_repository, commit);
121123
parents = commit->parents;
122124

negotiator/skipping.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,7 @@ static int push_parent(struct data *data, struct entry *entry,
143143
/*
144144
* Find the existing entry and use it.
145145
*/
146-
for (size_t i = 0; i < data->rev_list.nr; i++) {
147-
parent_entry = data->rev_list.array[i].data;
146+
prio_queue_for_each(&data->rev_list, parent_entry) {
148147
if (parent_entry->commit == to_push)
149148
goto parent_found;
150149
}
@@ -181,10 +180,12 @@ static const struct object_id *get_rev(struct data *data)
181180
struct commit_list *p;
182181
int parent_pushed = 0;
183182

184-
if (data->rev_list.nr == 0 || data->non_common_revs == 0)
183+
if (data->non_common_revs == 0)
185184
return NULL;
186185

187186
entry = prio_queue_get(&data->rev_list);
187+
if (!entry)
188+
return NULL;
188189
commit = entry->commit;
189190
commit->object.flags |= POPPED;
190191
if (!(commit->object.flags & COMMON))
@@ -253,8 +254,9 @@ static void have_sent(struct fetch_negotiator *n, struct commit *c)
253254
static void release(struct fetch_negotiator *n)
254255
{
255256
struct data *data = n->data;
256-
for (size_t i = 0; i < data->rev_list.nr; i++)
257-
free(data->rev_list.array[i].data);
257+
void *entry;
258+
prio_queue_for_each(&data->rev_list, entry)
259+
free(entry);
258260
clear_prio_queue(&data->rev_list);
259261
FREE_AND_NULL(data);
260262
}

object-name.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ static int get_oid_oneline(struct repository *r,
12091209
l->item->object.flags |= ONELINE_SEEN;
12101210
prio_queue_put(&copy, l->item);
12111211
}
1212-
while (copy.nr) {
1212+
while (prio_queue_size(&copy)) {
12131213
const char *p, *buf;
12141214
struct commit *commit;
12151215
int matches;

pack-bitmap-write.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,8 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
636636
struct bitmap_index *old_bitmap,
637637
const uint32_t *mapping)
638638
{
639+
struct commit *c;
640+
struct tree *t;
639641
int found;
640642
int from_pseudo_merge = commit->object.flags & BITMAP_PSEUDO_MERGE;
641643
uint32_t pos;
@@ -650,9 +652,8 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
650652

651653
prio_queue_put(queue, commit);
652654

653-
while (queue->nr) {
655+
while ((c = prio_queue_get(queue))) {
654656
struct commit_list *p;
655-
struct commit *c = prio_queue_get(queue);
656657

657658
if (old_bitmap && mapping) {
658659
struct ewah_bitmap *old;
@@ -740,8 +741,7 @@ static int fill_bitmap_commit(struct bitmap_writer *writer,
740741
}
741742
}
742743

743-
while (tree_queue->nr) {
744-
struct tree *t = prio_queue_get(tree_queue);
744+
while ((t = prio_queue_get(tree_queue))) {
745745
int found;
746746

747747
pos = find_object_pos(writer, &t->object.oid, &found);

0 commit comments

Comments
 (0)