Skip to content

Commit fad887b

Browse files
jeffhostetlerdscho
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 b997864 commit fad887b

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
@@ -21,6 +21,10 @@
2121
#include "utf8.h"
2222
#include "fsmonitor.h"
2323

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

2630
#define CE_NAMEMASK (0x0fff)
@@ -1566,6 +1570,34 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
15661570
return 0;
15671571
}
15681572

1573+
#ifndef NO_PTHREADS
1574+
/*
1575+
* Require index file to be larger than this threshold before
1576+
* we bother using a thread to verify the SHA.
1577+
* This value was arbitrarily chosen.
1578+
*/
1579+
#define VERIFY_HDR_THRESHOLD 10*1024*1024
1580+
1581+
struct verify_hdr_thread_data
1582+
{
1583+
pthread_t thread_id;
1584+
struct cache_header *hdr;
1585+
size_t size;
1586+
int result;
1587+
};
1588+
1589+
/*
1590+
* A thread proc to run the verify_hdr() computation
1591+
* in a background thread.
1592+
*/
1593+
static void *verify_hdr_thread(void *_data)
1594+
{
1595+
struct verify_hdr_thread_data *p = _data;
1596+
p->result = verify_hdr(p->hdr, (unsigned long)p->size);
1597+
return NULL;
1598+
}
1599+
#endif
1600+
15691601
static int read_index_extension(struct index_state *istate,
15701602
const char *ext, void *data, unsigned long sz)
15711603
{
@@ -1774,6 +1806,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
17741806
void *mmap;
17751807
size_t mmap_size;
17761808
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
1809+
#ifndef NO_PTHREADS
1810+
struct verify_hdr_thread_data verify_hdr_thread_data;
1811+
#endif
17771812

17781813
if (istate->initialized)
17791814
return istate->cache_nr;
@@ -1800,8 +1835,23 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
18001835
close(fd);
18011836

18021837
hdr = mmap;
1838+
#ifdef NO_PTHREADS
18031839
if (verify_hdr(hdr, mmap_size) < 0)
18041840
goto unmap;
1841+
#else
1842+
if (mmap_size < VERIFY_HDR_THRESHOLD) {
1843+
if (verify_hdr(hdr, mmap_size) < 0)
1844+
goto unmap;
1845+
} else {
1846+
verify_hdr_thread_data.hdr = hdr;
1847+
verify_hdr_thread_data.size = mmap_size;
1848+
verify_hdr_thread_data.result = -1;
1849+
if (pthread_create(
1850+
&verify_hdr_thread_data.thread_id, NULL,
1851+
verify_hdr_thread, &verify_hdr_thread_data))
1852+
die_errno("unable to start verify_hdr_thread");
1853+
}
1854+
#endif
18051855

18061856
hashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - 20);
18071857
istate->version = ntohl(hdr->hdr_version);
@@ -1849,6 +1899,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
18491899
src_offset += 8;
18501900
src_offset += extsize;
18511901
}
1902+
1903+
#ifndef NO_PTHREADS
1904+
if (mmap_size >= VERIFY_HDR_THRESHOLD) {
1905+
if (pthread_join(verify_hdr_thread_data.thread_id, NULL))
1906+
die_errno("unable to join verify_hdr_thread");
1907+
if (verify_hdr_thread_data.result < 0)
1908+
goto unmap;
1909+
}
1910+
#endif
1911+
18521912
munmap(mmap, mmap_size);
18531913
return istate->cache_nr;
18541914

0 commit comments

Comments
 (0)