Skip to content

Commit 3007752

Browse files
peffgitster
authored andcommitted
midx.c: improve cache locality in midx_pack_order_cmp()
There is a lot of pointer dereferencing in the pre-image version of 'midx_pack_order_cmp()', which this patch gets rid of. Instead of comparing the pack preferred-ness and then the pack id, both of these checks are done at the same time by using the high-order bit of the pack id to represent whether it's preferred. Then the pack id and offset are compared as usual. This produces the same result so long as there are less than 2^31 packs, which seems like a likely assumption to make in practice. Signed-off-by: Jeff King <[email protected]> Signed-off-by: Taylor Blau <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 38ff7ca commit 3007752

File tree

1 file changed

+29
-26
lines changed

1 file changed

+29
-26
lines changed

midx.c

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -818,46 +818,49 @@ static int write_midx_large_offsets(struct hashfile *f,
818818
return 0;
819819
}
820820

821-
static int midx_pack_order_cmp(const void *va, const void *vb, void *_ctx)
822-
{
823-
struct write_midx_context *ctx = _ctx;
824-
825-
struct pack_midx_entry *a = &ctx->entries[*(const uint32_t *)va];
826-
struct pack_midx_entry *b = &ctx->entries[*(const uint32_t *)vb];
827-
828-
uint32_t perm_a = ctx->pack_perm[a->pack_int_id];
829-
uint32_t perm_b = ctx->pack_perm[b->pack_int_id];
830-
831-
/* Sort objects in the preferred pack ahead of any others. */
832-
if (a->preferred > b->preferred)
833-
return -1;
834-
if (a->preferred < b->preferred)
835-
return 1;
821+
struct midx_pack_order_data {
822+
uint32_t nr;
823+
uint32_t pack;
824+
off_t offset;
825+
};
836826

837-
/* Then, order objects by which packs they appear in. */
838-
if (perm_a < perm_b)
827+
static int midx_pack_order_cmp(const void *va, const void *vb)
828+
{
829+
const struct midx_pack_order_data *a = va, *b = vb;
830+
if (a->pack < b->pack)
839831
return -1;
840-
if (perm_a > perm_b)
832+
else if (a->pack > b->pack)
841833
return 1;
842-
843-
/* Then, disambiguate by their offset within each pack. */
844-
if (a->offset < b->offset)
834+
else if (a->offset < b->offset)
845835
return -1;
846-
if (a->offset > b->offset)
836+
else if (a->offset > b->offset)
847837
return 1;
848-
849-
return 0;
838+
else
839+
return 0;
850840
}
851841

852842
static uint32_t *midx_pack_order(struct write_midx_context *ctx)
853843
{
844+
struct midx_pack_order_data *data;
854845
uint32_t *pack_order;
855846
uint32_t i;
856847

848+
ALLOC_ARRAY(data, ctx->entries_nr);
849+
for (i = 0; i < ctx->entries_nr; i++) {
850+
struct pack_midx_entry *e = &ctx->entries[i];
851+
data[i].nr = i;
852+
data[i].pack = ctx->pack_perm[e->pack_int_id];
853+
if (!e->preferred)
854+
data[i].pack |= (1U << 31);
855+
data[i].offset = e->offset;
856+
}
857+
858+
QSORT(data, ctx->entries_nr, midx_pack_order_cmp);
859+
857860
ALLOC_ARRAY(pack_order, ctx->entries_nr);
858861
for (i = 0; i < ctx->entries_nr; i++)
859-
pack_order[i] = i;
860-
QSORT_S(pack_order, ctx->entries_nr, midx_pack_order_cmp, ctx);
862+
pack_order[i] = data[i].nr;
863+
free(data);
861864

862865
return pack_order;
863866
}

0 commit comments

Comments
 (0)