• R/O
  • HTTP
  • SSH
  • HTTPS

提交

标签
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

GNU Binutils with patches for OS216


Commit MetaInfo

修订版81208388898d0d561dc0c167b8bb7b2d77e40381 (tree)
时间2013-11-05 03:02:11
作者Tom Tromey <tromey@redh...>
CommiterTom Tromey

Log Message

switch to fully parallel mode

This switches "make check" to fully parallel mode.

One primary issue facing full parallelization is the overhead of
"runtest". On my machine, if I "touch gdb.base/empty.exp", making a
new file, and then "time runtest.exp", it takes 0.08 seconds.

Multiply this by the 1008 (in my configuration) tests and you get ~80
seconds. This is the overhead that would theoretically be present if
all tests were run in parallel.

However, the problem isn't nearly as bad as this, for two reasons.

First, you must divide by the number of jobs, assuming perfect
parallelization -- reasonably true for small -j numbers, based on the
results I see.

Second, the current test suite parallelization approach bundles the
tests, largely by directory, but also splitting up gdb.base into two
halves.

I was curious to see how the current bundling played out in practice,
so I ran "make -j1 check RUNTEST='/bin/time runtest'". This invokes
the parallel mode (thus the bundling) and then shows the time taken by
each invocation of runtest.

Then, I ran "/bin/time make -j3 check". (See below about -j2.)

The time for the entire -j3 test run was the same as the time for
"gdb.base1". What this means is that gdb.base1 is currently the
time-limiting run, preventing further parallelization gains.

So, I reason, whatever overhead we see from full parallelization will
only be seen by "-j1" and "-j2".

I then tried a -j2 test run. This does take longer than a -j3 build,
meaning that the gdb.base1 job finishes and then proceeds to other
runtest invocations.

Finally I tried a -j2 test run with the appended patch.
This was 9% slower than the -j2 run without the patch.

I think that is a reasonable slowdown for what is probably a rare
case. I believe this patch will yield faster test results for all -j
values greater than 2. For -j3 on my machine, the test suite is a few
seconds faster; I didn't try any larger -j values.

For -j1, I went ahead and changed the Makefile so that, if no -j
option is given, then the "check-single" mode is used. You can still
use "make -j1 check" to get single-job parallel-mode, though of course
there's no good reason to do so.

This change is likely to speed up the plain "make check" scenario a
little as we will now bypass dg-extract-results.sh.

One drawback of this change is that "make -jN check" is now much more
verbose. I generally only look at the .sum and .log files, but
perhaps this will bother some.

Another interesting question is scalability of the result. The
slowest test, which limits the scalability, took 80.78 seconds. The
mean of the remaining tests is 1.08 seconds. (Note that this is just
a rough estimate, since there are still outliers.)

This means we can run 80.78 / 1.08 =~ 74 tests in the time available.
And, in this data set (slightly older than the above, but materially
the same) there were 948 tests. So, I think the current test suite
should scale ok up to about -j12.

We could improve this number if need be by breaking up the biggest
tests.

2013-11-04 Tom Tromey <tromey@redhat.com>

* Makefile.in (TEST_DIRS): Remove.
(TEST_TARGETS, check-parallel): Rewrite.
(check-gdb.%, BASE1_FILES, BASE2_FILES, check-gdb.base%)
(subdir_do, subdirs): Remove.
(do-check-parallel, check/%): New targets.
(clean): Remove outputs, temp, and cache directories.
(saw_dash_j): New variable.
(CHECK_TARGET): Use it.
(check): Depend on all, site.exp. Rewrite.
(check-single): Remove dependencies.
(slow_tests, all_tests, reordered_tests): New variables.

更改概述

差异

--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,19 @@
11 2013-11-04 Tom Tromey <tromey@redhat.com>
22
3+ * Makefile.in (TEST_DIRS): Remove.
4+ (TEST_TARGETS, check-parallel): Rewrite.
5+ (check-gdb.%, BASE1_FILES, BASE2_FILES, check-gdb.base%)
6+ (subdir_do, subdirs): Remove.
7+ (do-check-parallel, check/%): New targets.
8+ (clean): Remove outputs, temp, and cache directories.
9+ (saw_dash_j): New variable.
10+ (CHECK_TARGET): Use it.
11+ (check): Depend on all, site.exp. Rewrite.
12+ (check-single): Remove dependencies.
13+ (slow_tests, all_tests, reordered_tests): New variables.
14+
15+2013-11-04 Tom Tromey <tromey@redhat.com>
16+
317 * gdb.dwarf2/fission-base.S: Remove "gdb.dwarf/".
418 * gdb.dwarf2/fission-base.exp: Set debug-file-directory
519 before loading binfile.
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -128,14 +128,23 @@ $(abs_builddir)/site.exp site.exp: ./config.status Makefile
128128
129129 installcheck:
130130
131-# For GNU make, try to run the tests in parallel. If RUNTESTFLAGS is
132-# not empty, then by default the tests will be serialized. This can
133-# be overridden by setting FORCE_PARALLEL to any non-empty value.
134-# For a non-GNU make, do not parallelize.
135-@GMAKE_TRUE@CHECK_TARGET = $(if $(FORCE_PARALLEL),check-parallel,$(if $(RUNTESTFLAGS),check-single,check-parallel))
131+# See whether -j was given to make. Either it was given with no
132+# arguments, and appears as "j" in the first word, or it was given an
133+# argument and appears as "-j" in a separate word.
134+@GMAKE_TRUE@saw_dash_j = $(or $(findstring j,$(firstword $(MAKEFLAGS))),$(filter -j,$(MAKEFLAGS)))
135+
136+# For GNU make, try to run the tests in parallel if any -j option is
137+# given. If RUNTESTFLAGS is not empty, then by default the tests will
138+# be serialized. This can be overridden by setting FORCE_PARALLEL to
139+# any non-empty value. For a non-GNU make, do not parallelize.
140+@GMAKE_TRUE@CHECK_TARGET = $(if $(FORCE_PARALLEL),check-parallel,$(if $(RUNTESTFLAGS),check-single,$(if $(saw_dash_j),check-parallel,check-single)))
136141 @GMAKE_FALSE@CHECK_TARGET = check-single
137142
138-check: $(CHECK_TARGET)
143+# Note that we must resort to a recursive make invocation here,
144+# because GNU make 3.82 has a bug preventing MAKEFLAGS from being used
145+# in conditions.
146+check: all $(abs_builddir)/site.exp
147+ $(MAKE) $(CHECK_TARGET)
139148
140149 # All the hair to invoke dejagnu. A given invocation can just append
141150 # $(RUNTESTFLAGS)
@@ -151,70 +160,45 @@ DO_RUNTEST = \
151160 export TCL_LIBRARY ; fi ; \
152161 $(RUNTEST)
153162
154-check-single: all $(abs_builddir)/site.exp
163+check-single:
155164 $(DO_RUNTEST) $(RUNTESTFLAGS)
156165
157-# A list of all directories named "gdb.*" which also hold a .exp file.
158-# We filter out gdb.base and add fake entries, because that directory
159-# takes the longest to process, and so we split it in half.
160-TEST_DIRS = gdb.base1 gdb.base2 $(filter-out gdb.base,$(sort $(notdir $(patsubst %/,%,$(dir $(wildcard $(srcdir)/gdb.*/*.exp))))))
161-
162-TEST_TARGETS = $(addprefix check-,$(TEST_DIRS))
163-
164-# We explicitly re-invoke make here for two reasons. First, it lets
165-# us add a -k option, which makes the parallel check mimic the
166-# behavior of the serial check; and second, it means that we can still
167-# regenerate the sum and log files even if a sub-make fails -- which
168-# it usually does because dejagnu exits with an error if any test
169-# fails.
170166 check-parallel:
171- $(MAKE) -k $(TEST_TARGETS); \
167+ -rm -rf cache
168+ $(MAKE) -k do-check-parallel; \
172169 $(SHELL) $(srcdir)/dg-extract-results.sh \
173- $(addsuffix /gdb.sum,$(TEST_DIRS)) > gdb.sum; \
170+ `find outputs -name gdb.sum -print` > gdb.sum; \
174171 $(SHELL) $(srcdir)/dg-extract-results.sh -L \
175- $(addsuffix /gdb.log,$(TEST_DIRS)) > gdb.log
176-
177-@GMAKE_TRUE@$(filter-out check-gdb.base%,$(TEST_TARGETS)): check-gdb.%: all $(abs_builddir)/site.exp
178-@GMAKE_TRUE@ @if test ! -d gdb.$*; then mkdir gdb.$*; fi
179-@GMAKE_TRUE@ $(DO_RUNTEST) --directory=gdb.$* --outdir=gdb.$* $(RUNTESTFLAGS)
180-
181-# Each half (roughly) of the .exp files from gdb.base.
182-BASE1_FILES = $(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/gdb.base/[a-m]*.exp))
183-BASE2_FILES = $(patsubst $(srcdir)/%,%,$(wildcard $(srcdir)/gdb.base/[n-z]*.exp))
184-
185-# Handle each half of gdb.base.
186-check-gdb.base%: all $(abs_builddir)/site.exp
187- @if test ! -d gdb.base$*; then mkdir gdb.base$*; fi
188- $(DO_RUNTEST) $(BASE$*_FILES) --outdir gdb.base$* $(RUNTESTFLAGS)
189-
190-subdir_do: force
191- @for i in $(DODIRS); do \
192- if [ -d ./$$i ] ; then \
193- if (rootme=`pwd`/ ; export rootme ; \
194- rootsrc=`cd $(srcdir); pwd`/ ; export rootsrc ; \
195- cd ./$$i; \
196- $(MAKE) $(TARGET_FLAGS_TO_PASS) $(DO)) ; then true ; \
197- else exit 1 ; fi ; \
198- else true ; fi ; \
199- done
172+ `find outputs -name gdb.log -print` > gdb.log
173+
174+# Turn a list of .exp files into "check/" targets. Only examine .exp
175+# files appearing in a gdb.* directory -- we don't want to pick up
176+# lib/ by mistake. For example, gdb.linespec/linespec.exp becomes
177+# check/gdb.linespec/linespec.exp. The list is generally sorted
178+# alphabetically, but we take a few tests known to be slow and push
179+# them to the front of the list to try to lessen the overall time
180+# taken by the test suite -- if one of these tests happens to be run
181+# late, it will cause the overall time to increase.
182+slow_tests = gdb.base/break-interp.exp gdb.base/interp.exp \
183+ gdb.base/multi-forks.exp
184+@GMAKE_TRUE@all_tests := $(shell cd $(srcdir) && find gdb.* -name '*.exp' -print)
185+@GMAKE_TRUE@reordered_tests := $(slow_tests) $(filter-out $(slow_tests),$(all_tests))
186+@GMAKE_TRUE@TEST_TARGETS := $(addprefix check/,$(reordered_tests))
187+
188+do-check-parallel: $(TEST_TARGETS)
189+ @:
190+
191+@GMAKE_TRUE@check/%.exp:
192+@GMAKE_TRUE@ -mkdir -p outputs/$*
193+@GMAKE_TRUE@ @$(DO_RUNTEST) GDB_PARALLEL=yes --outdir=outputs/$* $*.exp $(RUNTESTFLAGS)
200194
201195 force:;
202196
203-subdirs:
204- for dir in ${ALL_SUBDIRS} ; \
205- do \
206- echo "$$dir:" ; \
207- if [ -d $$dir ] ; then \
208- (rootme=`pwd`/ ; export rootme ; \
209- rootsrc=`cd $(srcdir); pwd`/ ; export rootsrc ; \
210- cd $$dir; $(MAKE) $(TARGET_FLAGS_TO_PASS)); \
211- fi; \
212- done
213-
214197 clean mostlyclean:
215198 -rm -f *~ core *.o a.out xgdb *.x *.grt bigcore.corefile .gdb_history
216199 -rm -f core.* *.tf *.cl *.py tracecommandsscript copy1.txt zzz-gdbscript
217200 -rm -f *.dwo *.dwp
201+ -rm -rf outputs temp cache
218202 if [ x"${ALL_SUBDIRS}" != x ] ; then \
219203 for dir in ${ALL_SUBDIRS}; \
220204 do \