Commit 293fc82c authored by rnephew's avatar rnephew Committed by Commit bot

[Android] Add ability to generate test trace json for perf tests runs.

This adds the ability to set --trace-output <dir> and generate a json file that
can be opened in the chrome trace viewer that will display timelines of when
each test is run on which testing shard.

BUG=667470

Review-Url: https://codereview.chromium.org/2583613002
Cr-Commit-Position: refs/heads/master@{#439125}
parent 4b81adef
...@@ -31,6 +31,7 @@ def CommonChecks(input_api, output_api): ...@@ -31,6 +31,7 @@ def CommonChecks(input_api, output_api):
J(), J(),
J('gyp'), J('gyp'),
J('buildbot'), J('buildbot'),
J('..', '..', 'third_party', 'catapult', 'common', 'py_trace_event'),
J('..', '..', 'third_party', 'catapult', 'devil') J('..', '..', 'third_party', 'catapult', 'devil')
])) ]))
output.extend(input_api.canned_checks.RunPylint( output.extend(input_api.canned_checks.RunPylint(
......
...@@ -9,5 +9,12 @@ _DEVIL_PATH = os.path.abspath(os.path.join( ...@@ -9,5 +9,12 @@ _DEVIL_PATH = os.path.abspath(os.path.join(
os.path.dirname(__file__), '..', '..', '..', 'third_party', 'catapult', os.path.dirname(__file__), '..', '..', '..', 'third_party', 'catapult',
'devil')) 'devil'))
_PYTRACE_PATH = os.path.abspath(os.path.join(
os.path.dirname(__file__), '..', '..', '..', 'third_party', 'catapult',
'common', 'py_trace_event'))
if _DEVIL_PATH not in sys.path: if _DEVIL_PATH not in sys.path:
sys.path.append(_DEVIL_PATH) sys.path.append(_DEVIL_PATH)
if _PYTRACE_PATH not in sys.path:
sys.path.append(_PYTRACE_PATH)
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# found in the LICENSE file. # found in the LICENSE file.
import collections import collections
import contextlib
import io import io
import json import json
import logging import logging
...@@ -29,6 +30,7 @@ from pylib.base import base_test_result ...@@ -29,6 +30,7 @@ from pylib.base import base_test_result
from pylib.constants import host_paths from pylib.constants import host_paths
from pylib.local.device import local_device_environment from pylib.local.device import local_device_environment
from pylib.local.device import local_device_test_run from pylib.local.device import local_device_test_run
from py_trace_event import trace_event
class HeartBeat(object): class HeartBeat(object):
...@@ -94,10 +96,22 @@ class TestShard(object): ...@@ -94,10 +96,22 @@ class TestShard(object):
self._LogTest(test, cmd, timeout) self._LogTest(test, cmd, timeout)
@contextlib.contextmanager
def trace_if_enabled(test):
try:
if self._test_instance.trace_output:
trace_event.trace_begin(test)
yield
finally:
if self._test_instance.trace_output:
trace_event.trace_end(test)
try: try:
start_time = time.time() start_time = time.time()
exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
cmd, timeout, cwd=cwd, shell=True) with trace_if_enabled(test):
exit_code, output = cmd_helper.GetCmdStatusAndOutputWithTimeout(
cmd, timeout, cwd=cwd, shell=True)
end_time = time.time() end_time = time.time()
json_output = self._test_instance.ReadChartjsonOutput(self._output_dir) json_output = self._test_instance.ReadChartjsonOutput(self._output_dir)
if exit_code == 0: if exit_code == 0:
...@@ -110,7 +124,6 @@ class TestShard(object): ...@@ -110,7 +124,6 @@ class TestShard(object):
output = e.output output = e.output
json_output = '' json_output = ''
result_type = base_test_result.ResultType.TIMEOUT result_type = base_test_result.ResultType.TIMEOUT
return self._ProcessTestResult(test, cmd, start_time, end_time, exit_code, return self._ProcessTestResult(test, cmd, start_time, end_time, exit_code,
output, json_output, result_type) output, json_output, result_type)
...@@ -410,6 +423,9 @@ class LocalDevicePerfTestRun(local_device_test_run.LocalDeviceTestRun): ...@@ -410,6 +423,9 @@ class LocalDevicePerfTestRun(local_device_test_run.LocalDeviceTestRun):
#override #override
def RunTests(self): def RunTests(self):
# Affinitize the tests. # Affinitize the tests.
if self._test_instance.trace_output:
assert not trace_event.trace_is_enabled(), 'Tracing already running.'
trace_event.trace_enable(self._test_instance.trace_output)
self._SplitTestsByAffinity() self._SplitTestsByAffinity()
if not self._test_buckets and not self._no_device_tests: if not self._test_buckets and not self._no_device_tests:
raise local_device_test_run.NoTestsError() raise local_device_test_run.NoTestsError()
...@@ -447,6 +463,9 @@ class LocalDevicePerfTestRun(local_device_test_run.LocalDeviceTestRun): ...@@ -447,6 +463,9 @@ class LocalDevicePerfTestRun(local_device_test_run.LocalDeviceTestRun):
host_test_results, device_test_results = reraiser_thread.RunAsync( host_test_results, device_test_results = reraiser_thread.RunAsync(
[run_no_devices_tests, run_devices_tests]) [run_no_devices_tests, run_devices_tests])
if self._test_instance.trace_output:
assert trace_event.trace_is_enabled(), 'Tracing not running.'
trace_event.trace_disable()
return host_test_results + device_test_results return host_test_results + device_test_results
# override # override
......
...@@ -79,6 +79,7 @@ class PerfTestInstance(test_instance.TestInstance): ...@@ -79,6 +79,7 @@ class PerfTestInstance(test_instance.TestInstance):
' '.join(args.single_step_command) if args.single_step else None) ' '.join(args.single_step_command) if args.single_step else None)
self._steps = args.steps self._steps = args.steps
self._test_filter = args.test_filter self._test_filter = args.test_filter
self._trace_output = args.trace_output
self._write_buildbot_json = args.write_buildbot_json self._write_buildbot_json = args.write_buildbot_json
#override #override
...@@ -236,6 +237,10 @@ class PerfTestInstance(test_instance.TestInstance): ...@@ -236,6 +237,10 @@ class PerfTestInstance(test_instance.TestInstance):
def test_filter(self): def test_filter(self):
return self._test_filter return self._test_filter
@property
def trace_output(self):
return self._trace_output
class PersistentDataError(base_error.BaseError): class PersistentDataError(base_error.BaseError):
def __init__(self, message): def __init__(self, message):
......
...@@ -555,6 +555,10 @@ def AddPerfTestOptions(parser): ...@@ -555,6 +555,10 @@ def AddPerfTestOptions(parser):
group.add_argument( group.add_argument(
'--write-buildbot-json', action='store_true', '--write-buildbot-json', action='store_true',
help='Whether to output buildbot json.') help='Whether to output buildbot json.')
# TODO(rnephew): Move up to top level options when implemented on all tests.
group.add_argument(
'--trace-output', metavar='FILENAME', type=os.path.realpath,
help='Path to save test_runner trace data to.')
AddCommonOptions(parser) AddCommonOptions(parser)
AddDeviceOptions(parser) AddDeviceOptions(parser)
......
# Generated by running: # Generated by running:
# build/print_python_deps.py --root build/android --output build/android/test_runner.pydeps build/android/test_runner.py # build/print_python_deps.py --root build/android --output build/android/test_runner.pydeps build/android/test_runner.py
../../third_party/catapult/common/py_trace_event/py_trace_event/__init__.py
../../third_party/catapult/common/py_trace_event/py_trace_event/trace_event.py
../../third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/__init__.py
../../third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/decorators.py
../../third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/log.py
../../third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/meta_class.py
../../third_party/catapult/common/py_trace_event/py_trace_event/trace_event_impl/multiprocessing_shim.py
../../third_party/catapult/common/py_trace_event/py_trace_event/trace_time.py
../../third_party/catapult/common/py_utils/py_utils/__init__.py ../../third_party/catapult/common/py_utils/py_utils/__init__.py
../../third_party/catapult/common/py_utils/py_utils/cloud_storage.py ../../third_party/catapult/common/py_utils/py_utils/cloud_storage.py
../../third_party/catapult/common/py_utils/py_utils/cloud_storage_global_lock.py ../../third_party/catapult/common/py_utils/py_utils/cloud_storage_global_lock.py
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment