Skip to content

Commit c7a1535

Browse files
committed
Extend packfile in increments of page_size.
This improves performance by reducing the number of I/O operations.
1 parent 42864e5 commit c7a1535

File tree

1 file changed

+24
-1
lines changed

1 file changed

+24
-1
lines changed

src/indexer.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,13 +477,29 @@ static int write_at(git_indexer *idx, const void *data, git_off_t offset, size_t
477477

478478
static int append_to_pack(git_indexer *idx, const void *data, size_t size)
479479
{
480+
git_off_t new_size;
481+
size_t mmap_alignment;
482+
size_t page_offset;
483+
git_off_t page_start;
480484
git_off_t current_size = idx->pack->mwf.size;
481485
int fd = idx->pack->mwf.fd;
486+
int error;
482487

483488
if (!size)
484489
return 0;
485490

486-
if (p_lseek(fd, current_size + size - 1, SEEK_SET) < 0 ||
491+
if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
492+
return error;
493+
494+
/* Write a single byte to force the file system to allocate space now or
495+
* report an error, since we can't report errors when writing using mmap.
496+
* Round the size up to the nearest page so that we only need to perform file
497+
* I/O when we add a page, instead of whenever we write even a single byte. */
498+
new_size = current_size + size;
499+
page_offset = new_size % mmap_alignment;
500+
page_start = new_size - page_offset;
501+
502+
if (p_lseek(fd, page_start + mmap_alignment - 1, SEEK_SET) < 0 ||
487503
p_write(idx->pack->mwf.fd, data, 1) < 0) {
488504
giterr_set(GITERR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
489505
return -1;
@@ -1041,6 +1057,13 @@ int git_indexer_commit(git_indexer *idx, git_transfer_progress *stats)
10411057
goto on_error;
10421058

10431059
git_mwindow_free_all(&idx->pack->mwf);
1060+
1061+
/* Truncate file to undo rounding up to next page_size in append_to_pack */
1062+
if (p_ftruncate(idx->pack->mwf.fd, idx->pack->mwf.size) < 0) {
1063+
giterr_set(GITERR_OS, "failed to truncate pack file '%s'", idx->pack->pack_name);
1064+
return -1;
1065+
}
1066+
10441067
/* We need to close the descriptor here so Windows doesn't choke on commit_at */
10451068
if (p_close(idx->pack->mwf.fd) < 0) {
10461069
giterr_set(GITERR_OS, "failed to close packfile");

0 commit comments

Comments
 (0)