Add git config-batch support for improved Windows performance #2245
+1,550
−1
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.
This PR adds support for the new
git config-batchcommand to significantly improve config read performance on Windows platforms. The implementation uses a single persistent process for multiple config reads, reducing process spawn overhead.This change creates
GitBatchConfigurationwhich implements theIGitConfigurationand contains a child_fallbackimplementation that uses the standard one-process-per-request model. For interactions that are known to not work with mygit config-batchdraft, it's a simple pass-through.However, the
TryGet()method is able to check for the process to work.We lazy-load the process so it doesn't attempt starting one until some config is requested. If
git config-batchfails to run, then we mark the class state as not being compatible and go straight to the fallback mechanism.The
git config-batchcommand will exit when an empty line is read or whenstdincloses, so we don't need to watch it too closely as ourgit-credential-managerprocess dies.There are thread-safe locks so we do not get parallel reads interfering with our writing to or reading from the singleton
git config-batchprocess. These locks should be extremely short after the initial process startup.Performance Results
All tests performed on Windows using a test copy of my Git branch, merged with microsoft/git.
Table 1: Core Performance Benchmarks
Table 2: Real-World Impact on Azure DevOps Repository
Testing performed on a production Azure DevOps monorepo with typical credential configuration.
Impact: Every
git fetch,git push, andgit cloneoperation requiring credentials will be ~660ms faster.Note that this gets even better when using the
microsoft/gitfork and the GVFS Protocol, as each instance ofgit-gvfs-helpergets its own credential interactions and is separate from theinfo/refsauthentication, so these improvements stack across a complicated process such asgit pullthat runsgit fetchandgit merge(not to mention possible customizations that rungit fetchandgit sparse-checkout setwithin thepost-commandhook). I did not do extensive end-to-end testing on these cases as they are difficult to repeat. However, in my local enlistment I was looking at telemetry and saw as much as 20 seconds spent ingit-credential-managerin a singlegit pullprocess without any user prompts causing delays.Table 3: Speedup Summary by Workload
Test Execution
All tests can be run using: