Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Unified Diff: tools/run_perf.py

Issue 1215273003: [test] Let perf runner interleave try executions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Review Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tools/unittests/run_perf_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/run_perf.py
diff --git a/tools/run_perf.py b/tools/run_perf.py
index b13e9179c01341c48b89fc5fe9d2e9ef49672f1e..dbe5020f180f568b0fb967b86a340cf2593f517d 100755
--- a/tools/run_perf.py
+++ b/tools/run_perf.py
@@ -215,7 +215,28 @@ class Measurement(object):
}], self.errors)
-def AccumulateResults(graph_names, trace_configs, iter_output, calc_total):
+class NullMeasurement(object):
+ """Null object to avoid having extra logic for configurations that didn't
+ run like running without patch on trybots.
+ """
+ def ConsumeOutput(self, stdout):
+ pass
+
+ def GetResults(self):
+ return Results()
+
+
+def Unzip(iterable):
+ left = []
+ right = []
+ for l, r in iterable:
+ left.append(l)
+ right.append(r)
+ return lambda: iter(left), lambda: iter(right)
+
+
+def AccumulateResults(
+ graph_names, trace_configs, iter_output, trybot, no_patch, calc_total):
"""Iterates over the output of multiple benchmark reruns and accumulates
results for a configured list of traces.
@@ -225,10 +246,14 @@ def AccumulateResults(graph_names, trace_configs, iter_output, calc_total):
trace_configs: List of "TraceConfig" instances. Each trace config defines
how to perform a measurement.
iter_output: Iterator over the standard output of each test run.
+ trybot: Indicates that this is run in trybot mode, i.e. run twice, once
+ with once without patch.
+ no_patch: Indicates weather this is a trybot run without patch.
calc_total: Boolean flag to speficy the calculation of a summary trace.
Returns: A "Results" object.
"""
- measurements = [trace.CreateMeasurement() for trace in trace_configs]
+ measurements = [
+ trace.CreateMeasurement(trybot, no_patch) for trace in trace_configs]
for stdout in iter_output():
for measurement in measurements:
measurement.ConsumeOutput(stdout)
@@ -271,6 +296,9 @@ def AccumulateGenericResults(graph_names, suite_units, iter_output):
"""
traces = OrderedDict()
for stdout in iter_output():
+ if stdout is None:
+ # The None value is used as a null object to simplify logic.
+ continue
for line in stdout.strip().splitlines():
match = GENERIC_RESULTS_RE.match(line)
if match:
@@ -394,7 +422,11 @@ class TraceConfig(GraphConfig):
super(TraceConfig, self).__init__(suite, parent, arch)
assert self.results_regexp
- def CreateMeasurement(self):
+ def CreateMeasurement(self, trybot, no_patch):
+ if not trybot and no_patch:
+ # Use null object for no-patch logic if this is not a trybot run.
+ return NullMeasurement()
+
return Measurement(
self.graphs,
self.units,
@@ -428,9 +460,27 @@ class RunnableConfig(GraphConfig):
cmd = [os.path.join(shell_dir, self.binary)]
return cmd + self.GetCommandFlags(extra_flags=extra_flags)
- def Run(self, runner):
+ def Run(self, runner, trybot):
"""Iterates over several runs and handles the output for all traces."""
- return AccumulateResults(self.graphs, self._children, runner, self.total)
+ stdout_with_patch, stdout_no_patch = Unzip(runner())
+ return (
+ AccumulateResults(
+ self.graphs,
+ self._children,
+ iter_output=stdout_with_patch,
+ trybot=trybot,
+ no_patch=False,
+ calc_total=self.total,
+ ),
+ AccumulateResults(
+ self.graphs,
+ self._children,
+ iter_output=stdout_no_patch,
+ trybot=trybot,
+ no_patch=True,
+ calc_total=self.total,
+ ),
+ )
class RunnableTraceConfig(TraceConfig, RunnableConfig):
@@ -438,12 +488,17 @@ class RunnableTraceConfig(TraceConfig, RunnableConfig):
def __init__(self, suite, parent, arch):
super(RunnableTraceConfig, self).__init__(suite, parent, arch)
- def Run(self, runner):
+ def Run(self, runner, trybot):
"""Iterates over several runs and handles the output."""
- measurement = self.CreateMeasurement()
- for stdout in runner():
- measurement.ConsumeOutput(stdout)
- return measurement.GetResults()
+ measurement_with_patch = self.CreateMeasurement(trybot, False)
+ measurement_no_patch = self.CreateMeasurement(trybot, True)
+ for stdout_with_patch, stdout_no_patch in runner():
+ measurement_with_patch.ConsumeOutput(stdout_with_patch)
+ measurement_no_patch.ConsumeOutput(stdout_no_patch)
+ return (
+ measurement_with_patch.GetResults(),
+ measurement_no_patch.GetResults(),
+ )
class RunnableGenericConfig(RunnableConfig):
@@ -451,8 +506,12 @@ class RunnableGenericConfig(RunnableConfig):
def __init__(self, suite, parent, arch):
super(RunnableGenericConfig, self).__init__(suite, parent, arch)
- def Run(self, runner):
- return AccumulateGenericResults(self.graphs, self.units, runner)
+ def Run(self, runner, trybot):
+ stdout_with_patch, stdout_no_patch = Unzip(runner())
+ return (
+ AccumulateGenericResults(self.graphs, self.units, stdout_with_patch),
+ AccumulateGenericResults(self.graphs, self.units, stdout_no_patch),
+ )
def MakeGraphConfig(suite, arch, parent):
@@ -514,6 +573,7 @@ def FlattenRunnables(node, node_cb):
class Platform(object):
def __init__(self, options):
self.shell_dir = options.shell_dir
+ self.shell_dir_no_patch = options.shell_dir_no_patch
self.extra_flags = options.extra_flags.split()
@staticmethod
@@ -523,6 +583,27 @@ class Platform(object):
else:
return DesktopPlatform(options)
+ def _Run(self, runnable, count, no_patch=False):
+ raise NotImplementedError() # pragma: no cover
+
+ def Run(self, runnable, count):
+ """Execute the benchmark's main file.
+
+ If options.shell_dir_no_patch is specified, the benchmark is run once with
+ and once without patch.
+ Args:
+ runnable: A Runnable benchmark instance.
+ count: The number of this (repeated) run.
+ Returns: A tuple with the benchmark outputs with and without patch. The
+ latter will be None if options.shell_dir_no_patch was not
+ specified.
+ """
+ stdout = self._Run(runnable, count, no_patch=False)
+ if self.shell_dir_no_patch:
+ return stdout, self._Run(runnable, count, no_patch=True)
+ else:
+ return stdout, None
+
class DesktopPlatform(Platform):
def __init__(self, options):
@@ -538,21 +619,24 @@ class DesktopPlatform(Platform):
if isinstance(node, RunnableConfig):
node.ChangeCWD(path)
- def Run(self, runnable, count):
+ def _Run(self, runnable, count, no_patch=False):
+ suffix = ' - without patch' if no_patch else ''
+ shell_dir = self.shell_dir_no_patch if no_patch else self.shell_dir
+ title = ">>> %%s (#%d)%s:" % ((count + 1), suffix)
try:
output = commands.Execute(
- runnable.GetCommand(self.shell_dir, self.extra_flags),
+ runnable.GetCommand(shell_dir, self.extra_flags),
timeout=runnable.timeout,
)
- except OSError as e:
- print ">>> OSError (#%d):" % (count + 1)
+ except OSError as e: # pragma: no cover
+ print title % "OSError"
print e
return ""
- print ">>> Stdout (#%d):" % (count + 1)
+ print title % "Stdout"
print output.stdout
if output.stderr: # pragma: no cover
# Print stderr for debugging.
- print ">>> Stderr (#%d):" % (count + 1)
+ print title % "Stderr"
print output.stderr
if output.timed_out:
print ">>> Test timed out after %ss." % runnable.timeout
@@ -626,42 +710,51 @@ class AndroidPlatform(Platform): # pragma: no cover
self._SendCommand("shell mkdir -p %s" % folder_on_device)
self._SendCommand("shell cp %s %s" % (file_on_device_tmp, file_on_device))
- def PreTests(self, node, path):
- suite_dir = os.path.abspath(os.path.dirname(path))
- if node.path:
- bench_rel = os.path.normpath(os.path.join(*node.path))
- bench_abs = os.path.join(suite_dir, bench_rel)
- else:
- bench_rel = "."
- bench_abs = suite_dir
-
- self._PushFile(self.shell_dir, node.binary, "bin")
+ def _PushExecutable(self, shell_dir, target_dir, binary):
+ self._PushFile(shell_dir, binary, target_dir)
# Push external startup data. Backwards compatible for revisions where
# these files didn't exist.
self._PushFile(
- self.shell_dir,
+ shell_dir,
"natives_blob.bin",
- "bin",
+ target_dir,
skip_if_missing=True,
)
self._PushFile(
- self.shell_dir,
+ shell_dir,
"snapshot_blob.bin",
- "bin",
+ target_dir,
skip_if_missing=True,
)
+ def PreTests(self, node, path):
+ suite_dir = os.path.abspath(os.path.dirname(path))
+ if node.path:
+ bench_rel = os.path.normpath(os.path.join(*node.path))
+ bench_abs = os.path.join(suite_dir, bench_rel)
+ else:
+ bench_rel = "."
+ bench_abs = suite_dir
+
+ self._PushExecutable(self.shell_dir, "bin", node.binary)
+ if self.shell_dir_no_patch:
+ self._PushExecutable(
+ self.shell_dir_no_patch, "bin_no_patch", node.binary)
+
if isinstance(node, RunnableConfig):
self._PushFile(bench_abs, node.main, bench_rel)
for resource in node.resources:
self._PushFile(bench_abs, resource, bench_rel)
- def Run(self, runnable, count):
+ def _Run(self, runnable, count, no_patch=False):
+ suffix = ' - without patch' if no_patch else ''
+ target_dir = "bin_no_patch" if no_patch else "bin"
+ title = ">>> %%s (#%d)%s:" % ((count + 1), suffix)
cache = cache_control.CacheControl(self.device)
cache.DropRamCaches()
binary_on_device = os.path.join(
- AndroidPlatform.DEVICE_DIR, "bin", runnable.binary)
+ AndroidPlatform.DEVICE_DIR, target_dir, runnable.binary)
cmd = [binary_on_device] + runnable.GetCommandFlags(self.extra_flags)
# Relative path to benchmark directory.
@@ -678,7 +771,7 @@ class AndroidPlatform(Platform): # pragma: no cover
retries=0,
)
stdout = "\n".join(output)
- print ">>> Stdout (#%d):" % (count + 1)
+ print title % "Stdout"
print stdout
except device_errors.CommandTimeoutError:
print ">>> Test timed out after %ss." % runnable.timeout
@@ -708,8 +801,13 @@ def Main(args):
default="")
parser.add_option("--json-test-results",
help="Path to a file for storing json results.")
+ parser.add_option("--json-test-results-no-patch",
+ help="Path to a file for storing json results from run "
+ "without patch.")
parser.add_option("--outdir", help="Base directory with compile output",
default="out")
+ parser.add_option("--outdir-no-patch",
+ help="Base directory with compile output without patch")
(options, args) = parser.parse_args(args)
if len(args) == 0: # pragma: no cover
@@ -723,21 +821,35 @@ def Main(args):
print "Unknown architecture %s" % options.arch
return 1
- if (options.device and not options.android_build_tools): # pragma: no cover
+ if options.device and not options.android_build_tools: # pragma: no cover
print "Specifying a device requires Android build tools."
return 1
+ if (options.json_test_results_no_patch and
+ not options.outdir_no_patch): # pragma: no cover
+ print("For writing json test results without patch, an outdir without "
+ "patch must be specified.")
+ return 1
+
workspace = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
if options.buildbot:
- options.shell_dir = os.path.join(workspace, options.outdir, "Release")
+ build_config = "Release"
else:
- options.shell_dir = os.path.join(workspace, options.outdir,
- "%s.release" % options.arch)
+ build_config = "%s.release" % options.arch
+
+ options.shell_dir = os.path.join(workspace, options.outdir, build_config)
+
+ if options.outdir_no_patch:
+ options.shell_dir_no_patch = os.path.join(
+ workspace, options.outdir_no_patch, build_config)
+ else:
+ options.shell_dir_no_patch = None
platform = Platform.GetPlatform(options)
results = Results()
+ results_no_patch = Results()
for path in args:
path = os.path.abspath(path)
@@ -773,8 +885,10 @@ def Main(args):
yield platform.Run(runnable, i)
# Let runnable iterate over all runs and handle output.
- results += runnable.Run(Runner)
-
+ result, result_no_patch = runnable.Run(
+ Runner, trybot=options.shell_dir_no_patch)
+ results += result
+ results_no_patch += result_no_patch
platform.PostExecution()
if options.json_test_results:
@@ -782,6 +896,11 @@ def Main(args):
else: # pragma: no cover
print results
+ if options.json_test_results_no_patch:
+ results_no_patch.WriteToFile(options.json_test_results_no_patch)
+ else: # pragma: no cover
+ print results_no_patch
+
return min(1, len(results.errors))
if __name__ == "__main__": # pragma: no cover
« no previous file with comments | « no previous file | tools/unittests/run_perf_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698