Skip to content

Commit cec0c7b

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 58e7864 commit cec0c7b

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
@@ -19,6 +19,10 @@
1919
#include "split-index.h"
2020
#include "utf8.h"
2121

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

2428
#define CE_NAMEMASK (0x0fff)
@@ -1398,6 +1402,34 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
13981402
return 0;
13991403
}
14001404

1405+
#ifndef NO_PTHREADS
1406+
/*
1407+
* Require index file to be larger than this threshold before
1408+
* we bother using a thread to verify the SHA.
1409+
* This value was arbitrarily chosen.
1410+
*/
1411+
#define VERIFY_HDR_THRESHOLD 10*1024*1024
1412+
1413+
struct verify_hdr_thread_data
1414+
{
1415+
pthread_t thread_id;
1416+
struct cache_header *hdr;
1417+
size_t size;
1418+
int result;
1419+
};
1420+
1421+
/*
1422+
* A thread proc to run the verify_hdr() computation
1423+
* in a background thread.
1424+
*/
1425+
static void *verify_hdr_thread(void *_data)
1426+
{
1427+
struct verify_hdr_thread_data *p = _data;
1428+
p->result = verify_hdr(p->hdr, (unsigned long)p->size);
1429+
return NULL;
1430+
}
1431+
#endif
1432+
14011433
static int read_index_extension(struct index_state *istate,
14021434
const char *ext, void *data, unsigned long sz)
14031435
{
@@ -1585,6 +1617,9 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
15851617
void *mmap;
15861618
size_t mmap_size;
15871619
struct strbuf previous_name_buf = STRBUF_INIT, *previous_name;
1620+
#ifndef NO_PTHREADS
1621+
struct verify_hdr_thread_data verify_hdr_thread_data;
1622+
#endif
15881623

15891624
if (istate->initialized)
15901625
return istate->cache_nr;
@@ -1611,8 +1646,23 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
16111646
close(fd);
16121647

16131648
hdr = mmap;
1649+
#ifdef NO_PTHREADS
16141650
if (verify_hdr(hdr, mmap_size) < 0)
16151651
goto unmap;
1652+
#else
1653+
if (mmap_size < VERIFY_HDR_THRESHOLD) {
1654+
if (verify_hdr(hdr, mmap_size) < 0)
1655+
goto unmap;
1656+
} else {
1657+
verify_hdr_thread_data.hdr = hdr;
1658+
verify_hdr_thread_data.size = mmap_size;
1659+
verify_hdr_thread_data.result = -1;
1660+
if (pthread_create(
1661+
&verify_hdr_thread_data.thread_id, NULL,
1662+
verify_hdr_thread, &verify_hdr_thread_data))
1663+
die_errno("unable to start verify_hdr_thread");
1664+
}
1665+
#endif
16161666

16171667
hashcpy(istate->sha1, (const unsigned char *)hdr + mmap_size - 20);
16181668
istate->version = ntohl(hdr->hdr_version);
@@ -1660,6 +1710,16 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
16601710
src_offset += 8;
16611711
src_offset += extsize;
16621712
}
1713+
1714+
#ifndef NO_PTHREADS
1715+
if (mmap_size >= VERIFY_HDR_THRESHOLD) {
1716+
if (pthread_join(verify_hdr_thread_data.thread_id, NULL))
1717+
die_errno("unable to join verify_hdr_thread");
1718+
if (verify_hdr_thread_data.result < 0)
1719+
goto unmap;
1720+
}
1721+
#endif
1722+
16631723
munmap(mmap, mmap_size);
16641724
return istate->cache_nr;
16651725

0 commit comments

Comments
 (0)