- input_event_latency = FlattenList(stats.input_event_latency)
- if input_event_latency:
- mean_input_event_latency = statistics.ArithmeticMean(
- input_event_latency)
- input_event_latency_discrepancy = statistics.DurationsDiscrepancy(
- input_event_latency)
- results.AddValue(scalar.ScalarValue(
- results.current_page, 'mean_input_event_latency', 'ms',
- round(mean_input_event_latency, 3)))
- results.AddValue(scalar.ScalarValue(
- results.current_page, 'input_event_latency_discrepancy', 'ms',
- round(input_event_latency_discrepancy, 4)))
- scroll_update_latency = FlattenList(stats.scroll_update_latency)
- if scroll_update_latency:
- mean_scroll_update_latency = statistics.ArithmeticMean(
- scroll_update_latency)
- scroll_update_latency_discrepancy = statistics.DurationsDiscrepancy(
- scroll_update_latency)
- results.AddValue(scalar.ScalarValue(
- results.current_page, 'mean_scroll_update_latency', 'ms',
- round(mean_scroll_update_latency, 3)))
- results.AddValue(scalar.ScalarValue(
- results.current_page, 'scroll_update_latency_discrepancy', 'ms',
- round(scroll_update_latency_discrepancy, 4)))
- gesture_scroll_update_latency = FlattenList(
- stats.gesture_scroll_update_latency)
- if gesture_scroll_update_latency:
- results.AddValue(scalar.ScalarValue(
- results.current_page, 'first_gesture_scroll_update_latency', 'ms',
- round(gesture_scroll_update_latency[0], 4)))
-
- # List of queueing durations.
- frame_queueing_durations = FlattenList(stats.frame_queueing_durations)
- if frame_queueing_durations:
- results.AddValue(list_of_scalar_values.ListOfScalarValues(
- results.current_page, 'queueing_durations', 'ms',
- frame_queueing_durations))
-
- # List of raw frame times.
- frame_times = FlattenList(stats.frame_times)
- results.AddValue(list_of_scalar_values.ListOfScalarValues(
- results.current_page, 'frame_times', 'ms', frame_times,
- description='List of raw frame times, helpful to understand the other '
- 'metrics.'))
-
- # Arithmetic mean of frame times.
- mean_frame_time = statistics.ArithmeticMean(frame_times)
- results.AddValue(scalar.ScalarValue(
- results.current_page, 'mean_frame_time', 'ms',
- round(mean_frame_time, 3),
- description='Arithmetic mean of frame times.'))
-
- # Absolute discrepancy of frame time stamps.
- frame_discrepancy = statistics.TimestampsDiscrepancy(
- stats.frame_timestamps)
- results.AddValue(scalar.ScalarValue(
- results.current_page, 'jank', 'ms', round(frame_discrepancy, 4),
+ def _ComputeLatencyMetric(self, page, stats, name, list_of_latency_lists):
+ """Returns Values for the mean and discrepancy for given latency stats."""
+ mean_latency = None
+ latency_discrepancy = None
+ none_value_reason = None
+ if self._HasEnoughFrames(stats.frame_timestamps):
+ latency_list = FlattenList(list_of_latency_lists)
+ if len(latency_list) == 0:
+ return ()
+ mean_latency = round(statistics.ArithmeticMean(latency_list), 3)
+ latency_discrepancy = (
+ round(statistics.DurationsDiscrepancy(latency_list), 4))
+ else:
+ none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE
+ return (
+ scalar.ScalarValue(
+ page, 'mean_%s' % name, 'ms', mean_latency,
+ description='Arithmetic mean of the raw %s values' % name,
+ none_value_reason=none_value_reason),
+ scalar.ScalarValue(
+ page, '%s_discrepancy' % name, 'ms', latency_discrepancy,
+ description='Discrepancy of the raw %s values' % name,
+ none_value_reason=none_value_reason)
+ )
+
+ def _ComputeFirstGestureScrollUpdateLatency(self, page, stats):
+ """Returns a Value for the first gesture scroll update latency."""
+ first_gesture_scroll_update_latency = None
+ none_value_reason = None
+ if self._HasEnoughFrames(stats.frame_timestamps):
+ latency_list = FlattenList(stats.gesture_scroll_update_latency)
+ if len(latency_list) == 0:
+ return ()
+ first_gesture_scroll_update_latency = round(latency_list[0], 4)
+ else:
+ none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE
+ return (
+ scalar.ScalarValue(
+ page, 'first_gesture_scroll_update_latency', 'ms',
+ first_gesture_scroll_update_latency,
+ description='First gesture scroll update latency measures the time it '
+ 'takes to process the very first gesture scroll update '
+ 'input event. The first scroll gesture can often get '
+ 'delayed by work related to page loading.',
+ none_value_reason=none_value_reason),
+ )
+
+ def _ComputeQueueingDuration(self, page, stats):
+ """Returns a Value for the frame queueing durations."""
+ queueing_durations = None
+ none_value_reason = None
+ if 'frame_queueing_durations' in stats.errors:
+ none_value_reason = stats.errors['frame_queueing_durations']
+ elif self._HasEnoughFrames(stats.frame_timestamps):
+ queueing_durations = FlattenList(stats.frame_queueing_durations)
+ if len(queueing_durations) == 0:
+ queueing_durations = None
+ none_value_reason = 'No frame queueing durations recorded.'
+ else:
+ none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE
+ return list_of_scalar_values.ListOfScalarValues(
+ page, 'queueing_durations', 'ms', queueing_durations,
+ description='The frame queueing duration quantifies how out of sync '
+ 'the compositor and renderer threads are. It is the amount '
+ 'of wall time that elapses between a '
+ 'ScheduledActionSendBeginMainFrame event in the compositor '
+ 'thread and the corresponding BeginMainFrame event in the '
+ 'main thread.',
+ none_value_reason=none_value_reason)
+
+ def _ComputeFrameTimeMetric(self, page, stats):
+ """Returns Values for the frame time metrics.
+
+ This includes the raw and mean frame times, as well as the mostly_smooth
+ metric which tracks whether we hit 60 fps for 95% of the frames.
+ """
+ frame_times = None
+ mean_frame_time = None
+ mostly_smooth = None
+ none_value_reason = None
+ if self._HasEnoughFrames(stats.frame_timestamps):
+ frame_times = FlattenList(stats.frame_times)
+ mean_frame_time = round(statistics.ArithmeticMean(frame_times), 3)
+ # We use 19ms as a somewhat looser threshold, instead of 1000.0/60.0.
+ percentile_95 = statistics.Percentile(frame_times, 95.0)
+ mostly_smooth = 1.0 if percentile_95 < 19.0 else 0.0
+ else:
+ none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE
+ return (
+ list_of_scalar_values.ListOfScalarValues(
+ page, 'frame_times', 'ms', frame_times,
+ description='List of raw frame times, helpful to understand the '
+ 'other metrics.',
+ none_value_reason=none_value_reason),
+ scalar.ScalarValue(
+ page, 'mean_frame_time', 'ms', mean_frame_time,
+ description='Arithmetic mean of frame times.',
+ none_value_reason=none_value_reason),
+ scalar.ScalarValue(
+ page, 'mostly_smooth', 'score', mostly_smooth,
+ description='Were 95 percent of the frames hitting 60 fps?'
+ 'boolean value (1/0).',
+ none_value_reason=none_value_reason)
+ )
+
+ def _ComputeFrameTimeDiscrepancy(self, page, stats):
+ """Returns a Value for the absolute discrepancy of frame time stamps."""
+
+ frame_discrepancy = None
+ none_value_reason = None
+ if self._HasEnoughFrames(stats.frame_timestamps):
+ frame_discrepancy = round(statistics.TimestampsDiscrepancy(
+ stats.frame_timestamps), 4)
+ else:
+ none_value_reason = NOT_ENOUGH_FRAMES_MESSAGE
+ return scalar.ScalarValue(
+ page, 'jank', 'ms', frame_discrepancy,