| Index: tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
|
| diff --git a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
|
| index 631ada3dba76d6a71e93b0f82f95c7ce45d8d113..e7cd2b9da5dfdb4c118111fdf85a2505c1f34398 100644
|
| --- a/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
|
| +++ b/tools/telemetry/telemetry/web_perf/timeline_based_measurement.py
|
| @@ -5,12 +5,13 @@
|
| import logging
|
| import os
|
|
|
| +from collections import defaultdict
|
| from telemetry.core import util
|
| from telemetry.core.backends.chrome import tracing_backend
|
| from telemetry.timeline import model as model_module
|
| from telemetry.web_perf import timeline_interaction_record as tir_module
|
| -from telemetry.web_perf.metrics import smoothness
|
| from telemetry.web_perf.metrics import responsiveness_metric
|
| +from telemetry.web_perf.metrics import smoothness
|
| from telemetry.page import page_measurement
|
| from telemetry.value import string as string_value_module
|
|
|
| @@ -30,28 +31,43 @@ ALL_OVERHEAD_LEVELS = [
|
| ]
|
|
|
|
|
| +class InvalidInteractions(Exception):
|
| + pass
|
| +
|
| +
|
| +def _GetMetricFromMetricType(metric_type):
|
| + if metric_type == tir_module.IS_SMOOTH:
|
| + return smoothness.SmoothnessMetric()
|
| + if metric_type == tir_module.IS_RESPONSIVE:
|
| + return responsiveness_metric.ResponsivenessMetric()
|
| + raise Exception('Unrecognized metric type: %s' % metric_type)
|
| +
|
| +
|
| class _ResultsWrapper(object):
|
| - def __init__(self, results, interaction_record):
|
| + def __init__(self, results, logical_name):
|
| self._results = results
|
| - self._interaction_record = interaction_record
|
| + self._result_prefix = logical_name
|
| +
|
| + def _GetResultName(self, trace_name):
|
| + return '%s-%s' % (self._result_prefix, trace_name)
|
|
|
| def Add(self, trace_name, units, value, chart_name=None, data_type='default'):
|
| - trace_name = self._interaction_record.GetResultNameFor(trace_name)
|
| - self._results.Add(trace_name, units, value, chart_name, data_type)
|
| + result_name = self._GetResultName(trace_name)
|
| + self._results.Add(result_name, units, value, chart_name, data_type)
|
|
|
| def AddSummary(self, trace_name, units, value, chart_name=None,
|
| - data_type='default'):
|
| - trace_name = self._interaction_record.GetResultNameFor(trace_name)
|
| - self._results.AddSummary(trace_name, units, value, chart_name, data_type)
|
| + data_type='default'):
|
| + result_name = self._GetResultName(trace_name)
|
| + self._results.AddSummary(result_name, units, value, chart_name, data_type)
|
|
|
|
|
| class _TimelineBasedMetrics(object):
|
| def __init__(self, model, renderer_thread,
|
| - create_metrics_for_interaction_record_callback):
|
| + get_metric_from_metric_type_callback):
|
| self._model = model
|
| self._renderer_thread = renderer_thread
|
| - self._create_metrics_for_interaction_record_callback = \
|
| - create_metrics_for_interaction_record_callback
|
| + self._get_metric_from_metric_type_callback = \
|
| + get_metric_from_metric_type_callback
|
|
|
| def FindTimelineInteractionRecords(self):
|
| # TODO(nduca): Add support for page-load interaction record.
|
| @@ -60,16 +76,37 @@ class _TimelineBasedMetrics(object):
|
| if tir_module.IsTimelineInteractionRecord(event.name)]
|
|
|
| def AddResults(self, results):
|
| - interactions = self.FindTimelineInteractionRecords()
|
| - if len(interactions) == 0:
|
| - raise Exception('Expected at least one Interaction on the page')
|
| - for interaction in interactions:
|
| - metrics = \
|
| - self._create_metrics_for_interaction_record_callback(interaction)
|
| - wrapped_results = _ResultsWrapper(results, interaction)
|
| - for m in metrics:
|
| - m.AddResults(self._model, self._renderer_thread,
|
| - [interaction], wrapped_results)
|
| + all_interactions = self.FindTimelineInteractionRecords()
|
| + if len(all_interactions) == 0:
|
| + raise InvalidInteractions('Expected at least one interaction record on '
|
| + 'the page')
|
| +
|
| + interactions_by_logical_name = defaultdict(list)
|
| + for i in all_interactions:
|
| + interactions_by_logical_name[i.logical_name].append(i)
|
| +
|
| + for logical_name, interactions in interactions_by_logical_name.iteritems():
|
| + are_repeatable = [i.repeatable for i in interactions]
|
| + if not all(are_repeatable) and len(interactions) > 1:
|
| + raise InvalidInteractions('Duplicate unrepeatable interaction records '
|
| + 'on the page')
|
| + wrapped_results = _ResultsWrapper(results, logical_name)
|
| + self.UpdateResultsByMetric(interactions, wrapped_results)
|
| +
|
| + def UpdateResultsByMetric(self, interactions, wrapped_results):
|
| + for metric_type in tir_module.METRICS:
|
| + # For each metric type, either all or none of the interactions should
|
| + # have that metric.
|
| + interactions_with_metric = [i for i in interactions if
|
| + i.HasMetric(metric_type)]
|
| + if not interactions_with_metric:
|
| + continue
|
| + if len(interactions_with_metric) != len(interactions):
|
| + raise InvalidInteractions('Interaction records with the same logical '
|
| + 'name must have the same flags.')
|
| + metric = self._get_metric_from_metric_type_callback(metric_type)
|
| + metric.AddResults(self._model, self._renderer_thread,
|
| + interactions, wrapped_results)
|
|
|
|
|
| class TimelineBasedMeasurement(page_measurement.PageMeasurement):
|
| @@ -124,17 +161,6 @@ class TimelineBasedMeasurement(page_measurement.PageMeasurement):
|
| categories = ','.join([categories] + page.GetSyntheticDelayCategories())
|
| tab.browser.StartTracing(categories)
|
|
|
| - def CreateMetricsForTimelineInteractionRecord(self, interaction):
|
| - """ Subclass of TimelineBasedMeasurement overrides this method to customize
|
| - the binding of interaction's flags to metrics.
|
| - """
|
| - res = []
|
| - if interaction.is_smooth:
|
| - res.append(smoothness.SmoothnessMetric())
|
| - if interaction.is_responsive:
|
| - res.append(responsiveness_metric.ResponsivenessMetric())
|
| - return res
|
| -
|
| def MeasurePage(self, page, tab, results):
|
| """ Collect all possible metrics and added them to results. """
|
| trace_result = tab.browser.StopTracing()
|
| @@ -153,7 +179,7 @@ class TimelineBasedMeasurement(page_measurement.PageMeasurement):
|
| model = model_module.TimelineModel(trace_result)
|
| renderer_thread = model.GetRendererThreadFromTabId(tab.id)
|
| meta_metrics = _TimelineBasedMetrics(
|
| - model, renderer_thread, self.CreateMetricsForTimelineInteractionRecord)
|
| + model, renderer_thread, _GetMetricFromMetricType)
|
| meta_metrics.AddResults(results)
|
|
|
| def CleanUpAfterPage(self, page, tab):
|
|
|