| Index: tools/telemetry/telemetry/web_perf/timeline_interaction_record.py
|
| diff --git a/tools/telemetry/telemetry/web_perf/timeline_interaction_record.py b/tools/telemetry/telemetry/web_perf/timeline_interaction_record.py
|
| deleted file mode 100644
|
| index 7d6ce26a9172ed2f66f7e086bf833389fba8167c..0000000000000000000000000000000000000000
|
| --- a/tools/telemetry/telemetry/web_perf/timeline_interaction_record.py
|
| +++ /dev/null
|
| @@ -1,235 +0,0 @@
|
| -# Copyright 2014 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.
|
| -
|
| -import re
|
| -
|
| -from telemetry import decorators
|
| -import telemetry.timeline.bounds as timeline_bounds
|
| -
|
| -# Allows multiple duplicate interactions of the same type
|
| -REPEATABLE = 'repeatable'
|
| -
|
| -FLAGS = [REPEATABLE]
|
| -
|
| -
|
| -class ThreadTimeRangeOverlappedException(Exception):
|
| - """Exception that can be thrown when computing overlapped thread time range
|
| - with other events.
|
| - """
|
| -
|
| -class NoThreadTimeDataException(ThreadTimeRangeOverlappedException):
|
| - """Exception that can be thrown if there is not sufficient thread time data
|
| - to compute the overlapped thread time range."""
|
| -
|
| -def IsTimelineInteractionRecord(event_name):
|
| - return event_name.startswith('Interaction.')
|
| -
|
| -def _AssertFlagsAreValid(flags):
|
| - assert isinstance(flags, list)
|
| - for f in flags:
|
| - if f not in FLAGS:
|
| - raise AssertionError(
|
| - 'Unrecognized flag for a timeline interaction record: %s' % f)
|
| -
|
| -def GetJavaScriptMarker(label, flags):
|
| - """Computes the marker string of an interaction record.
|
| -
|
| - This marker string can be used with JavaScript API console.time()
|
| - and console.timeEnd() to mark the beginning and end of the
|
| - interaction record..
|
| -
|
| - Args:
|
| - label: The label used to identify the interaction record.
|
| - flags: the flags for the interaction record see FLAGS above.
|
| -
|
| - Returns:
|
| - The interaction record marker string (e.g., Interaction.Label/flag1,flag2).
|
| -
|
| - Raises:
|
| - AssertionError: If one or more of the flags is unrecognized.
|
| - """
|
| - _AssertFlagsAreValid(flags)
|
| - marker = 'Interaction.%s' % label
|
| - if flags:
|
| - marker += '/%s' % (','.join(flags))
|
| - return marker
|
| -
|
| -class TimelineInteractionRecord(object):
|
| - """Represents an interaction that took place during a timeline recording.
|
| -
|
| - As a page runs, typically a number of different (simulated) user interactions
|
| - take place. For instance, a user might click a button in a mail app causing a
|
| - popup to animate in. Then they might press another button that sends data to a
|
| - server and simultaneously closes the popup without an animation. These are two
|
| - interactions.
|
| -
|
| - From the point of view of the page, each interaction might have a different
|
| - label: ClickComposeButton and SendEmail, for instance. From the point
|
| - of view of the benchmarking harness, the labels aren't so interesting as what
|
| - the performance expectations are for that interaction: was it loading
|
| - resources from the network? was there an animation?
|
| -
|
| - Determining these things is hard to do, simply by observing the state given to
|
| - a page from javascript. There are hints, for instance if network requests are
|
| - sent, or if a CSS animation is pending. But this is by no means a complete
|
| - story.
|
| -
|
| - Instead, we expect pages to mark up the timeline what they are doing, with
|
| - label and flags indicating the semantics of that interaction. This
|
| - is currently done by pushing markers into the console.time/timeEnd API: this
|
| - for instance can be issued in JS:
|
| -
|
| - var str = 'Interaction.SendEmail';
|
| - console.time(str);
|
| - setTimeout(function() {
|
| - console.timeEnd(str);
|
| - }, 1000);
|
| -
|
| - When run with perf.measurements.timeline_based_measurement running, this will
|
| - then cause a TimelineInteractionRecord to be created for this range with
|
| - all metrics reported for the marked up 1000ms time-range.
|
| -
|
| - The valid interaction flags are:
|
| - * repeatable: Allows other interactions to use the same label
|
| - """
|
| -
|
| - def __init__(self, label, start, end, async_event=None, flags=None):
|
| - assert label
|
| - self._label = label
|
| - self._start = start
|
| - self._end = end
|
| - self._async_event = async_event
|
| - self._flags = flags if flags is not None else []
|
| - _AssertFlagsAreValid(self._flags)
|
| -
|
| - @property
|
| - def label(self):
|
| - return self._label
|
| -
|
| - @property
|
| - def start(self):
|
| - return self._start
|
| -
|
| - @property
|
| - def end(self):
|
| - return self._end
|
| -
|
| - @property
|
| - def repeatable(self):
|
| - return REPEATABLE in self._flags
|
| -
|
| - # TODO(nednguyen): After crbug.com/367175 is marked fixed, we should be able
|
| - # to get rid of perf.measurements.smooth_gesture_util and make this the only
|
| - # constructor method for TimelineInteractionRecord.
|
| - @classmethod
|
| - def FromAsyncEvent(cls, async_event):
|
| - """Construct an timeline_interaction_record from an async event.
|
| - Args:
|
| - async_event: An instance of
|
| - telemetry.timeline.async_slices.AsyncSlice
|
| - """
|
| - assert async_event.start_thread == async_event.end_thread, (
|
| - 'Start thread of this record\'s async event is not the same as its '
|
| - 'end thread')
|
| - m = re.match(r'Interaction\.(?P<label>.+?)(/(?P<flags>[^/]+))?$',
|
| - async_event.name)
|
| - assert m, "Async event is not an interaction record."
|
| - label = m.group('label')
|
| - flags = m.group('flags').split(',') if m.group('flags') is not None else []
|
| - return cls(label, async_event.start, async_event.end, async_event, flags)
|
| -
|
| - @decorators.Cache
|
| - def GetBounds(self):
|
| - bounds = timeline_bounds.Bounds()
|
| - bounds.AddValue(self.start)
|
| - bounds.AddValue(self.end)
|
| - return bounds
|
| -
|
| - def GetOverlappedThreadTimeForSlice(self, timeline_slice):
|
| - """Get the thread duration of timeline_slice that overlaps with this record.
|
| -
|
| - There are two cases :
|
| -
|
| - Case 1: timeline_slice runs in the same thread as the record.
|
| -
|
| - | [ timeline_slice ]
|
| - THREAD 1 | | |
|
| - | record starts record ends
|
| -
|
| - (relative order in thread time)
|
| -
|
| - As the thread timestamps in timeline_slice and record are consistent, we
|
| - simply use them to compute the overlap.
|
| -
|
| - Case 2: timeline_slice runs in a different thread from the record's.
|
| -
|
| - |
|
| - THREAD 2 | [ timeline_slice ]
|
| - |
|
| -
|
| - |
|
| - THREAD 1 | | |
|
| - | record starts record ends
|
| -
|
| - (relative order in wall-time)
|
| -
|
| - Unlike case 1, thread timestamps of a thread are measured by its
|
| - thread-specific clock, which is inconsistent with that of the other
|
| - thread, and thus can't be used to compute the overlapped thread duration.
|
| - Hence, we use a heuristic to compute the overlap (see
|
| - _GetOverlappedThreadTimeForSliceInDifferentThread for more details)
|
| -
|
| - Args:
|
| - timeline_slice: An instance of telemetry.timeline.slice.Slice
|
| - """
|
| - if not self._async_event:
|
| - raise ThreadTimeRangeOverlappedException(
|
| - 'This record was not constructed from async event')
|
| - if not self._async_event.has_thread_timestamps:
|
| - raise NoThreadTimeDataException(
|
| - 'This record\'s async_event does not contain thread time data. '
|
| - 'Event data: %s' % repr(self._async_event))
|
| - if not timeline_slice.has_thread_timestamps:
|
| - raise NoThreadTimeDataException(
|
| - 'slice does not contain thread time data')
|
| -
|
| - if timeline_slice.parent_thread == self._async_event.start_thread:
|
| - return self._GetOverlappedThreadTimeForSliceInSameThread(
|
| - timeline_slice)
|
| - else:
|
| - return self._GetOverlappedThreadTimeForSliceInDifferentThread(
|
| - timeline_slice)
|
| -
|
| - def _GetOverlappedThreadTimeForSliceInSameThread(self, timeline_slice):
|
| - return timeline_bounds.Bounds.GetOverlap(
|
| - timeline_slice.thread_start, timeline_slice.thread_end,
|
| - self._async_event.thread_start, self._async_event.thread_end)
|
| -
|
| - def _GetOverlappedThreadTimeForSliceInDifferentThread(self, timeline_slice):
|
| - # In case timeline_slice's parent thread is not the parent thread of the
|
| - # async slice that issues this record, we assume that events are descheduled
|
| - # uniformly. The overlap duration in thread time is then computed by
|
| - # multiplying the overlap wall-time duration of timeline_slice and the
|
| - # record's async slice with their thread_duration/duration ratios.
|
| - overlapped_walltime_duration = timeline_bounds.Bounds.GetOverlap(
|
| - timeline_slice.start, timeline_slice.end,
|
| - self.start, self.end)
|
| - if timeline_slice.duration == 0 or self._async_event.duration == 0:
|
| - return 0
|
| - timeline_slice_scheduled_ratio = (
|
| - timeline_slice.thread_duration / float(timeline_slice.duration))
|
| - record_scheduled_ratio = (
|
| - self._async_event.thread_duration / float(self._async_event.duration))
|
| - return (overlapped_walltime_duration * timeline_slice_scheduled_ratio *
|
| - record_scheduled_ratio)
|
| -
|
| - def __repr__(self):
|
| - flags_str = ','.join(self._flags)
|
| - return ('TimelineInteractionRecord(label=\'%s\', start=%f, end=%f,' +
|
| - ' flags=%s, async_event=%s)') % (
|
| - self.label,
|
| - self.start,
|
| - self.end,
|
| - flags_str,
|
| - repr(self._async_event))
|
|
|