From fc9ecbeb93d3c4fae2439e1d9c5346052a1796c2 Mon Sep 17 00:00:00 2001 From: Ben Peart Date: Mon, 5 Feb 2018 14:56:19 -0500 Subject: [PATCH 1/2] dir.c: don't flag the index as dirty for changes to the untracked cache The untracked cache saves its current state in the UNTR index extension. Currently, _any_ change to that state causes the index to be flagged as dirty and written out to disk. Unfortunately, the cost to write out the index can exceed the savings gained by using the untracked cache. Since it is a cache that can be updated from the current state of the working directory, there is no functional requirement that the index be written out for every change to the untracked cache. Update the untracked cache logic so that it no longer forces the index to be written to disk except in the case where the extension is being turned on or off. When some other git command requires the index to be written to disk, the untracked cache will take advantage of that to save it's updated state as well. This results in a performance win when looked at over common sequences of git commands (ie such as a status followed by add, commit, etc). After this patch, all the logic to track statistics for the untracked cache could be removed as it is only used by debug tracing used to debug the untracked cache. Signed-off-by: Ben Peart Signed-off-by: Junio C Hamano --- dir.c | 3 ++- t/t7063-status-untracked-cache.sh | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/dir.c b/dir.c index 7c4b45e30e0..da93374f0c7 100644 --- a/dir.c +++ b/dir.c @@ -2297,7 +2297,8 @@ int read_directory(struct dir_struct *dir, struct index_state *istate, dir->untracked->gitignore_invalidated, dir->untracked->dir_invalidated, dir->untracked->dir_opened); - if (dir->untracked == istate->untracked && + if (getenv("GIT_TEST_UNTRACKED_CACHE") && + dir->untracked == istate->untracked && (dir->untracked->dir_opened || dir->untracked->gitignore_invalidated || dir->untracked->dir_invalidated)) diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index e5fb892f957..6ef520e8237 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -14,6 +14,9 @@ test_description='test untracked cache' # See <20160803174522.5571-1-pclouds@gmail.com> if you want to know # more. +GIT_TEST_UNTRACKED_CACHE=true +export GIT_TEST_UNTRACKED_CACHE + sync_mtime () { find . -type d -ls >/dev/null } From 026336cb277693c5a8cdfa4705a26daf0a754328 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 28 Feb 2018 13:21:09 -0800 Subject: [PATCH 2/2] untracked cache: use git_env_bool() not getenv() for customization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GIT_DISABLE_UNTRACKED_CACHE and GIT_TEST_UNTRACKED_CACHE are only sensed for their presense by using getenv(); use git_env_bool() instead so that GIT_DISABLE_UNTRACKED_CACHE=false would work as naïvely expected. Also rename GIT_TEST_UNTRACKED_CACHE to GIT_FORCE_UNTRACKED_CACHE to express what it does more honestly. Forcing its use may be one useful thing to do while testing the feature, but testing does not have to be the only use of the knob. While at it, avoid repeated calls to git_env_bool() by capturing the return value from the first call in a static variable. Signed-off-by: Junio C Hamano --- dir.c | 14 ++++++++++++-- t/t7063-status-untracked-cache.sh | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/dir.c b/dir.c index da93374f0c7..d445d77e626 100644 --- a/dir.c +++ b/dir.c @@ -2164,8 +2164,13 @@ static struct untracked_cache_dir *validate_untracked_cache(struct dir_struct *d const struct pathspec *pathspec) { struct untracked_cache_dir *root; + static int untracked_cache_disabled = -1; - if (!dir->untracked || getenv("GIT_DISABLE_UNTRACKED_CACHE")) + if (!dir->untracked) + return NULL; + if (untracked_cache_disabled < 0) + untracked_cache_disabled = git_env_bool("GIT_DISABLE_UNTRACKED_CACHE", 0); + if (untracked_cache_disabled) return NULL; /* @@ -2287,7 +2292,12 @@ int read_directory(struct dir_struct *dir, struct index_state *istate, } if (dir->untracked) { + static int force_untracked_cache = -1; static struct trace_key trace_untracked_stats = TRACE_KEY_INIT(UNTRACKED_STATS); + + if (force_untracked_cache < 0) + force_untracked_cache = + git_env_bool("GIT_FORCE_UNTRACKED_CACHE", 0); trace_printf_key(&trace_untracked_stats, "node creation: %u\n" "gitignore invalidation: %u\n" @@ -2297,7 +2307,7 @@ int read_directory(struct dir_struct *dir, struct index_state *istate, dir->untracked->gitignore_invalidated, dir->untracked->dir_invalidated, dir->untracked->dir_opened); - if (getenv("GIT_TEST_UNTRACKED_CACHE") && + if (force_untracked_cache && dir->untracked == istate->untracked && (dir->untracked->dir_opened || dir->untracked->gitignore_invalidated || diff --git a/t/t7063-status-untracked-cache.sh b/t/t7063-status-untracked-cache.sh index 6ef520e8237..9cb16ca36da 100755 --- a/t/t7063-status-untracked-cache.sh +++ b/t/t7063-status-untracked-cache.sh @@ -14,8 +14,8 @@ test_description='test untracked cache' # See <20160803174522.5571-1-pclouds@gmail.com> if you want to know # more. -GIT_TEST_UNTRACKED_CACHE=true -export GIT_TEST_UNTRACKED_CACHE +GIT_FORCE_UNTRACKED_CACHE=true +export GIT_FORCE_UNTRACKED_CACHE sync_mtime () { find . -type d -ls >/dev/null