Skip to content

Commit

Permalink
read-cache: run verify_hdr() in background thread
Browse files Browse the repository at this point in the history
This is a performance optimization.

Teach do_read_index() to call verify_hdr() using a thread
and allow SHA1 verification to run concurrently with the
parsing of index-entries and extensions.

For large index files, this cuts the startup time in half.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
  • Loading branch information
jeffhostetler authored and Git for Windows Build Agent committed Oct 20, 2017
1 parent add3d73 commit 9eddf06
Showing 1 changed file with 60 additions and 0 deletions.
60 changes: 60 additions & 0 deletions read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
#include "split-index.h"
#include "utf8.h"

#ifndef NO_PTHREADS
#include <pthread.h>
#endif

/* Mask for the name length in ce_flags in the on-disk index */

#define CE_NAMEMASK (0x0fff)
Expand Down Expand Up @@ -1534,6 +1538,34 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
return 0;
}

#ifndef NO_PTHREADS
/*
* Require index file to be larger than this threshold before
* we bother using a thread to verify the SHA.
* This value was arbitrarily chosen.
*/
#define VERIFY_HDR_THRESHOLD 10*1024*1024

struct verify_hdr_thread_data
{
pthread_t thread_id;
struct cache_header *hdr;
size_t size;
int result;
};

/*
* A thread proc to run the verify_hdr() computation
* in a background thread.
*/
static void *verify_hdr_thread(void *_data)
{
struct verify_hdr_thread_data *p = _data;
p->result = verify_hdr(p->hdr, (unsigned long)p->size);
return NULL;
}
#endif

static int read_index_extension(struct index_state *istate,
const char *ext, void *data, unsigned long sz)
{
Expand Down Expand Up @@ -1735,6 +1767,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
void *mmap;
size_t mmap_size;
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
#ifndef NO_PTHREADS
struct verify_hdr_thread_data verify_hdr_thread_data;
#endif

if (istate->initialized)
return istate->cache_nr;
Expand All @@ -1761,8 +1796,23 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
close(fd);

hdr = mmap;
#ifdef NO_PTHREADS
if (verify_hdr(hdr, mmap_size) < 0)
goto unmap;
#else
if (mmap_size < VERIFY_HDR_THRESHOLD) {
if (verify_hdr(hdr, mmap_size) < 0)
goto unmap;
} else {
verify_hdr_thread_data.hdr = hdr;
verify_hdr_thread_data.size = mmap_size;
verify_hdr_thread_data.result = -1;
if (pthread_create(
&verify_hdr_thread_data.thread_id, NULL,
verify_hdr_thread, &verify_hdr_thread_data))
die_errno("unable to start verify_hdr_thread");
}
#endif

hashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - 20);
istate->version = ntohl(hdr->hdr_version);
Expand Down Expand Up @@ -1810,6 +1860,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
src_offset += 8;
src_offset += extsize;
}

#ifndef NO_PTHREADS
if (mmap_size >= VERIFY_HDR_THRESHOLD) {
if (pthread_join(verify_hdr_thread_data.thread_id, NULL))
die_errno("unable to join verify_hdr_thread");
if (verify_hdr_thread_data.result < 0)
goto unmap;
}
#endif

munmap(mmap, mmap_size);
return istate->cache_nr;

Expand Down

0 comments on commit 9eddf06

Please sign in to comment.