From fd9dbdfb3dc934a88b8b7505ab01db949a294a4e Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 13 May 2016 15:25:51 +0200 Subject: perf: let's disable symlinks when they are not available We already have a perfectly fine prereq to tell us whether it is safe to use symlinks. So let's use it. This fixes the performance tests in Git for Windows' SDK, where symlinks are not really available ([*1*]). This is not an issue with Git for Windows itself because it configures core.symlinks=false in its system config. However, the system config is disabled for the performance tests, for obvious reasons: we want them to be independent of the vagaries of any local configuration. Footnote *1*: Windows has symbolic links. Git for Windows disables them by default, though (for example: in standard setups, non-admins lack the privilege to create symbolic links). For details, see https://github.com/git-for-windows/git/wiki/Symbolic-Links Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- t/perf/perf-lib.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index 5cf74eddec..9fa07066d1 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -96,7 +96,10 @@ test_perf_create_repo_from () { esac done && cd .. && - git init -q && + git init -q && { + test_have_prereq SYMLINKS || + git config core.symlinks false + } && mv .git/hooks .git/hooks-disabled 2>/dev/null ) || error "failed to copy repository '$source' to '$repo'" } -- cgit v1.2.3 From 7501b59210906c89747dca1c44e15d8c2214c01d Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 13 May 2016 15:25:58 +0200 Subject: perf: make the tests work in worktrees This patch makes perf-lib.sh more robust so that it can run correctly even inside a worktree. For example, it assumed that $GIT_DIR/objects is the objects directory (which is not the case for worktrees) and it used the commondir file verbatim, even if it contained a relative path. Furthermore, the setup code expected `git rev-parse --git-dir` to spit out a relative path, which is also not true for worktrees. Let's just change the code to accept both relative and absolute paths, by avoiding the `cd` into the copied working directory. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- t/perf/perf-lib.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh index 9fa07066d1..5ef17440c0 100644 --- a/t/perf/perf-lib.sh +++ b/t/perf/perf-lib.sh @@ -80,22 +80,22 @@ test_perf_create_repo_from () { error "bug in the test script: not 2 parameters to test-create-repo" repo="$1" source="$2" - source_git=$source/$(cd "$source" && git rev-parse --git-dir) + source_git="$(git -C "$source" rev-parse --git-dir)" + objects_dir="$(git -C "$source" rev-parse --git-path objects)" mkdir -p "$repo/.git" ( - cd "$repo/.git" && - { cp -Rl "$source_git/objects" . 2>/dev/null || - cp -R "$source_git/objects" .; } && + { cp -Rl "$objects_dir" "$repo/.git/" 2>/dev/null || + cp -R "$objects_dir" "$repo/.git/"; } && for stuff in "$source_git"/*; do case "$stuff" in - */objects|*/hooks|*/config) + */objects|*/hooks|*/config|*/commondir) ;; *) - cp -R "$stuff" . || exit 1 + cp -R "$stuff" "$repo/.git/" || exit 1 ;; esac done && - cd .. && + cd "$repo" && git init -q && { test_have_prereq SYMLINKS || git config core.symlinks false -- cgit v1.2.3 From e4cfe74cd083c15947f57760d05d0e286a585afc Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 13 May 2016 15:26:03 +0200 Subject: perf: run "rebase -i" under perf This developer spent a lot of time trying to speed up the interactive rebase, in particular on Windows. And will continue to do so. To make it easier to demonstrate the performance improvement, let's have a reproducible performance test. The topic branch we use to test performance was found using these shell commands (essentially searching for a long-enough topic branch in Git's own history that touched the same file multiple times): git rev-list --parents origin/master | grep ' .* ' | while read commit rest do patch_count=$(git rev-list --count $commit^..$commit^2) test $patch_count -gt 20 || continue merges="$(git rev-list --parents $commit^..$commit^2 | grep ' .* ')" test -z "$merges" || continue patches_per_file="$(git log --pretty=%H --name-only \ $commit^..$commit^2 | grep -v '^$' | sort | uniq -c -d | sort -n -r)" test -n "$patches_per_file" && test 20 -lt $(echo "$patches_per_file" | sed -n '1s/^ *\([0-9]*\).*/\1/p') || continue printf 'commit %s\n%s\n' "$commit" "$patches_per_file" done Note that we can get away with *not* having to reset to the original branch tip before rebasing: we switch the first two "pick" lines every time, so we end up with the same patch order after two rebases, and the complexity of both rebases is equivalent. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- t/perf/p3404-rebase-interactive.sh | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100755 t/perf/p3404-rebase-interactive.sh diff --git a/t/perf/p3404-rebase-interactive.sh b/t/perf/p3404-rebase-interactive.sh new file mode 100755 index 0000000000..88f47de282 --- /dev/null +++ b/t/perf/p3404-rebase-interactive.sh @@ -0,0 +1,36 @@ +#!/bin/sh + +test_description='Tests rebase -i performance' +. ./perf-lib.sh + +test_perf_default_repo + +# This commit merges a sufficiently long topic branch for reasonable +# performance testing +branch_merge=ba5312da19c6fdb6c6747d479f58932aae6e900c^{commit} +export branch_merge + +git rev-parse --verify $branch_merge >/dev/null 2>&1 || { + skip_all='skipping because $branch_merge was not found' + test_done +} + +write_script swap-first-two.sh <<\EOF +case "$1" in +*/COMMIT_EDITMSG) + mv "$1" "$1".bak && + sed -e '1{h;d}' -e 2G <"$1".bak >"$1" + ;; +esac +EOF + +test_expect_success 'setup' ' + git config core.editor "\"$PWD"/swap-first-two.sh\" && + git checkout -f $branch_merge^2 +' + +test_perf 'rebase -i' ' + git rebase -i $branch_merge^ +' + +test_done -- cgit v1.2.3