Skip to content

Commit 0b1459a

Browse files
jeffhostetlerGit for Windows Build Agent
authored andcommitted
read-cache: run verify_hdr() in background thread
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 <[email protected]>
1 parent 4caf06e commit 0b1459a

File tree

1 file changed

+60
-0
lines changed

1 file changed

+60
-0
lines changed

read-cache.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@
2020
#include "split-index.h"
2121
#include "utf8.h"
2222

23+
#ifndef NO_PTHREADS
24+
#include <pthread.h>
25+
#endif
26+
2327
/* Mask for the name length in ce_flags in the on-disk index */
2428

2529
#define CE_NAMEMASK (0x0fff)
@@ -1533,6 +1537,34 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
15331537
return 0;
15341538
}
15351539

1540+
#ifndef NO_PTHREADS
1541+
/*
1542+
* Require index file to be larger than this threshold before
1543+
* we bother using a thread to verify the SHA.
1544+
* This value was arbitrarily chosen.
1545+
*/
1546+
#define VERIFY_HDR_THRESHOLD 10*1024*1024
1547+
1548+
struct verify_hdr_thread_data
1549+
{
1550+
pthread_t thread_id;
1551+
struct cache_header *hdr;
1552+
size_t size;
1553+
int result;
1554+
};
1555+
1556+
/*
1557+
* A thread proc to run the verify_hdr() computation
1558+
* in a background thread.
1559+
*/
1560+
static void *verify_hdr_thread(void *_data)
1561+
{
1562+
struct verify_hdr_thread_data *p = _data;
1563+
p->result = verify_hdr(p->hdr, (unsigned long)p->size);
1564+
return NULL;
1565+
}
1566+
#endif
1567+
15361568
static int read_index_extension(struct index_state *istate,
15371569
const char *ext, void *data, unsigned long sz)
15381570
{
@@ -1734,6 +1766,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
17341766
void *mmap;
17351767
size_t mmap_size;
17361768
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
1769+
#ifndef NO_PTHREADS
1770+
struct verify_hdr_thread_data verify_hdr_thread_data;
1771+
#endif
17371772

17381773
if (istate->initialized)
17391774
return istate->cache_nr;
@@ -1760,8 +1795,23 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
17601795
close(fd);
17611796

17621797
hdr = mmap;
1798+
#ifdef NO_PTHREADS
17631799
if (verify_hdr(hdr, mmap_size) < 0)
17641800
goto unmap;
1801+
#else
1802+
if (mmap_size < VERIFY_HDR_THRESHOLD) {
1803+
if (verify_hdr(hdr, mmap_size) < 0)
1804+
goto unmap;
1805+
} else {
1806+
verify_hdr_thread_data.hdr = hdr;
1807+
verify_hdr_thread_data.size = mmap_size;
1808+
verify_hdr_thread_data.result = -1;
1809+
if (pthread_create(
1810+
&verify_hdr_thread_data.thread_id, NULL,
1811+
verify_hdr_thread, &verify_hdr_thread_data))
1812+
die_errno("unable to start verify_hdr_thread");
1813+
}
1814+
#endif
17651815

17661816
hashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - 20);
17671817
istate->version = ntohl(hdr->hdr_version);
@@ -1809,6 +1859,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
18091859
src_offset += 8;
18101860
src_offset += extsize;
18111861
}
1862+
1863+
#ifndef NO_PTHREADS
1864+
if (mmap_size >= VERIFY_HDR_THRESHOLD) {
1865+
if (pthread_join(verify_hdr_thread_data.thread_id, NULL))
1866+
die_errno("unable to join verify_hdr_thread");
1867+
if (verify_hdr_thread_data.result < 0)
1868+
goto unmap;
1869+
}
1870+
#endif
1871+
18121872
munmap(mmap, mmap_size);
18131873
return istate->cache_nr;
18141874

0 commit comments

Comments
 (0)