Skip to content

Commit fe2aa19

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 ce1e904 commit fe2aa19

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)
@@ -1554,6 +1558,34 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
15541558
return 0;
15551559
}
15561560

1561+
#ifndef NO_PTHREADS
1562+
/*
1563+
* Require index file to be larger than this threshold before
1564+
* we bother using a thread to verify the SHA.
1565+
* This value was arbitrarily chosen.
1566+
*/
1567+
#define VERIFY_HDR_THRESHOLD 10*1024*1024
1568+
1569+
struct verify_hdr_thread_data
1570+
{
1571+
pthread_t thread_id;
1572+
struct cache_header *hdr;
1573+
size_t size;
1574+
int result;
1575+
};
1576+
1577+
/*
1578+
* A thread proc to run the verify_hdr() computation
1579+
* in a background thread.
1580+
*/
1581+
static void *verify_hdr_thread(void *_data)
1582+
{
1583+
struct verify_hdr_thread_data *p = _data;
1584+
p->result = verify_hdr(p->hdr, (unsigned long)p->size);
1585+
return NULL;
1586+
}
1587+
#endif
1588+
15571589
static int read_index_extension(struct index_state *istate,
15581590
const char *ext, void *data, unsigned long sz)
15591591
{
@@ -1759,6 +1791,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
17591791
void *mmap;
17601792
size_t mmap_size;
17611793
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
1794+
#ifndef NO_PTHREADS
1795+
struct verify_hdr_thread_data verify_hdr_thread_data;
1796+
#endif
17621797

17631798
if (istate->initialized)
17641799
return istate->cache_nr;
@@ -1785,8 +1820,23 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
17851820
close(fd);
17861821

17871822
hdr = mmap;
1823+
#ifdef NO_PTHREADS
17881824
if (verify_hdr(hdr, mmap_size) < 0)
17891825
goto unmap;
1826+
#else
1827+
if (mmap_size < VERIFY_HDR_THRESHOLD) {
1828+
if (verify_hdr(hdr, mmap_size) < 0)
1829+
goto unmap;
1830+
} else {
1831+
verify_hdr_thread_data.hdr = hdr;
1832+
verify_hdr_thread_data.size = mmap_size;
1833+
verify_hdr_thread_data.result = -1;
1834+
if (pthread_create(
1835+
&verify_hdr_thread_data.thread_id, NULL,
1836+
verify_hdr_thread, &verify_hdr_thread_data))
1837+
die_errno("unable to start verify_hdr_thread");
1838+
}
1839+
#endif
17901840

17911841
hashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - 20);
17921842
istate->version = ntohl(hdr->hdr_version);
@@ -1834,6 +1884,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
18341884
src_offset += 8;
18351885
src_offset += extsize;
18361886
}
1887+
1888+
#ifndef NO_PTHREADS
1889+
if (mmap_size >= VERIFY_HDR_THRESHOLD) {
1890+
if (pthread_join(verify_hdr_thread_data.thread_id, NULL))
1891+
die_errno("unable to join verify_hdr_thread");
1892+
if (verify_hdr_thread_data.result < 0)
1893+
goto unmap;
1894+
}
1895+
#endif
1896+
18371897
munmap(mmap, mmap_size);
18381898
return istate->cache_nr;
18391899

0 commit comments

Comments
 (0)