Index: tools/run_perf.py |
diff --git a/tools/run_perf.py b/tools/run_perf.py |
index 957e2370d7b1623b072f52f34736f7008cb8c664..2e8f6b528546f0c7f46d6cf4241c0406af7c7186 100755 |
--- a/tools/run_perf.py |
+++ b/tools/run_perf.py |
@@ -97,6 +97,7 @@ The test flags are passed to the js test file after '--'. |
from collections import OrderedDict |
import json |
+import logging |
import math |
import optparse |
import os |
@@ -124,6 +125,21 @@ RESULT_STDDEV_RE = re.compile(r"^\{([^\}]+)\}$") |
RESULT_LIST_RE = re.compile(r"^\[([^\]]+)\]$") |
+def LoadAndroidBuildTools(path): # pragma: no cover |
+ assert os.path.exists(path) |
+ sys.path.insert(0, path) |
+ |
+ from pylib.device import device_utils # pylint: disable=F0401 |
+ from pylib.device import device_errors # pylint: disable=F0401 |
+ from pylib.perf import cache_control # pylint: disable=F0401 |
+ from pylib.perf import perf_control # pylint: disable=F0401 |
+ import pylib.android_commands # pylint: disable=F0401 |
+ global cache_control |
+ global device_errors |
+ global device_utils |
+ global perf_control |
+ global pylib |
+ |
def GeometricMean(values): |
"""Returns the geometric mean of a list of values. |
@@ -210,6 +226,7 @@ class Graph(Node): |
self.run_count = suite.get("run_count", parent.run_count) |
self.run_count = suite.get("run_count_%s" % arch, self.run_count) |
self.timeout = suite.get("timeout", parent.timeout) |
+ self.timeout = suite.get("timeout_%s" % arch, self.timeout) |
self.units = suite.get("units", parent.units) |
self.total = suite.get("total", parent.total) |
@@ -287,15 +304,13 @@ class Runnable(Graph): |
bench_dir = os.path.normpath(os.path.join(*self.path)) |
os.chdir(os.path.join(suite_dir, bench_dir)) |
+ def GetCommandFlags(self): |
+ suffix = ["--"] + self.test_flags if self.test_flags else [] |
+ return self.flags + [self.main] + suffix |
+ |
def GetCommand(self, shell_dir): |
# TODO(machenbach): This requires +.exe if run on windows. |
- suffix = ["--"] + self.test_flags if self.test_flags else [] |
- return ( |
- [os.path.join(shell_dir, self.binary)] + |
- self.flags + |
- [self.main] + |
- suffix |
- ) |
+ return [os.path.join(shell_dir, self.binary)] + self.GetCommandFlags() |
def Run(self, runner): |
"""Iterates over several runs and handles the output for all traces.""" |
@@ -408,7 +423,7 @@ def BuildGraphs(suite, arch, parent=None): |
parent = parent or DefaultSentinel() |
# TODO(machenbach): Implement notion of cpu type? |
- if arch not in suite.get("archs", ["ia32", "x64"]): |
+ if arch not in suite.get("archs", SUPPORTED_ARCHS): |
return None |
graph = MakeGraph(suite, arch, parent) |
@@ -443,18 +458,15 @@ class Platform(object): |
class DesktopPlatform(Platform): |
def __init__(self, options): |
- workspace = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) |
+ self.shell_dir = options.shell_dir |
- if options.buildbot: |
- self.shell_dir = os.path.join(workspace, options.outdir, "Release") |
- else: |
- self.shell_dir = os.path.join(workspace, options.outdir, |
- "%s.release" % options.arch) |
+ def PreExecution(self): |
+ pass |
- def PrepareExecution(self): |
+ def PostExecution(self): |
pass |
- def PrepareTests(self, runnable, path): |
+ def PreTests(self, runnable, path): |
runnable.ChangeCWD(path) |
def Run(self, runnable, count): |
@@ -471,14 +483,77 @@ class DesktopPlatform(Platform): |
return output.stdout |
-# TODO(machenbach): Implement android platform. |
-class AndroidPlatform(Platform): |
+class AndroidPlatform(Platform): # pragma: no cover |
+ DEVICE_DIR = "/data/local/tmp/v8/" |
+ |
def __init__(self, options): |
- pass |
+ self.shell_dir = options.shell_dir |
+ LoadAndroidBuildTools(options.android_build_tools) |
+ |
+ if not options.device: |
+ # Detect attached device if not specified. |
+ devices = pylib.android_commands.GetAttachedDevices( |
+ hardware=True, emulator=False, offline=False) |
+ assert devices and len(devices) == 1, ( |
+ "None or multiple devices detected. Please specify the device on " |
+ "the command-line with --device") |
+ options.device = devices[0] |
+ adb_wrapper = pylib.android_commands.AndroidCommands(options.device) |
+ self.device = device_utils.DeviceUtils(adb_wrapper) |
+ self.adb = adb_wrapper.Adb() |
+ |
+ def PreExecution(self): |
+ perf = perf_control.PerfControl(self.device) |
+ perf.SetHighPerfMode() |
+ |
+ def PostExecution(self): |
+ perf = perf_control.PerfControl(self.device) |
+ perf.SetDefaultPerfMode() |
+ self.device.RunShellCommand( |
+ ["rm", "-rf", "*"], |
+ cwd=AndroidPlatform.DEVICE_DIR, |
+ ) |
+ |
+ def _PushFile(self, host_dir, file_name): |
+ file_on_host = os.path.join(host_dir, file_name) |
+ file_on_device = AndroidPlatform.DEVICE_DIR + file_name |
+ logging.info("adb push %s %s" % (file_on_host, file_on_device)) |
+ self.adb.Push(file_on_host, file_on_device) |
+ |
+ def PreTests(self, runnable, path): |
+ suite_dir = os.path.abspath(os.path.dirname(path)) |
+ bench_dir = os.path.join(suite_dir, |
+ os.path.normpath(os.path.join(*runnable.path))) |
+ |
+ self._PushFile(self.shell_dir, runnable.binary) |
+ self._PushFile(bench_dir, runnable.main) |
+ for resource in runnable.resources: |
+ self._PushFile(bench_dir, resource) |
+ |
+ def Run(self, runnable, count): |
+ cache = cache_control.CacheControl(self.device) |
+ cache.DropRamCaches() |
+ binary_on_device = AndroidPlatform.DEVICE_DIR + runnable.binary |
+ cmd = [binary_on_device] + runnable.GetCommandFlags() |
+ try: |
+ output = self.device.RunShellCommand( |
+ cmd, |
+ cwd=AndroidPlatform.DEVICE_DIR, |
+ timeout=runnable.timeout, |
+ retries=0, |
+ ) |
+ stdout = "\n".join(output) |
+ print ">>> Stdout (#%d):" % (count + 1) |
+ print stdout |
+ except device_errors.CommandTimeoutError: |
+ print ">>> Test timed out after %ss." % runnable.timeout |
+ stdout = "" |
+ return stdout |
# TODO: Implement results_processor. |
def Main(args): |
+ logging.getLogger().setLevel(logging.INFO) |
parser = optparse.OptionParser() |
parser.add_option("--android-build-tools", |
help="Path to chromium's build/android.") |
@@ -520,8 +595,16 @@ def Main(args): |
print "Specifying a device requires an Android architecture to be used." |
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") |
+ else: |
+ options.shell_dir = os.path.join(workspace, options.outdir, |
+ "%s.release" % options.arch) |
+ |
platform = Platform.GetPlatform(options) |
- platform.PrepareExecution() |
+ platform.PreExecution() |
results = Results() |
for path in args: |
@@ -539,7 +622,7 @@ def Main(args): |
for runnable in FlattenRunnables(BuildGraphs(suite, options.arch)): |
print ">>> Running suite: %s" % "/".join(runnable.graphs) |
- platform.PrepareTests(runnable, path) |
+ platform.PreTests(runnable, path) |
def Runner(): |
"""Output generator that reruns several times.""" |
@@ -551,6 +634,8 @@ def Main(args): |
# Let runnable iterate over all runs and handle output. |
results += runnable.Run(Runner) |
+ platform.PostExecution() |
+ |
if options.json_test_results: |
results.WriteToFile(options.json_test_results) |
else: # pragma: no cover |