Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions Documentation/config/checkout.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ commands or functionality in the future.

`checkout.workers`::
The number of parallel workers to use when updating the working tree.
The default is one, i.e. sequential execution. If set to a value less
than one, Git will use as many workers as the number of logical cores
available. This setting and `checkout.thresholdForParallelism` affect
all commands that perform checkout. E.g. checkout, clone, reset,
sparse-checkout, etc.
The default is one, i.e. sequential execution, except on Windows,
where it is four. If set to a value less than one, Git will use as
many workers as the number of logical cores available. This setting
and `checkout.thresholdForParallelism` affect all commands that
perform checkout. E.g. checkout, clone, reset, sparse-checkout, etc.
+
On Windows the number of workers is capped at 62, because the `poll()`
emulation cannot wait on more worker pipes than that. A higher configured
Expand All @@ -46,4 +46,4 @@ well the parallel version performs.
of subprocess spawning and inter-process communication might outweigh
the parallelization gains. This setting allows you to define the minimum
number of files for which parallel checkout should be attempted. The
default is 100.
default is 100 (500 on Windows).
9 changes: 9 additions & 0 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,15 @@ int is_valid_win32_path(const char *path, int allow_literal_nul);
*/
#define MAX_LONG_PATH 4096

/*
* Replacing a file in the worktree (unlink, create, write, close) costs
* a few hundred microseconds on Windows, and parallel checkout overlaps
* that cost well. Starting a worker costs tens of milliseconds, though,
* so only use workers for checkouts that touch at least 500 files.
*/
#define PARALLEL_CHECKOUT_DEFAULT_WORKERS 4
#define PARALLEL_CHECKOUT_DEFAULT_THRESHOLD 500

/**
* Handles paths that would exceed the MAX_PATH limit of Windows Unicode APIs.
*
Expand Down
12 changes: 10 additions & 2 deletions parallel-checkout.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,16 @@ enum pc_status parallel_checkout_status(void)
return parallel_checkout.status;
}

static const int DEFAULT_THRESHOLD_FOR_PARALLELISM = 100;
static const int DEFAULT_NUM_WORKERS = 1;
#ifndef PARALLEL_CHECKOUT_DEFAULT_THRESHOLD
#define PARALLEL_CHECKOUT_DEFAULT_THRESHOLD 100
#endif

#ifndef PARALLEL_CHECKOUT_DEFAULT_WORKERS
#define PARALLEL_CHECKOUT_DEFAULT_WORKERS 1
#endif

static const int DEFAULT_THRESHOLD_FOR_PARALLELISM = PARALLEL_CHECKOUT_DEFAULT_THRESHOLD;
static const int DEFAULT_NUM_WORKERS = PARALLEL_CHECKOUT_DEFAULT_WORKERS;

void get_parallel_checkout_configs(int *num_workers, int *threshold)
{
Expand Down
45 changes: 45 additions & 0 deletions t/t2080-parallel-checkout-basics.sh
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,49 @@ test_expect_success MINGW 'checkout caps workers at the poll limit' '
verify_checkout many-workers
'

# On Windows, parallel checkout is on by default (four workers), but only
# for checkouts of at least 500 files; elsewhere it is off by default.
test_expect_success 'default workers and threshold' '
test_when_finished "rm -rf default-workers" &&
git init default-workers &&
(
cd default-workers &&
mkdir dir &&
for i in $(test_seq 1 500)
do
echo "content $i" >dir/file$i || return 1
done &&
git add -A &&
git commit -q -m base &&
git tag base &&

git checkout -q -b few &&
for i in $(test_seq 1 499)
do
echo "changed $i" >dir/file$i || return 1
done &&
git commit -q -a -m few &&

git checkout -q -b many base &&
for i in $(test_seq 1 500)
do
echo "changed $i" >dir/file$i || return 1
done &&
git commit -q -a -m many &&
git checkout -q base
) &&

if test_have_prereq MINGW
then
expected_workers=4
else
expected_workers=0
fi &&
test_checkout_workers 0 git -C default-workers checkout few &&
verify_checkout default-workers &&
git -C default-workers checkout -q base &&
test_checkout_workers $expected_workers git -C default-workers checkout many &&
verify_checkout default-workers
'

test_done