|
| 1 | +#!/bin/sh |
| 2 | + |
| 3 | +test_description='performance with large numbers of packs' |
| 4 | +. ./perf-lib.sh |
| 5 | + |
| 6 | +test_perf_large_repo |
| 7 | + |
| 8 | +# A real many-pack situation would probably come from having a lot of pushes |
| 9 | +# over time. We don't know how big each push would be, but we can fake it by |
| 10 | +# just walking the first-parent chain and having every 5 commits be their own |
| 11 | +# "push". This isn't _entirely_ accurate, as real pushes would have some |
| 12 | +# duplicate objects due to thin-pack fixing, but it's a reasonable |
| 13 | +# approximation. |
| 14 | +# |
| 15 | +# And then all of the rest of the objects can go in a single packfile that |
| 16 | +# represents the state before any of those pushes (actually, we'll generate |
| 17 | +# that first because in such a setup it would be the oldest pack, and we sort |
| 18 | +# the packs by reverse mtime inside git). |
| 19 | +repack_into_n () { |
| 20 | + rm -rf staging && |
| 21 | + mkdir staging && |
| 22 | + |
| 23 | + git rev-list --first-parent HEAD | |
| 24 | + sed -n '1~5p' | |
| 25 | + head -n "$1" | |
| 26 | + perl -e 'print reverse <>' \ |
| 27 | + >pushes |
| 28 | + |
| 29 | + # create base packfile |
| 30 | + head -n 1 pushes | |
| 31 | + git pack-objects --delta-base-offset --revs staging/pack |
| 32 | + |
| 33 | + # and then incrementals between each pair of commits |
| 34 | + last= && |
| 35 | + while read rev |
| 36 | + do |
| 37 | + if test -n "$last"; then |
| 38 | + { |
| 39 | + echo "$rev" && |
| 40 | + echo "^$last" |
| 41 | + } | |
| 42 | + git pack-objects --delta-base-offset --revs \ |
| 43 | + staging/pack || return 1 |
| 44 | + fi |
| 45 | + last=$rev |
| 46 | + done <pushes && |
| 47 | + |
| 48 | + # and install the whole thing |
| 49 | + rm -f .git/objects/pack/* && |
| 50 | + mv staging/* .git/objects/pack/ |
| 51 | +} |
| 52 | + |
| 53 | +# Pretend we just have a single branch and no reflogs, and that everything is |
| 54 | +# in objects/pack; that makes our fake pack-building via repack_into_n() |
| 55 | +# much simpler. |
| 56 | +test_expect_success 'simplify reachability' ' |
| 57 | + tip=$(git rev-parse --verify HEAD) && |
| 58 | + git for-each-ref --format="option no-deref%0adelete %(refname)" | |
| 59 | + git update-ref --stdin && |
| 60 | + rm -rf .git/logs && |
| 61 | + git update-ref refs/heads/master $tip && |
| 62 | + git symbolic-ref HEAD refs/heads/master && |
| 63 | + git repack -ad |
| 64 | +' |
| 65 | + |
| 66 | +for nr_packs in 1 50 1000 |
| 67 | +do |
| 68 | + test_expect_success "create $nr_packs-pack scenario" ' |
| 69 | + repack_into_n $nr_packs |
| 70 | + ' |
| 71 | + |
| 72 | + test_perf "rev-list ($nr_packs)" ' |
| 73 | + git rev-list --objects --all >/dev/null |
| 74 | + ' |
| 75 | + |
| 76 | + # This simulates the interesting part of the repack, which is the |
| 77 | + # actual pack generation, without smudging the on-disk setup |
| 78 | + # between trials. |
| 79 | + test_perf "repack ($nr_packs)" ' |
| 80 | + git pack-objects --keep-true-parents \ |
| 81 | + --honor-pack-keep --non-empty --all \ |
| 82 | + --reflog --indexed-objects --delta-base-offset \ |
| 83 | + --stdout </dev/null >/dev/null |
| 84 | + ' |
| 85 | +done |
| 86 | + |
| 87 | +test_done |
0 commit comments