Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: tools/telemetry/telemetry/web_perf/metrics/mainthread_jank.py

Issue 273103003: Add responsiveness_metric for timeline_based_measurement (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address Chris's comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 import logging
5
6 from telemetry.web_perf.metrics import timeline_based_metric
7 from telemetry.web_perf import timeline_interaction_record as tir_module
8
9 # A top slice (defined below) of a main thread can cause the webapp to behave
10 # unresponsively if its thread duration is greater than or equals to
11 # USER_PERCEIVABLE_DELAY_THRESHOLD_MS. Human eyes can perceive delay at low as
12 # 100ms, but since we use thread time instead of wall-time, we reduce the
13 # threshold further to 50ms to make room for other OS's activity.
14 USER_PERCEIVABLE_DELAY_THRESHOLD_MS = 50
15
16
17 def _IsTopSlice(event):
18 """Whether event refers to a top MessageLoop task, i.e: there is no
19 other MessageLoop task on top of this task and contains it.
20
21 Returns:
22 True if this timeline event refers to the top MesssageLoop task.
23 False otherwise.
24 """
25 return event.name == 'MessageLoop::RunTask' and event.category == 'toplevel'
26
27
28 class _MainthreadJankStat(object):
29 """A small wrapper class for storing stats related to mainthread jank."""
30
31 def __init__(self):
32 self.num_big_top_slices = 0
33 self.sum_top_slices_thread_time = 0
34 self.sum_big_top_slices_thread_time = 0
35 self.biggest_top_slice_thread_time = 0
36
37
38 def _ComputeMainthreadJankStats(renderer_thread, record):
39 """Computes the mainthread jank stat on the record range.
40
41 Returns:
42 An instance of _MainthreadJankStat, which has:
43
44 num_big_top_slices is the number of top slices whose thread time ranges
45 overlapped with (thread_start, thread_end) and the overlapped thread
46 duration is greater than or equal USER_PERCEIVABLE_DELAY_THRESHOLD_MS.
47
48 sum_top_slices_thread_time is the total thread duration of all top slices
49 whose thread time ranges overlapped with the (thread_start, thread_end)
50 time of record.
51
52 sum_big_top_slices_thread_time is the total thread duration of all top
53 slices whose thread time ranges overlapped with (thread_start, thread_end)
54 and the overlapped thread duration is greater than or equal
55 USER_PERCEIVABLE_DELAY_THRESHOLD_MS.
56
57 biggest_top_slice_thread_time is the biggest thread duration of all
58 top slices whose thread time ranges overlapped with
59 (thread_start, thread_end).
60
61 Note: thread duration of each slices is computed using overlapped range
62 with (thread_start, thread_end).
63 """
64 stat = _MainthreadJankStat()
65 # If a slice overlaps with record in thread time, it will also overlap with
66 # the record in wall-time. Hence we can iterate through all slices that
67 # overlap with record's start & end in wall time.
68 for s in renderer_thread.IterAllSlicesOverlappedWithTimeRange(
69 record.start, record.end):
70 if not _IsTopSlice(s):
nduca 2014/05/29 23:33:12 so we have "toplevel slices" on a thread that are
nednguyen 2014/05/30 16:38:26 Done. I just iterate through all the top slices. I
71 continue
72 jank_thread_duration = record.GetOverlappedThreadTimeForSlice(s)
73 stat.sum_top_slices_thread_time += jank_thread_duration
74 stat.biggest_top_slice_thread_time = max(
75 stat.biggest_top_slice_thread_time, jank_thread_duration)
76 if jank_thread_duration >= USER_PERCEIVABLE_DELAY_THRESHOLD_MS:
77 stat.num_big_top_slices += 1
78 stat.sum_big_top_slices_thread_time += jank_thread_duration
79 return stat
80
81
82 class MainthreadJankMetric(timeline_based_metric.TimelineBasedMetric):
83 """Computes the mainthread jank metrics on the record ranges.
84
85 num_big_mainthread_jank is the number of top slices whose thread time
86 ranges overlapped with any thread time ranges of the records and the
87 overlapped thread duration is greater than or equal
88 USER_PERCEIVABLE_DELAY_THRESHOLD_MS.
89
90 total_mainthread_jank_thread_time is the total thread duration of all top
91 slices whose thread time ranges overlapped with any thread time ranges of
92 the records.
93
94 total_big_jank_thread_time is the total thread duration of all top
95 slices whose thread time ranges overlapped with any thread time ranges of
96 the records and the overlapped thread duration is greater than or equal
97 USER_PERCEIVABLE_DELAY_THRESHOLD_MS.
98
99 biggest_jank_thread_time is the biggest thread duration of all
100 top slices whose thread time ranges overlapped with any of records' thread
101 time ranges.
102 """
103
104 def __init__(self):
105 super(MainthreadJankMetric, self).__init__()
106
107 def AddResults(self, _, renderer_thread, interaction_records, results):
108 self.VerifyNonOverlappedRecords(interaction_records)
109 num_big_janks = 0
110 total_mainthread_jank_thread_time = 0
111 total_big_jank_thread_time = 0
112 biggest_jank_thread_time = 0
113
114 try:
115 for record in interaction_records:
116 record_jank_stat = _ComputeMainthreadJankStats(renderer_thread, record)
117 num_big_janks += record_jank_stat.num_big_top_slices
118 total_mainthread_jank_thread_time += (
119 record_jank_stat.sum_top_slices_thread_time)
120 total_big_jank_thread_time += (
121 record_jank_stat.sum_big_top_slices_thread_time)
122 biggest_jank_thread_time = (
123 max(biggest_jank_thread_time,
124 record_jank_stat.biggest_top_slice_thread_time))
125 # TODO(nednguyen): maybe fall back to use wall-time for computing the
126 # metrics.
127 except tir_module.NoThreadTimeDataException as e:
128 logging.warning(
129 'Main thread jank metrics cannot be computed since trace does not '
nduca 2014/05/29 23:33:12 this is going to spam the console hugely... can yo
nednguyen 2014/05/30 16:38:26 By hugely, do you mean one log line per list of re
130 'contain thread time data. %s', repr(e))
131 return
132
133 results.Add('num_big_mainthread_janks', 'score', num_big_janks)
nduca 2014/05/29 23:33:12 are these all important? can you please pick 1 tha
nednguyen 2014/05/30 16:38:26 I think num_big_mainthread_janks and total_big_jan
134 results.Add('total_mainthread_jank_thread_time', 'ms',
135 total_mainthread_jank_thread_time)
136 results.Add('total_big_jank_thread_time', 'ms',
137 total_big_jank_thread_time)
138 results.Add('biggest_jank_thread_time', 'ms', biggest_jank_thread_time)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698