87 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			87 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable file
		
	
	
	
	
#!/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
 |