Chromium Code Reviews| Index: tools/telemetry/telemetry/web_perf/metrics/trace_event_aggregator.py |
| diff --git a/tools/telemetry/telemetry/web_perf/metrics/trace_event_aggregator.py b/tools/telemetry/telemetry/web_perf/metrics/trace_event_aggregator.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6627e822db1be76633cb56ded760842bdf6316ca |
| --- /dev/null |
| +++ b/tools/telemetry/telemetry/web_perf/metrics/trace_event_aggregator.py |
| @@ -0,0 +1,100 @@ |
| +# Copyright 2015 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| + |
| +from telemetry.value import list_of_scalar_values |
| +from telemetry.value import scalar |
| +from telemetry.web_perf.metrics import timeline_based_metric |
| + |
| +class TraceEventAggregatorInput(object): |
|
cmumford
2015/08/03 17:31:34
This class doesn't seem to do anything. Why not si
dmurph
2015/08/05 15:30:33
I'm going to defer to you and Ned for this. It see
|
| + """Input for the TraceEventAggregator. |
| + |
| + event_name: The name of the event to track. |
| + list_metric_name: The name of the list metric name, which accumulates |
| + all of the times of the events. |
| + list_metric_description: Description of the list metric. |
| + units: Units for the list metric. |
| + count_metric_name: The name of the metric that is the count of the events. |
| + count_metric_description: The description of the count metric. |
| + process_name: The name of the process to inspect for the trace events. |
| + """ |
| + def __init__(self, event_name, list_metric_name, |
| + list_metric_description, units, count_metric_name, |
| + count_metric_description, process_name=None): |
| + self.event_name = event_name |
| + self.list_metric_name = list_metric_name |
| + self.list_metric_description = list_metric_description |
| + self.units = units |
| + self.count_metric_name = count_metric_name |
| + self.count_metric_description = count_metric_description |
| + self.process_name = process_name |
| + |
| + |
| +class TraceEventAggregator(timeline_based_metric.TimelineBasedMetric): |
| + """Reports durations and counts of given trace events. |
|
nednguyen
2015/08/03 16:12:21
This seems similar to single_event in web_perf/met
dmurph
2015/08/05 15:30:33
yay! I tried to make it as performant as possible
|
| + """ |
| + |
| + def __init__(self, trace_event_aggregator_inputs=[]): |
| + super(TraceEventAggregator, self).__init__() |
| + self._inputs_by_process_name = dict() |
| + self._IndexNewInputs(trace_event_aggregator_inputs) |
| + |
| + def AddInput(self, trace_event_aggregator_input): |
| + self._IndexNewInputs([trace_event_aggregator_input]) |
| + |
| + def _IndexNewInputs(self, input_list): |
| + for input_obj in input_list: |
| + if input_obj.process_name not in self._inputs_by_process_name: |
| + self._inputs_by_process_name[input_obj.process_name] = list() |
| + self._inputs_by_process_name[input_obj.process_name].append(input_obj) |
| + |
| + @staticmethod |
| + def ThreadDurationIfPresent(event): |
| + if event.thread_duration: |
|
cmumford
2015/08/03 17:31:34
Could you ever have a thread_duration of zero?
dmurph
2015/08/05 15:30:33
I imagine so.
|
| + return event.thread_duration |
| + else: |
| + return event.end - event.start |
| + |
| + def AddResults(self, model, renderer_thread, interactions, results): |
| + assert interactions |
| + # NOTE: This means duplicate names can cause problems. |
| + for p in model.GetAllProcesses(): |
| + if (p.name is renderer_thread.name and |
| + None in self._inputs_by_process_name): |
| + self._AddResultsInternal(renderer_thread.parent.IterAllSlices(), |
| + interactions, results, |
| + self._inputs_by_process_name[None]) |
| + elif p.name in self._inputs_by_process_name: |
| + self._AddResultsInternal(p.parent.IterAllSlices(), |
| + interactions, results, |
| + self._inputs_by_process_name[p.name]) |
| + |
| + def _AddResultsInternal(self, events, interactions, results, inputs): |
| + times_by_event_name = dict([[input_obj.event_name, []] |
| + for input_obj in inputs]) |
| + inputs_by_event_name = dict([[input_obj.event_name, input_obj] |
| + for input_obj in inputs]) |
| + for event in events: |
| + if event.name not in inputs_by_event_name or not any( |
| + interaction.start <= event.start <= interaction.end |
| + for interaction in interactions): |
| + continue |
| + times_by_event_name[event.name].append( |
| + self.ThreadDurationIfPresent(event)) |
| + |
| + for (event_name, times) in times_by_event_name.iteritems(): |
| + input_for_event = inputs_by_event_name[event_name] |
| + results.AddValue(scalar.ScalarValue( |
| + page=results.current_page, |
| + name=input_for_event.count_metric_name, |
| + units='count', |
| + value=len(times), |
| + description=input_for_event.count_metric_description)) |
| + if len(times) == 0: |
|
cmumford
2015/08/03 17:31:34
Not pythonic. Just do:
if not times:
continue
dmurph
2015/08/05 15:30:33
Done.
|
| + continue |
| + results.AddValue(list_of_scalar_values.ListOfScalarValues( |
| + page=results.current_page, |
| + name=input_for_event.list_metric_name, |
| + units=input_for_event.units, |
| + values=times, |
| + description=input_for_event.list_metric_description)) |