Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 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 | |
Jeff King | f08b6c5 | 2021-01-29 15:04:08 -0500 | [diff] [blame] | 24 | perl -e ' |
| 25 | my $n = shift; |
| 26 | while (<>) { |
| 27 | last unless @commits < $n; |
| 28 | push @commits, $_ if $. % 5 == 1; |
| 29 | } |
| 30 | print reverse @commits; |
Jeff King | 60bb5f2 | 2021-02-22 21:25:13 -0500 | [diff] [blame] | 31 | ' "$1" >pushes && |
Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 32 | |
| 33 | # create base packfile |
Jeff King | fbf20ae | 2021-02-22 21:25:17 -0500 | [diff] [blame] | 34 | base_pack=$( |
| 35 | head -n 1 pushes | |
| 36 | git pack-objects --delta-base-offset --revs staging/pack |
| 37 | ) && |
| 38 | test_export base_pack && |
| 39 | |
| 40 | # create an empty packfile |
| 41 | empty_pack=$(git pack-objects staging/pack </dev/null) && |
| 42 | test_export empty_pack && |
Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 43 | |
| 44 | # and then incrementals between each pair of commits |
| 45 | last= && |
| 46 | while read rev |
| 47 | do |
| 48 | if test -n "$last"; then |
| 49 | { |
| 50 | echo "$rev" && |
| 51 | echo "^$last" |
| 52 | } | |
| 53 | git pack-objects --delta-base-offset --revs \ |
| 54 | staging/pack || return 1 |
| 55 | fi |
| 56 | last=$rev |
| 57 | done <pushes && |
| 58 | |
Jeff King | fbf20ae | 2021-02-22 21:25:17 -0500 | [diff] [blame] | 59 | ( |
| 60 | find staging -type f -name 'pack-*.pack' | |
| 61 | xargs -n 1 basename | grep -v "$base_pack" && |
| 62 | printf "^pack-%s.pack\n" $base_pack |
| 63 | ) >stdin.packs |
| 64 | |
Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 65 | # and install the whole thing |
| 66 | rm -f .git/objects/pack/* && |
| 67 | mv staging/* .git/objects/pack/ |
| 68 | } |
| 69 | |
| 70 | # Pretend we just have a single branch and no reflogs, and that everything is |
| 71 | # in objects/pack; that makes our fake pack-building via repack_into_n() |
| 72 | # much simpler. |
| 73 | test_expect_success 'simplify reachability' ' |
| 74 | tip=$(git rev-parse --verify HEAD) && |
| 75 | git for-each-ref --format="option no-deref%0adelete %(refname)" | |
| 76 | git update-ref --stdin && |
| 77 | rm -rf .git/logs && |
| 78 | git update-ref refs/heads/master $tip && |
| 79 | git symbolic-ref HEAD refs/heads/master && |
| 80 | git repack -ad |
| 81 | ' |
| 82 | |
| 83 | for nr_packs in 1 50 1000 |
| 84 | do |
| 85 | test_expect_success "create $nr_packs-pack scenario" ' |
| 86 | repack_into_n $nr_packs |
| 87 | ' |
| 88 | |
| 89 | test_perf "rev-list ($nr_packs)" ' |
| 90 | git rev-list --objects --all >/dev/null |
| 91 | ' |
| 92 | |
Jeff King | 67bb65d | 2020-09-17 12:47:43 -0400 | [diff] [blame] | 93 | test_perf "abbrev-commit ($nr_packs)" ' |
| 94 | git rev-list --abbrev-commit HEAD >/dev/null |
| 95 | ' |
| 96 | |
Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 97 | # This simulates the interesting part of the repack, which is the |
| 98 | # actual pack generation, without smudging the on-disk setup |
| 99 | # between trials. |
| 100 | test_perf "repack ($nr_packs)" ' |
Jeff King | f66e040 | 2019-11-11 06:12:49 -0500 | [diff] [blame] | 101 | GIT_TEST_FULL_IN_PACK_ARRAY=1 \ |
Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 102 | git pack-objects --keep-true-parents \ |
| 103 | --honor-pack-keep --non-empty --all \ |
| 104 | --reflog --indexed-objects --delta-base-offset \ |
| 105 | --stdout </dev/null >/dev/null |
| 106 | ' |
Jeff King | fbf20ae | 2021-02-22 21:25:17 -0500 | [diff] [blame] | 107 | |
| 108 | test_perf "repack with kept ($nr_packs)" ' |
| 109 | git pack-objects --keep-true-parents \ |
| 110 | --keep-pack=pack-$empty_pack.pack \ |
| 111 | --honor-pack-keep --non-empty --all \ |
| 112 | --reflog --indexed-objects --delta-base-offset \ |
| 113 | --stdout </dev/null >/dev/null |
| 114 | ' |
| 115 | |
| 116 | test_perf "repack with --stdin-packs ($nr_packs)" ' |
| 117 | git pack-objects \ |
| 118 | --keep-true-parents \ |
| 119 | --stdin-packs \ |
| 120 | --non-empty \ |
| 121 | --delta-base-offset \ |
| 122 | --stdout <stdin.packs >/dev/null |
| 123 | ' |
Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 124 | done |
| 125 | |
Colin Stolley | ec48540 | 2019-11-27 16:24:53 -0600 | [diff] [blame] | 126 | # Measure pack loading with 10,000 packs. |
| 127 | test_expect_success 'generate lots of packs' ' |
| 128 | for i in $(test_seq 10000); do |
Eric Sunshine | 74d2f56 | 2021-12-09 00:11:06 -0500 | [diff] [blame] | 129 | echo "blob" && |
| 130 | echo "data <<EOF" && |
| 131 | echo "blob $i" && |
| 132 | echo "EOF" && |
Eric Sunshine | db5875a | 2021-12-09 00:11:12 -0500 | [diff] [blame] | 133 | echo "checkpoint" || return 1 |
Colin Stolley | ec48540 | 2019-11-27 16:24:53 -0600 | [diff] [blame] | 134 | done | |
| 135 | git -c fastimport.unpackLimit=0 fast-import |
| 136 | ' |
| 137 | |
| 138 | # The purpose of this test is to evaluate load time for a large number |
| 139 | # of packs while doing as little other work as possible. |
| 140 | test_perf "load 10,000 packs" ' |
| 141 | git rev-parse --verify "HEAD^{commit}" |
| 142 | ' |
| 143 | |
Jeff King | 77023ea | 2016-07-29 00:06:09 -0400 | [diff] [blame] | 144 | test_done |