enhance: implement fast path for repository local change status update when core.fsmonitor and core.untrackedcache are enabled
#2012
+110
−16
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Finally this experiment has come to a stage where it's reviewable. It is still very early. Opinions are welcome. Binaries for testing (win-x64 only) can be downloaded here: https://github.com/AlanIWBFT/sourcegit/releases
Problem it aims to solve: #1998
To accurately report and let the user pick each individual untracked file, SourceGit uses
--untracked-files=all(-uall) when doingQueryLocalChanges, which is unfortunately very slow on large repositories.core.fsmonitorandcore.untrackedcachecannot help this case if-uallis specified as it makes the untracked cache bypassed, yielding no performance improvement.This pull request detects if
core.fsmonitorandcore.untrackedcacheare enabled and uses a two pass algorithm: it runs a normalgit statusfirst to retrive a list of untracked directories (which is fast as untracked cache is functioning here), then rungit status -uallonly on these dirs. The time it takes to traverse these dirs are much faster than running-uallon the entire repository.To use this experimental feature, the user must deliberately enable
core.fsmonitorandcore.untrackedcache, or not settingcore.untrackedcachebut settingfeature.manyfilestotrue.Components
First, to robustly detect if the fast path is possible,
Commands.Config.GetBoolAsyncis added which leverages git itself to canonicalize possible weird values in config files, like "000" will be intepreted as "false", "010" -> "true".Every time you open a repository the above detection is performed. If they are enabled, a normal, index-locking 'git status' will be run to populate/update the untracked cache. The first time will be slow as the cache needs to be populated entirely from empty. Subsequent runs will be much faster, in fact, negligible. (~0.4s on UE5-main). Thus the slow-down on UI start-up isn't very noticable expect for the first time. Since SourceGit always runs
git statuswith--no-optional-lockswhich means the index will not be modified, the untracked cache thus cannot be updated either, once SourceGit is up. So we need a place to insert the update, and it is scheduled when you open the repository, as said above.Performance results
On large repos like UE5, a consistent ~5x - ~6x speedup is observed whenever a status update is needed and the responsiveness is greatly improved.
Other fixes
As we've discussed in #1998 (comment),
Stash.PushAsyncbool includeUntracked's default value has been changed tofalse. The intention is to let git handle the untracked instead of manually stash them (which was performed with--included-untracked, very slow (2x slower than the slow status update)).