t / perf / p5303-many-packs.shon commit Merge branch 'nd/command-list-gen-fix' (ca6e972)
   1#!/bin/sh
   2
   3test_description='performance with large numbers of packs'
   4. ./perf-lib.sh
   5
   6test_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).
  19repack_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.
  56test_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
  66for nr_packs in 1 50 1000
  67do
  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        '
  85done
  86
  87test_done