git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 11/11] perf: add a bisection tool

From
Thomas Rast <trast@student.ethz.ch>
Date
Mar 12, 2012, 16:27 UTC
Message-ID
<4d8e9b13f6fe755ed16c3f8f180a8f4cf4ec7199.1331561353.git.trast@student.ethz.ch>
In-Reply-To
<cover.1331561353.git.trast@student.ethz.ch>

Using the perf suite for bisection is not hard with all the features recently added; you can say

  git bisect start --no-checkout
  git bisect bad BAD
  git bisect good GOOD
  # repeat until done:
  ./run BISECT_HEAD ^BAD ^GOOD
  git bisect {good|bad}

This script does the bulk of the work for the user. You can for example say

  ./bisect_slowdown p4000.3 v1.7.0 v1.7.10-rc0

to bisect the ~5% performance hit incurred by 3e5a188 (diff.c: Ensure "index $from..$to" line contains unambiguous SHA1s, 2010-05-30). The main output is quite noisy, but you can follow test-results/bisect.log for a more concise summary of the results and decisions taken.

The heuristic applied is that if the result for BISECT_HEAD is scaled between GOOD and BAD, then anything <0.25 must be good and >0.75 must be bad. Put in terms of differences towards the good and bad sides, it decides in favor of the smaller one if they are at least a factor of 3 apart.

Anything in the middle punts and asks for help. You may then for example re-run with more iterations to improve the measurements, or manually edit the test script to make it more expensive (but remember that you also need to re-test BAD and GOOD in this case!). Once you have told git-bisect your decision, you can restart the script to let it continue the search.

Points of note:
* Performance regressions are not a binary event, so the search may
  not find anything reasonable.  For example, there is a ~6% hit in
  p3400.4 between adc3b2b27..a9f578685, but because it is spread
  across 13 commits, a bisection can only determine the general area.
* The default settings do not have high enough S/N in the timings to
  give good results.  Try setting GIT_PERF_REPEAT_COUNT to around 8.
* Many CPUs have a dynamic overclocking feature (such as Intel Turbo
  Boost) that helps single-process performance.  Running other things
  in parallel may prevent it from working.  The difference may be
  larger than 20% and will usually drown out the performance hit you
  are bisecting for.
Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---
 t/perf/bisect_slowdown |   88 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)
 create mode 100755 t/perf/bisect_slowdown
diff --git a/t/perf/bisect_slowdown b/t/perf/bisect_slowdown
new file mode 100755
index 0000000..8b58b8d
--- /dev/null
+++ b/t/perf/bisect_slowdown
@@ -0,0 +1,88 @@
+#!/bin/sh
+
+test=$1
+good=$2
+bad=$3
+
+subtest=${test#p????.}
+maintest=${test%%.*}
+
+export subtest maintest
+
+export GIT_PERF_TEST_ONLY=$test
+
+goodrev=$(git rev-parse "$good^{commit}")
+badrev=$(git rev-parse "$bad^{commit}")
+
+git_dir=$(git rev-parse --git-dir)
+perfdir=$(cd "$(dirname "$0")" && pwd)
+log="$perfdir/test-results/bisect.log"
+
+export good bad goodrev badrev perfdir log
+
+if ! test -s "$git_dir/BISECT_LOG"; then
+	# Establish initial timings for the endpoints
+	echo "## Before bisection: comparing $good (good) and $bad (bad)" >"$log"
+	GIT_PERF_AGGREGATING_LATER=t ./run "$good" "$bad" -- "$maintest"*.sh
+	./aggregate.perl "$good" "$bad" -- "$maintest"*.sh | tee -a "$log"
+
+	cd "$perfdir/../.."
+
+	echo "## Starting bisection between $good (good) and $bad (bad)" >>"$log"
+	git bisect start --no-checkout
+	git bisect good "$good"
+	git bisect bad "$bad"
+else
+	cd "$perfdir/../.."
+fi
+
+git bisect run sh -c '
+	cd "$perfdir"
+	echo "## Testing $(git log --no-walk --format="%h %s" BISECT_HEAD)" >>"$log"
+	GIT_PERF_AGGREGATING_LATER=t ./run BISECT_HEAD -- "$maintest"*.sh
+	./aggregate.perl BISECT_HEAD "$good" "$bad" -- "$maintest"*.sh | tee -a "$log"
+	tested=$(git rev-parse BISECT_HEAD)
+	perl -e '\''
+		open STDOUT, "|-", "tee", "-a", "'"$log"'" or die "failed to spawn tee: $!";
+		sub avg {
+			open my $fp, "<$_" or die "cannot open $_: $!";
+			my $s = 0;
+			my $n = 0;
+			while (<$fp>) {
+				if (/^(\d+\.\d+)/) {
+					$s += $1;
+					$n++;
+				}
+			}
+			close $fp or die "cannot close: $!";
+			return $s/$n;
+		}
+		my ($good,$bad,$test) = map { avg $_ } @ARGV;
+		if ($good == $bad) { die "good = bad?" };
+		my $ratio = ($test-$good)/($bad-$good);
+		if ($ratio < 0.25) {
+			print "# Result: GOOD!\n";
+			exit 0;
+		} elsif ($ratio > 0.75) {
+			print "# Result: BAD!\n";
+			exit 42;
+		} else {
+			print "# INCONCLUSIVE.\n";
+			print "# Please check manually, say git bisect good/bad, and restart me!\n";
+			exit 1;
+		}
+	'\'' \
+		test-results/build_"$goodrev"."$maintest"*."$subtest".times \
+		test-results/build_"$badrev"."$maintest"*."$subtest".times \
+		test-results/build_"$tested"."$maintest"*."$subtest".times
+	ret=$?
+	test $ret = 0 && exit 0
+	test $ret = 42 && exit 1
+	exit 255
+' || exit $?
+
+cd "$perfdir"
+echo "## Double-checking $(git log --no-walk --format="%h %s" bisect/bad)" >>"$log"
+GIT_PERF_AGGREGATING_LATER=t ./run bisect/bad^ bisect/bad -- "$maintest"*.sh
+git show bisect/bad
+./aggregate.perl bisect/bad^ bisect/bad -- "$maintest"*.sh | tee -a "$log"
-- 
1.7.10.rc0.230.g16d90
Previous: Thomas Rast
Message 20 of 20 in “perf improvements past v1.7.10”
  1. 00/11 perf improvements past v1.7.10Thomas Rast, Mar 12, 2012
  2. 01/11 perf/aggregate: load Git.pm from the build treeThomas Rast, Mar 12, 2012
  3. 02/11 Introduce a performance test for git-rebaseThomas Rast, Mar 12, 2012
  4. Thomas RastMar 12, 2012
  5. Junio C HamanoMar 12, 2012
  6. Thomas RastMar 12, 2012
  7. Junio C HamanoMar 12, 2012
  8. 03/11 Introduce a performance test for git-blameThomas Rast, Mar 12, 2012
  9. 04/11 perf: display average instead of minimum timeThomas Rast, Mar 12, 2012
  10. 05/11 perf: suppress aggregation also in 'run'Thomas Rast, Mar 12, 2012
  11. 06/11 perf: dereference to a commit when buildingThomas Rast, Mar 12, 2012
  12. 07/11 perf: convert realtime to seconds when collecting runsThomas Rast, Mar 12, 2012
  13. 08/11 perf/aggregate: optionally include a t-test scoreThomas Rast, Mar 12, 2012
  14. 09/11 perf/run: allow skipping some revisionsThomas Rast, Mar 12, 2012
  15. Nguyen Thai Ngoc DuyMar 12, 2012
  16. Thomas RastMar 12, 2012
  17. Jakub NarebskiMar 12, 2012
  18. Thomas RastMar 12, 2012
  19. 10/11 perf: implement a test-selection featureThomas Rast, Mar 12, 2012
  20. 11/11 perf: add a bisection toolThomas Rast, Mar 12, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.