Skip to content

Commit c1e2e2e

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 43bcfe7 commit c1e2e2e

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

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

17641799
if (istate->initialized)
17651800
return istate->cache_nr;
@@ -1786,8 +1821,23 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
17861821
close(fd);
17871822

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

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

0 commit comments

Comments
 (0)