read-cache: call verify_hdr() in a background thread
v2 cover read-cache: call verify_hdr() in a background thread
From: Jeff Hostetler <[email protected]>
Version 2 of this patch series simplifies this to just turn off the hash verification. Independent comments from Linus and Peff suggested that we could just turn this off and not worry about it. So I've updated this patch to do that. I added a global variable to allow the original code path to be used. I also added a t/helper command to demonstrate the differences.
On the Linux repo, the effect is rather trivial:
$ ~/work/gfw/t/helper/test-skip-verify-index -c 3
0.029884 0 [cache_nr 57994]
0.031035 0 [cache_nr 57994]
0.024308 0 [cache_nr 57994]
0.028409 0 avg
0.018359 1 [cache_nr 57994]
0.017025 1 [cache_nr 57994]
0.011087 1 [cache_nr 57994]
0.015490 1 avgOn my Windows source tree (450MB index), I'm seeing a savings of 0.6 seconds -- read_index() went from 1.2 to 0.6 seconds.
=====================
This patch contains a performance optimization to run verify_hdr() in a background thread while the foreground thread parses the index. This allows do_read_index() to complete faster.
This idea was recently discussed on the mailing list in:
https://public-inbox.org/git/[email protected]/
during a discussion on sha1dc.
Our testing on Windows showed that verifying the SHA1 hash on the index file takes approximately the same amount of time as parsing the file and building the array of cache_entries. (It could also be that having 2 threads better ammortizes the page faults of reading from the mmap'd file.)
An earlier version of this change has been in use in GfW since December:
https://github.com/git-for-windows/git/pull/978
Jeff Hostetler (2):
read-cache: skip index SHA verification
skip_verify_index: helper test
Makefile | 1 + cache.h | 5 +++ read-cache.c | 6 ++++ t/helper/.gitignore | 1 + t/helper/test-skip-verify-index.c | 73 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 86 insertions(+) create mode 100644 t/helper/test-skip-verify-index.c
Signature · 1 line
2.7.4
PATCH v2 1/2 read-cache: skip index SHA verification
From: Jeff Hostetler <[email protected]>
Teach git to skip verification of the index SHA in read_index().
This is a performance optimization. The index file SHA verification can be considered an ancient relic from the early days of git and only useful for detecting disk corruption. For small repositories, this SHA calculation is not that significant, but for gigantic repositories this calculation adds significant time to every command.
I added a global "skip_verify_index" variable to control this and allow it to be tested.
I did not create a config setting for this because of chicken-n-egg problems with the loading the config and the index.
--- cache.h | 5 +++++ read-cache.c | 6 ++++++ 2 files changed, 11 insertions(+)
cache.h +5 -0
@@ -740,6 +740,11 @@ extern int protect_ntfs;extern int git_db_env, git_index_env, git_graft_env, git_common_dir_env;/* +* When set, skip verification of the index SHA in read_index(). +*/ +extern int skip_verify_index; + +/* * Include broken refs in all ref iterations, which will * generally choke dangerous operations rather than letting * them silently proceed without taking the broken ref into
read-cache.c +6 -0
@@ -46,6 +46,8 @@struct index_state the_index;static const char *alternate_index_output; +int skip_verify_index =1 ; +static void set_index_entry (struct index_state *istate,int nr,struct cache_entry *ce) { istate->cache[nr] = ce;
@@ -1382,6 +1384,10 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size) hdr_version =ntohl (hdr->hdr_version);if (hdr_version <INDEX_FORMAT_LB ||INDEX_FORMAT_UB < hdr_version)return error ("bad index version %d" , hdr_version); + +if (skip_verify_index) +return 0 ; +git_SHA1_Init (&c);git_SHA1_Update (&c, hdr, size -20 );git_SHA1_Final (sha1, &c);
Signature · 1 line
2.7.4
Re: [PATCH v2 1/2] read-cache: skip index SHA verification
Quoted 10 lines · On Mon, Mar 27, 2017 at 09:09:38PM +0000, [email protected] wrote:
From: Jeff Hostetler <[email protected]>
Teach git to skip verification of the index SHA in
read_index().This is a performance optimization. The index file SHA verification can be considered an ancient relic from the early days of git and only useful for detecting disk corruption. For small repositories, this SHA calculation is not that significant, but for gigantic repositories this calculation adds significant time to every command.
Quoted 5 lines
I added a global "
skip_verify_index" variable to control this and allow it to be tested.I did not create a config setting for this because of chicken-n-egg problems with the loading the config and the index.
Hrm, there shouldn't be any dependency of the config on the index (and there are a handful of options which impact the index already). Did you try it and run into problems?
In general, I'd much rather see us either:
1. Rip the code out entirely if it is not meant to be configurable, and cannot be triggered by the actual git binary.
or
2. Make it configurable, even if most people wouldn't use it. And then have a test to exercise it using a git command (unlike the one-off test helper, which isn't run at all).
-Peff
Re: [PATCH v2 1/2] read-cache: skip index SHA verification
Quoted 6 lines · Jeff King
Hrm, there shouldn't be any dependency of the config on the index (and there are a handful of options which impact the index already). Did you try it and run into problems?
In general, I'd much rather see us either:
Quoted 8 lines
1. Rip the code out entirely if it is not meant to be configurable, and cannot be triggered by the actual git binary.
or
2. Make it configurable, even if most people wouldn't use it. And then have a test to exercise it using a git command (unlike the one-off test helper, which isn't run at all).
Agreed with this, leaning toward (1).
If "git fsck" verifies the .git/index file then I don't see any need for other commands to.
Thanks and hope that helps,
Jonathan
Re: [PATCH v2 1/2] read-cache: skip index SHA verification
Quoted 13 lines · Jonathan Nieder
Quoted 11 lines · Jeff King
Hrm, there shouldn't be any dependency of the config on the index (and there are a handful of options which impact the index already). Did you try it and run into problems?
In general, I'd much rather see us either:
1. Rip the code out entirely if it is not meant to be configurable, and cannot be triggered by the actual git binary.
or
Quoted 8 lines
Quoted 3 lines
2. Make it configurable, even if most people wouldn't use it. And then have a test to exercise it using a git command (unlike the one-off test helper, which isn't run at all).
Agreed with this, leaning toward (1).
If "git fsck" verifies the .git/index file then I don't see any need for other commands to.
Yeah, code that _can_ be run but almost nobody does is possibly worse than code that can't be run. :)
I agree that it would make sense for fsck to check it, though (just like it checks the actual pack trailer checksums, even though normal operations do not).
-Peff
Re: [PATCH v2 1/2] read-cache: skip index SHA verification
In reply to Jeff KingQuoted 15 lines · Jeff King
Quoted 13 lines · On Mon, Mar 27, 2017 at 09:09:38PM +0000, [email protected] wrote:
From: Jeff Hostetler <[email protected]>
Teach git to skip verification of the index SHA in
read_index().This is a performance optimization. The index file SHA verification can be considered an ancient relic from the early days of git and only useful for detecting disk corruption. For small repositories, this SHA calculation is not that significant, but for gigantic repositories this calculation adds significant time to every command.
I added a global "
skip_verify_index" variable to control this and allow it to be tested.
Quoted 6 lines
Quoted 2 lines
I did not create a config setting for this because of chicken-n-egg problems with the loading the config and the index.
Hrm, there shouldn't be any dependency of the config on the index (and there are a handful of options which impact the index already). Did you try it and run into problems?
Yeah, I tried adding a new "core.verifyindex" property and the corresponding global variable. But read_index() and verify_hdr() was being called BEFORE the config was loaded. And it wasn't clear how best to solve that.
The issue was in "git status" where cmd_status() called status_init_config() which called gitmodules_config() before git_config(). but gitmodules_config() called read_index(), so my settings weren't loaded yet in verify_hdr().
I tried switching the order in status_init_config(), but that caused errors in t7508 with submodules not being handled properly.
https://github.com/jeffhostetler/git/commits/upstream/core_verify_index
At this point I decided that it wasn't that important to have this config setting, since we'll probably default it to be faster and be done with it.
Quoted 6 lines
In general, I'd much rather see us either:
1. Rip the code out entirely if it is not meant to be configurable, and cannot be triggered by the actual git binary.
Quoted 8 lines
or
2. Make it configurable, even if most people wouldn't use it. And then have a test to exercise it using a git command (unlike the one-off test helper, which isn't run at all).
-Peff
I'm OK with (1) if everyone else is.
Jeff
Re: [PATCH v2 1/2] read-cache: skip index SHA verification
Quoted 9 lines · Jeff Hostetler
Quoted 3 lines
Hrm, there shouldn't be any dependency of the config on the index (and there are a handful of options which impact the index already). Did you try it and run into problems?
Yeah, I tried adding a new "core.verifyindex" property and the corresponding global variable. But
read_index()andverify_hdr()was being called BEFORE the config was loaded. And it wasn't clear how best to solve that.
Quoted 4 lines
The issue was in "git status" where
cmd_status()calledstatus_init_config()which calledgitmodules_config()beforegit_config(). butgitmodules_config()calledread_index(), so my settings weren't loaded yet inverify_hdr().
Ugh, yeah, the callback-oriented interface suffers from these kind of dependency cycles. You can fix it by doing a limited "basic config that should always be loaded" git_config() call before anything else, and then following up with the application-level config.
For something low-level that should _always_ be respected, even in plumbing programs, I think we're better off lazy-loading the config inside the function. The configset cache makes them more or less free.
I.e., something like:
read-cache.c +11 -5
@@ -1376,17 +1376,23 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)git_SHA_CTX c;unsigned char sha1[20 ];int hdr_version; +int do_checksum =0 ;if (hdr->hdr_signature !=htonl (CACHE_SIGNATURE ))return error ("bad signature" ); hdr_version =ntohl (hdr->hdr_version);if (hdr_version <INDEX_FORMAT_LB ||INDEX_FORMAT_UB < hdr_version)return error ("bad index version %d" , hdr_version); -git_SHA1_Init (&c); -git_SHA1_Update (&c, hdr, size -20 ); -git_SHA1_Final (sha1, &c); -if (hashcmp (sha1, (unsigned char *)hdr + size -20 )) -return error ("bad index file sha1 signature" ); + +git_config_get_bool ("core.checksumindex" , &do_checksum); +if (do_checksum) { +git_SHA1_Init (&c); +git_SHA1_Update (&c, hdr, size -20 ); +git_SHA1_Final (sha1, &c); +if (hashcmp (sha1, (unsigned char *)hdr + size -20 )) +return error ("bad index file sha1 signature" ); + } +return 0 ; }
-Peff
PATCH v2 2/2 skip_verify_index: helper test
In reply to [email protected]From: Jeff Hostetler <[email protected]>
Created test to measure read_index() with and without skip_verify_index set and report performance differences.
--- Makefile | 1 + t/helper/.gitignore | 1 + t/helper/test-skip-verify-index.c | 73 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 t/helper/test-skip-verify-index.c
Makefile +1 -0
@@ -631,6 +631,7 @@ TEST_PROGRAMS_NEED_X += test-scrap-cache-tree TEST_PROGRAMS_NEED_X += test-sha1 TEST_PROGRAMS_NEED_X += test-sha1-array TEST_PROGRAMS_NEED_X += test-sigchain +TEST_PROGRAMS_NEED_X += test-skip-verify-index TEST_PROGRAMS_NEED_X += test-string-list TEST_PROGRAMS_NEED_X += test-submodule-config TEST_PROGRAMS_NEED_X += test-subprocess
t/helper/.gitignore +1 -0
@@ -25,6 +25,7 @@ /test-sha1 /test-sha1-array /test-sigchain +/test-skip-verify-index /test-string-list /test-submodule-config /test-subprocess
t/helper/test-skip-verify-index.c new file +73 -0
73 lines not on this page · raw message
Signature · 1 line
2.7.4
Quoted 22 lines · On Mon, Mar 27, 2017 at 09:09:37PM +0000, [email protected] wrote:
From: Jeff Hostetler <[email protected]>
Version 2 of this patch series simplifies this to just turn off the hash verification. Independent comments from Linus and Peff suggested that we could just turn this off and not worry about it. So I've updated this patch to do that. I added a global variable to allow the original code path to be used. I also added a t/helper command to demonstrate the differences.
On the Linux repo, the effect is rather trivial:
$ ~/work/gfw/t/helper/test-skip-verify-index -c 3 0.029884 0 [cache_nr 57994] 0.031035 0 [cache_nr 57994] 0.024308 0 [cache_nr 57994] 0.028409 0 avg 0.018359 1 [cache_nr 57994] 0.017025 1 [cache_nr 57994] 0.011087 1 [cache_nr 57994] 0.015490 1 avg
Quoted 3 lines
On my Windows source tree (450MB index), I'm seeing a savings of 0.6 seconds --
read_index()went from 1.2 to 0.6 seconds.
Very satisfying. I assume that was with OpenSSL as the SHA-1 implementation (sha1dc would have been much slower on 450MB, I think).
-Peff
Quoted 24 lines · Jeff King
Quoted 22 lines · On Mon, Mar 27, 2017 at 09:09:37PM +0000, [email protected] wrote:
From: Jeff Hostetler <[email protected]>
Version 2 of this patch series simplifies this to just turn off the hash verification. Independent comments from Linus and Peff suggested that we could just turn this off and not worry about it. So I've updated this patch to do that. I added a global variable to allow the original code path to be used. I also added a t/helper command to demonstrate the differences.
On the Linux repo, the effect is rather trivial:
$ ~/work/gfw/t/helper/test-skip-verify-index -c 3 0.029884 0 [cache_nr 57994] 0.031035 0 [cache_nr 57994] 0.024308 0 [cache_nr 57994] 0.028409 0 avg 0.018359 1 [cache_nr 57994] 0.017025 1 [cache_nr 57994] 0.011087 1 [cache_nr 57994] 0.015490 1 avg
Quoted 9 lines
Quoted 3 lines
On my Windows source tree (450MB index), I'm seeing a savings of 0.6 seconds --
read_index()went from 1.2 to 0.6 seconds.Very satisfying. I assume that was with OpenSSL as the SHA-1 implementation (sha1dc would have been much slower on 450MB, I think).
-Peff
Yes, this was with the OpenSSL SHA-1 code in a GfW build. I haven't played with the sha1dc code yet.
$ $/work/gh_gfw/t/helper/test-skip-verify-index.exe -c 5 1.276485 0 [cache_nr 3077831] 1.261164 0 [cache_nr 3077831] 1.256012 0 [cache_nr 3077831] 1.261411 0 [cache_nr 3077831] 1.266174 0 [cache_nr 3077831] 1.264249 0 avg 0.672057 1 [cache_nr 3077831] 0.666968 1 [cache_nr 3077831] 0.668725 1 [cache_nr 3077831] 0.675879 1 [cache_nr 3077831] 0.670213 1 [cache_nr 3077831] 0.670768 1 avg
Jeff