Commit 7fda4612 authored by Mikhail Khokhlov's avatar Mikhail Khokhlov Committed by Commit Bot

[tools/perf] Implement traces aggregation in Results Processor

Bug: 981349
Change-Id: I1a47afea1dedcd352a0d6999f7119246b74b737f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1849855
Commit-Queue: Mikhail Khokhlov <khokhlov@google.com>
Reviewed-by: default avatarJuan Antonio Navarro Pérez <perezju@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704705}
parent 4607d229
...@@ -20,6 +20,7 @@ from core.results_processor import compute_metrics ...@@ -20,6 +20,7 @@ from core.results_processor import compute_metrics
from core.results_processor import formatters from core.results_processor import formatters
from core.results_processor import util from core.results_processor import util
from tracing.trace_data import trace_data
from tracing.value.diagnostics import generic_set from tracing.value.diagnostics import generic_set
from tracing.value.diagnostics import reserved_infos from tracing.value.diagnostics import reserved_infos
from tracing.value import histogram_set from tracing.value import histogram_set
...@@ -46,7 +47,7 @@ def ProcessResults(options): ...@@ -46,7 +47,7 @@ def ProcessResults(options):
intermediate_results = _LoadIntermediateResults( intermediate_results = _LoadIntermediateResults(
os.path.join(options.intermediate_dir, TELEMETRY_RESULTS)) os.path.join(options.intermediate_dir, TELEMETRY_RESULTS))
_AggregateTraces(intermediate_results) AggregateTraces(intermediate_results)
UploadArtifacts( UploadArtifacts(
intermediate_results, options.upload_bucket, options.results_label) intermediate_results, options.upload_bucket, options.results_label)
...@@ -99,7 +100,7 @@ def _LoadIntermediateResults(intermediate_file): ...@@ -99,7 +100,7 @@ def _LoadIntermediateResults(intermediate_file):
return results return results
def _AggregateTraces(intermediate_results): def AggregateTraces(intermediate_results):
"""Replace individual traces with an aggregate one for each test result. """Replace individual traces with an aggregate one for each test result.
For each test run with traces, generates an aggregate HTML trace. Removes For each test run with traces, generates an aggregate HTML trace. Removes
...@@ -109,10 +110,16 @@ def _AggregateTraces(intermediate_results): ...@@ -109,10 +110,16 @@ def _AggregateTraces(intermediate_results):
artifacts = result.get('outputArtifacts', {}) artifacts = result.get('outputArtifacts', {})
traces = [name for name in artifacts if name.startswith('trace/')] traces = [name for name in artifacts if name.startswith('trace/')]
if len(traces) > 0: if len(traces) > 0:
# For now, the html trace is generated by Telemetry, so it should be there if compute_metrics.HTML_TRACE_NAME not in artifacts:
# already. All we need to do is remove individual traces from the dict. trace_files = [artifacts[name]['filePath'] for name in traces]
# TODO(crbug.com/981349): replace this with actual aggregation code. html_path = os.path.join(
assert compute_metrics.HTML_TRACE_NAME in artifacts os.path.dirname(os.path.commonprefix(trace_files)),
compute_metrics.HTML_TRACE_NAME)
trace_data.SerializeAsHtml(trace_files, html_path)
artifacts[compute_metrics.HTML_TRACE_NAME] = {
'filePath': html_path,
'contentType': 'text/html',
}
for trace in traces: for trace in traces:
del artifacts[trace] del artifacts[trace]
......
...@@ -24,6 +24,7 @@ from core.results_processor import compute_metrics ...@@ -24,6 +24,7 @@ from core.results_processor import compute_metrics
from core.results_processor import processor from core.results_processor import processor
from core.results_processor import testing from core.results_processor import testing
from tracing.value.diagnostics import generic_set
from tracing.value import histogram from tracing.value import histogram
from tracing.value import histogram_set from tracing.value import histogram_set
from tracing_build import render_histograms_viewer from tracing_build import render_histograms_viewer
...@@ -268,12 +269,45 @@ class ResultsProcessorIntegrationTests(unittest.TestCase): ...@@ -268,12 +269,45 @@ class ResultsProcessorIntegrationTests(unittest.TestCase):
out_histograms = histogram_set.HistogramSet() out_histograms = histogram_set.HistogramSet()
out_histograms.ImportDicts(results) out_histograms.ImportDicts(results)
self.assertEqual(len(out_histograms), 4)
self.assertIsNotNone(out_histograms.GetHistogramNamed('foo'))
diag_values = [list(v) for v in out_histograms.shared_diagnostics] # sampleMetric records a histogram with the name 'foo'.
self.assertEqual(len(diag_values), 1) hist = out_histograms.GetHistogramNamed('foo')
self.assertIn(['gs://trace.html'], diag_values) self.assertIsNotNone(hist)
self.assertEqual(hist.diagnostics['traceUrls'],
generic_set.GenericSet(['gs://trace.html']))
def testHistogramsOutputNoAggregatedTrace(self):
json_trace = os.path.join(self.output_dir, 'trace.json')
with open(json_trace, 'w') as f:
json.dump({'traceEvents': []}, f)
self.SerializeIntermediateResults(
test_results=[
testing.TestResult(
'benchmark/story',
output_artifacts={'trace/json': testing.Artifact(json_trace)},
tags=['tbmv2:sampleMetric'],
),
],
)
processor.main([
'--output-format', 'histograms',
'--output-dir', self.output_dir,
'--intermediate-dir', self.intermediate_dir,
])
with open(os.path.join(
self.output_dir, histograms_output.OUTPUT_FILENAME)) as f:
results = json.load(f)
out_histograms = histogram_set.HistogramSet()
out_histograms.ImportDicts(results)
# sampleMetric records a histogram with the name 'foo'.
hist = out_histograms.GetHistogramNamed('foo')
self.assertIsNotNone(hist)
self.assertIn('traceUrls', hist.diagnostics)
def testHtmlOutput(self): def testHtmlOutput(self):
hist_file = os.path.join(self.output_dir, hist_file = os.path.join(self.output_dir,
......
...@@ -94,3 +94,55 @@ class ResultsProcessorUnitTests(unittest.TestCase): ...@@ -94,3 +94,55 @@ class ResultsProcessorUnitTests(unittest.TestCase):
'src_abc_123_20191001T120000_54321/benchmark/story/trace.html', 'src_abc_123_20191001T120000_54321/benchmark/story/trace.html',
'/trace.html' '/trace.html'
) )
def testAggregateTraces(self):
in_results = testing.IntermediateResults(
test_results=[
testing.TestResult(
'benchmark/story1',
output_artifacts={
'trace/1.json': testing.Artifact(
'/artifacts/test_run/story1/trace/1.json'),
},
),
testing.TestResult(
'benchmark/story2',
output_artifacts={
'trace/1.json': testing.Artifact(
'/artifacts/test_run/story2/trace/1.json'),
'trace/2.json': testing.Artifact(
'/artifacts/test_run/story2/trace/2.json'),
},
),
],
)
with mock.patch('tracing.trace_data.trace_data.SerializeAsHtml') as patch:
processor.AggregateTraces(in_results)
call_list = [list(call[0]) for call in patch.call_args_list]
self.assertEqual(len(call_list), 2)
for call in call_list:
call[0] = set(call[0])
self.assertIn(
[
set(['/artifacts/test_run/story1/trace/1.json']),
'/artifacts/test_run/story1/trace/trace.html',
],
call_list
)
self.assertIn(
[
set([
'/artifacts/test_run/story2/trace/1.json',
'/artifacts/test_run/story2/trace/2.json',
]),
'/artifacts/test_run/story2/trace/trace.html',
],
call_list
)
for result in in_results['testResults']:
artifacts = result['outputArtifacts']
self.assertEqual(len(artifacts), 1)
self.assertEqual(artifacts.keys()[0], 'trace.html')
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