With the new --valgrind-parallel=<n> option, we support running the
tests in a single test script under valgrind in parallel using 'n'
processes.

This really follows the dumbest approach possible, as follows:

* We spawn the test script 'n' times, using a throw-away
  TEST_OUTPUT_DIRECTORY.  Each of the instances is given options that
  ensures that it only runs every n-th test under valgrind, but
  together they cover the entire range.

* We add up the numbers from the individual tests, and provide the
  usual output.

This is really a gross hack at this point, and should be improved.  In
particular we should keep the actual outputs somewhere more easily
discoverable, and summarize them to the user.

Nevertheless, this is already workable and gives a speedup of more
than 2 on a dual-core (hyperthreaded) machine, using n=4.  This is
expected since the overhead of valgrind is so big (on the order of 20x
under good conditions, and a large startup overhead at every git
invocation) that redundantly running the non-valgrind tests in between
is not that expensive.

Signed-off-by: Thomas Rast <tr...@inf.ethz.ch>
---
 t/test-lib.sh | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 55 insertions(+), 5 deletions(-)

diff --git a/t/test-lib.sh b/t/test-lib.sh
index 55fa749..b4e81bc 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -204,6 +204,15 @@ do
        --valgrind-only=*)
                valgrind_only=$(expr "z$1" : 'z[^=]*=\(.*\)')
                shift ;;
+       --valgrind-parallel=*)
+               valgrind_parallel=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
+       --valgrind-only-stride=*)
+               valgrind_only_stride=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
+       --valgrind-only-offset=*)
+               valgrind_only_offset=$(expr "z$1" : 'z[^=]*=\(.*\)')
+               shift ;;
        --tee)
                shift ;; # was handled already
        --root=*)
@@ -217,7 +226,7 @@ do
        esac
 done
 
-if test -n "$valgrind_only"
+if test -n "$valgrind_only" || test -n "$valgrind_only_stride"
 then
        test -z "$valgrind" && valgrind=memcheck
        test -z "$verbose" && verbose_only="$valgrind_only"
@@ -359,8 +368,10 @@ match_pattern_list () {
 }
 
 toggle_verbose () {
-       test -z "$verbose_only" && return
-       if match_pattern_list $test_count $verbose_only
+       test -z "$verbose_only" && test -z "$valgrind_only_stride" && return
+       if match_pattern_list $test_count $verbose_only ||
+               { test -n "$valgrind_only_stride" &&
+               expr $test_count "%" $valgrind_only_stride - 
$valgrind_only_offset = 0 >/dev/null; }
        then
                exec 4>&2 3>&1
        else
@@ -370,7 +381,7 @@ toggle_verbose () {
 
 toggle_valgrind () {
        test -z "$GIT_VALGRIND" && return
-       if test -z "$valgrind_only"
+       if test -z "$valgrind_only" && test -z "$valgrind_only_stride"
        then
                GIT_VALGRIND_ENABLED=t
                return
@@ -379,6 +390,10 @@ toggle_valgrind () {
        if match_pattern_list $test_count $valgrind_only
        then
                GIT_VALGRIND_ENABLED=t
+       elif test -n "$valgrind_only_stride" &&
+               expr $test_count "%" $valgrind_only_stride - 
$valgrind_only_offset = 0 >/dev/null
+       then
+               GIT_VALGRIND_ENABLED=t
        fi
 }
 
@@ -600,7 +615,10 @@ then
        GIT_VALGRIND_MODE="$valgrind"
        export GIT_VALGRIND_MODE
        GIT_VALGRIND_ENABLED=t
-       test -n "$valgrind_only" && GIT_VALGRIND_ENABLED=
+       if test -n "$valgrind_only" || test -n "$valgrind_only_stride"
+       then
+               GIT_VALGRIND_ENABLED=
+       fi
        export GIT_VALGRIND_ENABLED
 elif test -n "$GIT_TEST_INSTALLED"
 then
@@ -686,6 +704,38 @@ then
 else
        mkdir -p "$TRASH_DIRECTORY"
 fi
+
+if test -n "$valgrind_parallel"
+then
+       for i in $(test_seq 1 $valgrind_parallel)
+       do
+               root="$TRASH_DIRECTORY/vgparallel-$i"
+               mkdir "$root"
+               TEST_OUTPUT_DIRECTORY="$root" \
+                       ${SHELL_PATH} "$0" \
+                       --root="$root" --statusprefix="[$i] " \
+                       --valgrind="$valgrind" \
+                       --valgrind-only-stride="$valgrind_parallel" \
+                       --valgrind-only-offset="$i" &
+               pids="$pids $!"
+       done
+       trap "kill $pids" INT TERM HUP
+       wait $pids
+       trap - INT TERM HUP
+       for i in $(test_seq 1 $valgrind_parallel)
+       do
+               root="$TRASH_DIRECTORY/vgparallel-$i"
+               eval "$(cat "$root/test-results/$(basename "$0" .sh)"-*.counts |
+                       sed 's/^\([a-z][a-z]*\) \([0-9][0-9]*\)/inner_\1=\2/')"
+               test_count=$(expr $test_count + $inner_total)
+               test_success=$(expr $test_success + $inner_success)
+               test_fixed=$(expr $test_fixed + $inner_fixed)
+               test_broken=$(expr $test_broken + $inner_broken)
+               test_failed=$(expr $test_failed + $inner_failed)
+       done
+       test_done
+fi
+
 # Use -P to resolve symlinks in our working directory so that the cwd
 # in subprocesses like git equals our $PWD (for pathname comparisons).
 cd -P "$TRASH_DIRECTORY" || exit 1
-- 
1.8.3.rc2.393.g8636c0b

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to