#!/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