mirror of
https://github.com/git/git
synced 2024-11-05 18:59:29 +00:00
f1bf54aee3
We have a few functions which are basically just accessors to structures. As those functions are executed inside the hot loop when iterating through many refs, the fact that they cannot be inlined is costing us some performance. Move the function definitions into their respective headers so that they can be inlined. This results in a performance improvement when iterating over 1 million refs: Benchmark 1: show-ref: single matching ref (revision = HEAD~) Time (mean ± σ): 105.9 ms ± 3.6 ms [User: 103.0 ms, System: 2.8 ms] Range (min … max): 103.1 ms … 133.4 ms 1000 runs Benchmark 2: show-ref: single matching ref (revision = HEAD) Time (mean ± σ): 100.7 ms ± 3.4 ms [User: 97.8 ms, System: 2.8 ms] Range (min … max): 97.8 ms … 124.0 ms 1000 runs Summary show-ref: single matching ref (revision = HEAD) ran 1.05 ± 0.05 times faster than show-ref: single matching ref (revision = HEAD~) Signed-off-by: Patrick Steinhardt <ps@pks.im> Signed-off-by: Junio C Hamano <gitster@pobox.com>
77 lines
1.4 KiB
C
77 lines
1.4 KiB
C
/*
|
|
Copyright 2020 Google LLC
|
|
|
|
Use of this source code is governed by a BSD-style
|
|
license that can be found in the LICENSE file or at
|
|
https://developers.google.com/open-source/licenses/bsd
|
|
*/
|
|
|
|
#include "pq.h"
|
|
|
|
#include "reftable-record.h"
|
|
#include "system.h"
|
|
#include "basics.h"
|
|
|
|
int pq_less(struct pq_entry *a, struct pq_entry *b)
|
|
{
|
|
int cmp = reftable_record_cmp(a->rec, b->rec);
|
|
if (cmp == 0)
|
|
return a->index > b->index;
|
|
return cmp < 0;
|
|
}
|
|
|
|
struct pq_entry merged_iter_pqueue_remove(struct merged_iter_pqueue *pq)
|
|
{
|
|
int i = 0;
|
|
struct pq_entry e = pq->heap[0];
|
|
pq->heap[0] = pq->heap[pq->len - 1];
|
|
pq->len--;
|
|
|
|
i = 0;
|
|
while (i < pq->len) {
|
|
int min = i;
|
|
int j = 2 * i + 1;
|
|
int k = 2 * i + 2;
|
|
if (j < pq->len && pq_less(&pq->heap[j], &pq->heap[i])) {
|
|
min = j;
|
|
}
|
|
if (k < pq->len && pq_less(&pq->heap[k], &pq->heap[min])) {
|
|
min = k;
|
|
}
|
|
|
|
if (min == i) {
|
|
break;
|
|
}
|
|
|
|
SWAP(pq->heap[i], pq->heap[min]);
|
|
i = min;
|
|
}
|
|
|
|
return e;
|
|
}
|
|
|
|
void merged_iter_pqueue_add(struct merged_iter_pqueue *pq, const struct pq_entry *e)
|
|
{
|
|
int i = 0;
|
|
|
|
REFTABLE_ALLOC_GROW(pq->heap, pq->len + 1, pq->cap);
|
|
pq->heap[pq->len++] = *e;
|
|
|
|
i = pq->len - 1;
|
|
while (i > 0) {
|
|
int j = (i - 1) / 2;
|
|
if (pq_less(&pq->heap[j], &pq->heap[i])) {
|
|
break;
|
|
}
|
|
|
|
SWAP(pq->heap[j], pq->heap[i]);
|
|
|
|
i = j;
|
|
}
|
|
}
|
|
|
|
void merged_iter_pqueue_release(struct merged_iter_pqueue *pq)
|
|
{
|
|
FREE_AND_NULL(pq->heap);
|
|
memset(pq, 0, sizeof(*pq));
|
|
}
|