Skip to content

Commit 66a75fd

Browse files
committed
indexer: Avoid one mmap(2)/munmap(2) pair per git_indexer_append call
This change makes `append_to_pack` completely rely on `p_pwrite` to do all its I/O instead of splitting it between `p_pwrite` and a `mmap(2)`/`munmap(2)`+`memcpy(3)`. This saves a good chunk of user CPU time and avoids making two syscalls per round, but doesn't really cut down a lot of wall time (~1% on cloning the [git](https://github.com/git/git.git) repository).
1 parent 109b4c8 commit 66a75fd

File tree

1 file changed

+2
-47
lines changed

1 file changed

+2
-47
lines changed

src/indexer.c

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,6 @@ static void hash_partially(git_indexer *idx, const uint8_t *data, size_t size)
603603

604604
static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t size)
605605
{
606-
#ifdef NO_MMAP
607606
size_t remaining_size = size;
608607
const char *ptr = (const char *)data;
609608

@@ -619,65 +618,21 @@ static int write_at(git_indexer *idx, const void *data, off64_t offset, size_t s
619618
offset += nb;
620619
remaining_size -= nb;
621620
}
622-
#else
623-
git_file fd = idx->pack->mwf.fd;
624-
size_t mmap_alignment;
625-
size_t page_offset;
626-
off64_t page_start;
627-
unsigned char *map_data;
628-
git_map map;
629-
int error;
630-
631-
GIT_ASSERT_ARG(data);
632-
GIT_ASSERT_ARG(size);
633-
634-
if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
635-
return error;
636-
637-
/* the offset needs to be at the mmap boundary for the platform */
638-
page_offset = offset % mmap_alignment;
639-
page_start = offset - page_offset;
640-
641-
if ((error = p_mmap(&map, page_offset + size, GIT_PROT_WRITE, GIT_MAP_SHARED, fd, page_start)) < 0)
642-
return error;
643-
644-
map_data = (unsigned char *)map.data;
645-
memcpy(map_data + page_offset, data, size);
646-
p_munmap(&map);
647-
#endif
648621

649622
return 0;
650623
}
651624

652625
static int append_to_pack(git_indexer *idx, const void *data, size_t size)
653626
{
654-
off64_t new_size;
655-
size_t mmap_alignment;
656-
size_t page_offset;
657-
off64_t page_start;
658-
off64_t current_size = idx->pack->mwf.size;
659-
int error;
660-
661627
if (!size)
662628
return 0;
663629

664-
if ((error = git__mmap_alignment(&mmap_alignment)) < 0)
665-
return error;
666-
667-
/* Write a single byte to force the file system to allocate space now or
668-
* report an error, since we can't report errors when writing using mmap.
669-
* Round the size up to the nearest page so that we only need to perform file
670-
* I/O when we add a page, instead of whenever we write even a single byte. */
671-
new_size = current_size + size;
672-
page_offset = new_size % mmap_alignment;
673-
page_start = new_size - page_offset;
674-
675-
if (p_pwrite(idx->pack->mwf.fd, data, 1, page_start + mmap_alignment - 1) < 0) {
630+
if (write_at(idx, data, idx->pack->mwf.size, size) < 0) {
676631
git_error_set(GIT_ERROR_OS, "cannot extend packfile '%s'", idx->pack->pack_name);
677632
return -1;
678633
}
679634

680-
return write_at(idx, data, idx->pack->mwf.size, size);
635+
return 0;
681636
}
682637

683638
static int read_stream_object(git_indexer *idx, git_indexer_progress *stats)

0 commit comments

Comments
 (0)