summaryrefslogtreecommitdiff
path: root/t/perf
diff options
context:
space:
mode:
Diffstat (limited to 't/perf')
-rw-r--r--t/perf/README12
-rwxr-xr-xt/perf/p3400-rebase.sh36
-rwxr-xr-xt/perf/p4211-line-log.sh6
-rwxr-xr-xt/perf/p5303-many-packs.sh87
-rw-r--r--t/perf/perf-lib.sh5
5 files changed, 140 insertions, 6 deletions
diff --git a/t/perf/README b/t/perf/README
index 8848c14619..49ea4349be 100644
--- a/t/perf/README
+++ b/t/perf/README
@@ -115,8 +115,16 @@ After that you will want to use some of the following:
At least one of the first two is required!
-You can use test_expect_success as usual. For actual performance
-tests, use
+You can use test_expect_success as usual. In both test_expect_success
+and in test_perf, running "git" points to the version that is being
+perf-tested. The $MODERN_GIT variable points to the git wrapper for the
+currently checked-out version (i.e., the one that matches the t/perf
+scripts you are running). This is useful if your setup uses commands
+that only work with newer versions of git than what you might want to
+test (but obviously your new commands must still create a state that can
+be used by the older version of git you are testing).
+
+For actual performance tests, use
test_perf 'descriptive string' '
command1 &&
diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh
new file mode 100755
index 0000000000..b3e7d525d2
--- /dev/null
+++ b/t/perf/p3400-rebase.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+
+test_description='Tests rebase performance'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+test_expect_success 'setup' '
+ git checkout -f -b base &&
+ git checkout -b to-rebase &&
+ git checkout -b upstream &&
+ for i in $(seq 100)
+ do
+ # simulate huge diffs
+ echo change$i >unrelated-file$i &&
+ seq 1000 >>unrelated-file$i &&
+ git add unrelated-file$i &&
+ test_tick &&
+ git commit -m commit$i unrelated-file$i &&
+ echo change$i >unrelated-file$i &&
+ seq 1000 | tac >>unrelated-file$i &&
+ git add unrelated-file$i &&
+ test_tick &&
+ git commit -m commit$i-reverse unrelated-file$i ||
+ break
+ done &&
+ git checkout to-rebase &&
+ test_commit our-patch interesting-file
+'
+
+test_perf 'rebase on top of a lot of unrelated changes' '
+ git rebase --onto upstream HEAD^ &&
+ git rebase --onto base HEAD^
+'
+
+test_done
diff --git a/t/perf/p4211-line-log.sh b/t/perf/p4211-line-log.sh
index 3d074b0e41..b7ff68d4fa 100755
--- a/t/perf/p4211-line-log.sh
+++ b/t/perf/p4211-line-log.sh
@@ -23,11 +23,11 @@ test_perf 'git log --follow (baseline for -M)' '
git log --oneline --follow -- "$file" >/dev/null
'
-test_perf 'git log -L' '
- git log -L 1:"$file" >/dev/null
+test_perf 'git log -L (renames off)' '
+ git log --no-renames -L 1:"$file" >/dev/null
'
-test_perf 'git log -M -L' '
+test_perf 'git log -L (renames on)' '
git log -M -L 1:"$file" >/dev/null
'
diff --git a/t/perf/p5303-many-packs.sh b/t/perf/p5303-many-packs.sh
new file mode 100755
index 0000000000..3779851941
--- /dev/null
+++ b/t/perf/p5303-many-packs.sh
@@ -0,0 +1,87 @@
+#!/bin/sh
+
+test_description='performance with large numbers of packs'
+. ./perf-lib.sh
+
+test_perf_large_repo
+
+# A real many-pack situation would probably come from having a lot of pushes
+# over time. We don't know how big each push would be, but we can fake it by
+# just walking the first-parent chain and having every 5 commits be their own
+# "push". This isn't _entirely_ accurate, as real pushes would have some
+# duplicate objects due to thin-pack fixing, but it's a reasonable
+# approximation.
+#
+# And then all of the rest of the objects can go in a single packfile that
+# represents the state before any of those pushes (actually, we'll generate
+# that first because in such a setup it would be the oldest pack, and we sort
+# the packs by reverse mtime inside git).
+repack_into_n () {
+ rm -rf staging &&
+ mkdir staging &&
+
+ git rev-list --first-parent HEAD |
+ sed -n '1~5p' |
+ head -n "$1" |
+ perl -e 'print reverse <>' \
+ >pushes
+
+ # create base packfile
+ head -n 1 pushes |
+ git pack-objects --delta-base-offset --revs staging/pack
+
+ # and then incrementals between each pair of commits
+ last= &&
+ while read rev
+ do
+ if test -n "$last"; then
+ {
+ echo "$rev" &&
+ echo "^$last"
+ } |
+ git pack-objects --delta-base-offset --revs \
+ staging/pack || return 1
+ fi
+ last=$rev
+ done <pushes &&
+
+ # and install the whole thing
+ rm -f .git/objects/pack/* &&
+ mv staging/* .git/objects/pack/
+}
+
+# Pretend we just have a single branch and no reflogs, and that everything is
+# in objects/pack; that makes our fake pack-building via repack_into_n()
+# much simpler.
+test_expect_success 'simplify reachability' '
+ tip=$(git rev-parse --verify HEAD) &&
+ git for-each-ref --format="option no-deref%0adelete %(refname)" |
+ git update-ref --stdin &&
+ rm -rf .git/logs &&
+ git update-ref refs/heads/master $tip &&
+ git symbolic-ref HEAD refs/heads/master &&
+ git repack -ad
+'
+
+for nr_packs in 1 50 1000
+do
+ test_expect_success "create $nr_packs-pack scenario" '
+ repack_into_n $nr_packs
+ '
+
+ test_perf "rev-list ($nr_packs)" '
+ git rev-list --objects --all >/dev/null
+ '
+
+ # This simulates the interesting part of the repack, which is the
+ # actual pack generation, without smudging the on-disk setup
+ # between trials.
+ test_perf "repack ($nr_packs)" '
+ git pack-objects --keep-true-parents \
+ --honor-pack-keep --non-empty --all \
+ --reflog --indexed-objects --delta-base-offset \
+ --stdout </dev/null >/dev/null
+ '
+done
+
+test_done
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index 773f955d4a..46f08ee087 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -52,6 +52,9 @@ TEST_NO_MALLOC_CHECK=t
# need to export them for test_perf subshells
export TEST_DIRECTORY TRASH_DIRECTORY GIT_BUILD_DIR GIT_TEST_CMP
+MODERN_GIT=$GIT_BUILD_DIR/bin-wrappers/git
+export MODERN_GIT
+
perf_results_dir=$TEST_OUTPUT_DIRECTORY/test-results
mkdir -p "$perf_results_dir"
rm -f "$perf_results_dir"/$(basename "$0" .sh).subtests
@@ -81,7 +84,7 @@ test_perf_create_repo_from () {
repo="$1"
source="$2"
source_git="$(git -C "$source" rev-parse --git-dir)"
- objects_dir="$(git -C "$source" rev-parse --git-path objects)"
+ objects_dir="$("$MODERN_GIT" -C "$source" rev-parse --git-path objects)"
mkdir -p "$repo/.git"
(
cd "$source" &&