Skip to content

Commit 7af607c

Browse files
pks-tgitster
authored andcommitted
reftable/record: store "val1" hashes as static arrays
When reading ref records of type "val1", we store its object ID in an allocated array. This results in an additional allocation for every single ref record we read, which is rather inefficient especially when iterating over refs. Refactor the code to instead use an embedded array of `GIT_MAX_RAWSZ` bytes. While this means that `struct ref_record` is bigger now, we typically do not store all refs in an array anyway and instead only handle a limited number of records at the same point in time. Using `git show-ref --quiet` in a repository with ~350k refs this leads to a significant drop in allocations. Before: HEAP SUMMARY: in use at exit: 21,098 bytes in 192 blocks total heap usage: 2,116,683 allocs, 2,116,491 frees, 76,098,060 bytes allocated After: HEAP SUMMARY: in use at exit: 21,098 bytes in 192 blocks total heap usage: 1,419,031 allocs, 1,418,839 frees, 62,145,036 bytes allocated Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 88f59d9 commit 7af607c

File tree

7 files changed

+13
-30
lines changed

7 files changed

+13
-30
lines changed

reftable/block_test.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,11 @@ static void test_block_read_write(void)
4949

5050
for (i = 0; i < N; i++) {
5151
char name[100];
52-
uint8_t hash[GIT_SHA1_RAWSZ];
5352
snprintf(name, sizeof(name), "branch%02d", i);
54-
memset(hash, i, sizeof(hash));
5553

5654
rec.u.ref.refname = name;
5755
rec.u.ref.value_type = REFTABLE_REF_VAL1;
58-
rec.u.ref.value.val1 = hash;
56+
memset(rec.u.ref.value.val1, i, GIT_SHA1_RAWSZ);
5957

6058
names[i] = xstrdup(name);
6159
n = block_writer_add(&bw, &rec);

reftable/merged_test.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,11 @@ static void readers_destroy(struct reftable_reader **readers, size_t n)
123123

124124
static void test_merged_between(void)
125125
{
126-
uint8_t hash1[GIT_SHA1_RAWSZ] = { 1, 2, 3, 0 };
127-
128126
struct reftable_ref_record r1[] = { {
129127
.refname = "b",
130128
.update_index = 1,
131129
.value_type = REFTABLE_REF_VAL1,
132-
.value.val1 = hash1,
130+
.value.val1 = { 1, 2, 3, 0 },
133131
} };
134132
struct reftable_ref_record r2[] = { {
135133
.refname = "a",
@@ -165,26 +163,24 @@ static void test_merged_between(void)
165163

166164
static void test_merged(void)
167165
{
168-
uint8_t hash1[GIT_SHA1_RAWSZ] = { 1 };
169-
uint8_t hash2[GIT_SHA1_RAWSZ] = { 2 };
170166
struct reftable_ref_record r1[] = {
171167
{
172168
.refname = "a",
173169
.update_index = 1,
174170
.value_type = REFTABLE_REF_VAL1,
175-
.value.val1 = hash1,
171+
.value.val1 = { 1 },
176172
},
177173
{
178174
.refname = "b",
179175
.update_index = 1,
180176
.value_type = REFTABLE_REF_VAL1,
181-
.value.val1 = hash1,
177+
.value.val1 = { 1 },
182178
},
183179
{
184180
.refname = "c",
185181
.update_index = 1,
186182
.value_type = REFTABLE_REF_VAL1,
187-
.value.val1 = hash1,
183+
.value.val1 = { 1 },
188184
}
189185
};
190186
struct reftable_ref_record r2[] = { {
@@ -197,13 +193,13 @@ static void test_merged(void)
197193
.refname = "c",
198194
.update_index = 3,
199195
.value_type = REFTABLE_REF_VAL1,
200-
.value.val1 = hash2,
196+
.value.val1 = { 2 },
201197
},
202198
{
203199
.refname = "d",
204200
.update_index = 3,
205201
.value_type = REFTABLE_REF_VAL1,
206-
.value.val1 = hash1,
202+
.value.val1 = { 1 },
207203
},
208204
};
209205

reftable/readwrite_test.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,15 @@ static void write_table(char ***names, struct strbuf *buf, int N,
6060
*names = reftable_calloc(sizeof(char *) * (N + 1));
6161
reftable_writer_set_limits(w, update_index, update_index);
6262
for (i = 0; i < N; i++) {
63-
uint8_t hash[GIT_SHA256_RAWSZ] = { 0 };
6463
char name[100];
6564
int n;
6665

67-
set_test_hash(hash, i);
68-
6966
snprintf(name, sizeof(name), "refs/heads/branch%02d", i);
7067

7168
ref.refname = name;
7269
ref.update_index = update_index;
7370
ref.value_type = REFTABLE_REF_VAL1;
74-
ref.value.val1 = hash;
71+
set_test_hash(ref.value.val1, i);
7572
(*names)[i] = xstrdup(name);
7673

7774
n = reftable_writer_add_ref(w, &ref);
@@ -675,11 +672,10 @@ static void test_write_object_id_min_length(void)
675672
struct strbuf buf = STRBUF_INIT;
676673
struct reftable_writer *w =
677674
reftable_new_writer(&strbuf_add_void, &buf, &opts);
678-
uint8_t hash[GIT_SHA1_RAWSZ] = {42};
679675
struct reftable_ref_record ref = {
680676
.update_index = 1,
681677
.value_type = REFTABLE_REF_VAL1,
682-
.value.val1 = hash,
678+
.value.val1 = {42},
683679
};
684680
int err;
685681
int i;
@@ -711,11 +707,10 @@ static void test_write_object_id_length(void)
711707
struct strbuf buf = STRBUF_INIT;
712708
struct reftable_writer *w =
713709
reftable_new_writer(&strbuf_add_void, &buf, &opts);
714-
uint8_t hash[GIT_SHA1_RAWSZ] = {42};
715710
struct reftable_ref_record ref = {
716711
.update_index = 1,
717712
.value_type = REFTABLE_REF_VAL1,
718-
.value.val1 = hash,
713+
.value.val1 = {42},
719714
};
720715
int err;
721716
int i;
@@ -814,11 +809,10 @@ static void test_write_multiple_indices(void)
814809
writer = reftable_new_writer(&strbuf_add_void, &writer_buf, &opts);
815810
reftable_writer_set_limits(writer, 1, 1);
816811
for (i = 0; i < 100; i++) {
817-
unsigned char hash[GIT_SHA1_RAWSZ] = {i};
818812
struct reftable_ref_record ref = {
819813
.update_index = 1,
820814
.value_type = REFTABLE_REF_VAL1,
821-
.value.val1 = hash,
815+
.value.val1 = {i},
822816
};
823817

824818
strbuf_reset(&buf);

reftable/record.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,6 @@ static void reftable_ref_record_copy_from(void *rec, const void *src_rec,
219219
case REFTABLE_REF_DELETION:
220220
break;
221221
case REFTABLE_REF_VAL1:
222-
ref->value.val1 = reftable_malloc(hash_size);
223222
memcpy(ref->value.val1, src->value.val1, hash_size);
224223
break;
225224
case REFTABLE_REF_VAL2:
@@ -303,7 +302,6 @@ void reftable_ref_record_release(struct reftable_ref_record *ref)
303302
reftable_free(ref->value.val2.value);
304303
break;
305304
case REFTABLE_REF_VAL1:
306-
reftable_free(ref->value.val1);
307305
break;
308306
case REFTABLE_REF_DELETION:
309307
break;
@@ -394,7 +392,6 @@ static int reftable_ref_record_decode(void *rec, struct strbuf key,
394392
return -1;
395393
}
396394

397-
r->value.val1 = reftable_malloc(hash_size);
398395
memcpy(r->value.val1, in.buf, hash_size);
399396
string_view_consume(&in, hash_size);
400397
break;

reftable/record_test.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ static void test_reftable_ref_record_roundtrip(void)
119119
case REFTABLE_REF_DELETION:
120120
break;
121121
case REFTABLE_REF_VAL1:
122-
in.u.ref.value.val1 = reftable_malloc(GIT_SHA1_RAWSZ);
123122
set_hash(in.u.ref.value.val1, 1);
124123
break;
125124
case REFTABLE_REF_VAL2:

reftable/reftable-record.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ license that can be found in the LICENSE file or at
99
#ifndef REFTABLE_RECORD_H
1010
#define REFTABLE_RECORD_H
1111

12+
#include "hash-ll.h"
1213
#include <stdint.h>
1314

1415
/*
@@ -38,7 +39,7 @@ struct reftable_ref_record {
3839
#define REFTABLE_NR_REF_VALUETYPES 4
3940
} value_type;
4041
union {
41-
uint8_t *val1; /* malloced hash. */
42+
unsigned char val1[GIT_MAX_RAWSZ];
4243
struct {
4344
uint8_t *value; /* first value, malloced hash */
4445
uint8_t *target_value; /* second value, malloced hash */

reftable/stack_test.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,6 @@ static void test_reftable_stack_add(void)
463463
refs[i].refname = xstrdup(buf);
464464
refs[i].update_index = i + 1;
465465
refs[i].value_type = REFTABLE_REF_VAL1;
466-
refs[i].value.val1 = reftable_malloc(GIT_SHA1_RAWSZ);
467466
set_test_hash(refs[i].value.val1, i);
468467

469468
logs[i].refname = xstrdup(buf);
@@ -600,7 +599,6 @@ static void test_reftable_stack_tombstone(void)
600599
refs[i].update_index = i + 1;
601600
if (i % 2 == 0) {
602601
refs[i].value_type = REFTABLE_REF_VAL1;
603-
refs[i].value.val1 = reftable_malloc(GIT_SHA1_RAWSZ);
604602
set_test_hash(refs[i].value.val1, i);
605603
}
606604

0 commit comments

Comments
 (0)