Skip to content

Commit 66ed011

Browse files
pks-tgitster
authored andcommitted
reftable/writer: optimize allocations by using a scratch buffer
Both `writer_add_record()` and `reftable_writer_add_ref()` get executed for every single ref record we're adding to the reftable writer. And as both functions use a local buffer to write data, the allocations we have to do here add up during larger transactions. Refactor the code to use a scratch buffer part of the `reftable_writer` itself such that we can reuse it. This signifcantly reduces the number of allocations during large transactions, e.g. when migrating refs from the "files" backend to the "reftable" backend. Before this change: HEAP SUMMARY: in use at exit: 80,048 bytes in 49 blocks total heap usage: 5,032,171 allocs, 5,032,122 frees, 418,792,092 bytes allocated After this change: HEAP SUMMARY: in use at exit: 80,048 bytes in 49 blocks total heap usage: 3,025,864 allocs, 3,025,815 frees, 372,746,291 bytes allocated This also translate into a small speedup: Benchmark 1: migrate files:reftable (refcount = 1000000, revision = HEAD~) Time (mean ± σ): 827.2 ms ± 16.5 ms [User: 689.4 ms, System: 124.9 ms] Range (min … max): 809.0 ms … 924.7 ms 50 runs Benchmark 2: migrate files:reftable (refcount = 1000000, revision = HEAD) Time (mean ± σ): 813.6 ms ± 11.6 ms [User: 679.0 ms, System: 123.4 ms] Range (min … max): 786.7 ms … 833.5 ms 50 runs Summary migrate files:reftable (refcount = 1000000, revision = HEAD) ran 1.02 ± 0.02 times faster than migrate files:reftable (refcount = 1000000, revision = HEAD~) Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent a7004ab commit 66ed011

File tree

2 files changed

+12
-12
lines changed

2 files changed

+12
-12
lines changed

reftable/writer.c

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ int reftable_writer_new(struct reftable_writer **out,
148148

149149
reftable_buf_init(&wp->block_writer_data.last_key);
150150
reftable_buf_init(&wp->last_key);
151+
reftable_buf_init(&wp->buf);
151152
REFTABLE_CALLOC_ARRAY(wp->block, opts.block_size);
152153
if (!wp->block) {
153154
reftable_free(wp);
@@ -180,6 +181,7 @@ static void writer_release(struct reftable_writer *w)
180181
w->block_writer = NULL;
181182
writer_clear_index(w);
182183
reftable_buf_release(&w->last_key);
184+
reftable_buf_release(&w->buf);
183185
}
184186
}
185187

@@ -249,20 +251,19 @@ static int writer_index_hash(struct reftable_writer *w, struct reftable_buf *has
249251
static int writer_add_record(struct reftable_writer *w,
250252
struct reftable_record *rec)
251253
{
252-
struct reftable_buf key = REFTABLE_BUF_INIT;
253254
int err;
254255

255-
err = reftable_record_key(rec, &key);
256+
err = reftable_record_key(rec, &w->buf);
256257
if (err < 0)
257258
goto done;
258259

259-
if (reftable_buf_cmp(&w->last_key, &key) >= 0) {
260+
if (reftable_buf_cmp(&w->last_key, &w->buf) >= 0) {
260261
err = REFTABLE_API_ERROR;
261262
goto done;
262263
}
263264

264265
reftable_buf_reset(&w->last_key);
265-
err = reftable_buf_add(&w->last_key, key.buf, key.len);
266+
err = reftable_buf_add(&w->last_key, w->buf.buf, w->buf.len);
266267
if (err < 0)
267268
goto done;
268269

@@ -312,7 +313,6 @@ static int writer_add_record(struct reftable_writer *w,
312313
}
313314

314315
done:
315-
reftable_buf_release(&key);
316316
return err;
317317
}
318318

@@ -325,7 +325,6 @@ int reftable_writer_add_ref(struct reftable_writer *w,
325325
.ref = *ref
326326
},
327327
};
328-
struct reftable_buf buf = REFTABLE_BUF_INIT;
329328
int err;
330329

331330
if (!ref->refname ||
@@ -340,32 +339,32 @@ int reftable_writer_add_ref(struct reftable_writer *w,
340339
goto out;
341340

342341
if (!w->opts.skip_index_objects && reftable_ref_record_val1(ref)) {
343-
err = reftable_buf_add(&buf, (char *)reftable_ref_record_val1(ref),
342+
reftable_buf_reset(&w->buf);
343+
err = reftable_buf_add(&w->buf, (char *)reftable_ref_record_val1(ref),
344344
hash_size(w->opts.hash_id));
345345
if (err < 0)
346346
goto out;
347347

348-
err = writer_index_hash(w, &buf);
348+
err = writer_index_hash(w, &w->buf);
349349
if (err < 0)
350350
goto out;
351351
}
352352

353353
if (!w->opts.skip_index_objects && reftable_ref_record_val2(ref)) {
354-
reftable_buf_reset(&buf);
355-
err = reftable_buf_add(&buf, reftable_ref_record_val2(ref),
354+
reftable_buf_reset(&w->buf);
355+
err = reftable_buf_add(&w->buf, reftable_ref_record_val2(ref),
356356
hash_size(w->opts.hash_id));
357357
if (err < 0)
358358
goto out;
359359

360-
err = writer_index_hash(w, &buf);
360+
err = writer_index_hash(w, &w->buf);
361361
if (err < 0)
362362
goto out;
363363
}
364364

365365
err = 0;
366366

367367
out:
368-
reftable_buf_release(&buf);
369368
return err;
370369
}
371370

reftable/writer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ struct reftable_writer {
2020
void *write_arg;
2121
int pending_padding;
2222
struct reftable_buf last_key;
23+
struct reftable_buf buf;
2324

2425
/* offset of next block to write. */
2526
uint64_t next;

0 commit comments

Comments
 (0)