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

Side by Side Diff: tools/perf/metrics/timeline.py

Issue 1097463004: Add key_idle_power_cases for ensuring idle activity on Android (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 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
« no previous file with comments | « tools/perf/measurements/thread_times.py ('k') | tools/perf/page_sets/key_power_cases.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2014 The Chromium Authors. All rights reserved. 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 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 import collections 4 import collections
5 5
6 from telemetry.util.statistics import DivideIfPossibleOrZero 6 from telemetry.util.statistics import DivideIfPossibleOrZero
7 from telemetry.value import scalar 7 from telemetry.value import scalar
8 from telemetry.web_perf.metrics import timeline_based_metric 8 from telemetry.web_perf.metrics import timeline_based_metric
9 9
10 10
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 120
121 def ThreadCategoryName(thread_name): 121 def ThreadCategoryName(thread_name):
122 thread_category = "other" 122 thread_category = "other"
123 for substring, category in TimelineThreadCategories.iteritems(): 123 for substring, category in TimelineThreadCategories.iteritems():
124 if substring in _MatchBySubString and substring in thread_name: 124 if substring in _MatchBySubString and substring in thread_name:
125 thread_category = category 125 thread_category = category
126 if thread_name in TimelineThreadCategories: 126 if thread_name in TimelineThreadCategories:
127 thread_category = TimelineThreadCategories[thread_name] 127 thread_category = TimelineThreadCategories[thread_name]
128 return thread_category 128 return thread_category
129 129
130 def ThreadCpuTimeResultName(thread_category):
131 # This isn't a good name, but I don't want to change it and lose continuity.
132 return "thread_" + thread_category + "_cpu_time_per_frame"
133
134 def ThreadTasksResultName(thread_category):
135 return "tasks_per_frame_" + thread_category
136
137 def ThreadMeanFrameTimeResultName(thread_category):
138 return "mean_frame_time_" + thread_category
139
140 def ThreadDetailResultName(thread_category, detail): 130 def ThreadDetailResultName(thread_category, detail):
141 detail_sanitized = detail.replace('.','_') 131 detail_sanitized = detail.replace('.','_')
142 return "thread_" + thread_category + "|" + detail_sanitized 132 return "thread_" + thread_category + "|" + detail_sanitized
143 133
144 134
145 class ResultsForThread(object): 135 class ResultsForThread(object):
146 def __init__(self, model, record_ranges, name): 136 def __init__(self, model, record_ranges, name, measure_per_frame):
147 self.model = model 137 self.model = model
148 self.toplevel_slices = [] 138 self.toplevel_slices = []
149 self.all_slices = [] 139 self.all_slices = []
150 self.name = name 140 self.name = name
151 self.record_ranges = record_ranges 141 self.record_ranges = record_ranges
152 self.all_action_time = \ 142 self.all_action_time = \
153 sum([record_range.bounds for record_range in self.record_ranges]) 143 sum([record_range.bounds for record_range in self.record_ranges])
144 self.measure_per_frame = measure_per_frame
154 145
155 @property 146 @property
156 def clock_time(self): 147 def clock_time(self):
157 clock_duration = sum([x.duration for x in self.toplevel_slices]) 148 clock_duration = sum([x.duration for x in self.toplevel_slices])
158 clock_overhead = sum([ClockOverheadForEvent(x) for x in self.all_slices]) 149 clock_overhead = sum([ClockOverheadForEvent(x) for x in self.all_slices])
159 return clock_duration - clock_overhead 150 return clock_duration - clock_overhead
160 151
161 @property 152 @property
162 def cpu_time(self): 153 def cpu_time(self):
163 cpu_duration = 0 154 cpu_duration = 0
(...skipping 20 matching lines...) Expand all
184 break 175 break
185 return slices_in_actions 176 return slices_in_actions
186 177
187 def AppendThreadSlices(self, thread): 178 def AppendThreadSlices(self, thread):
188 self.all_slices.extend(self.SlicesInActions(thread.all_slices)) 179 self.all_slices.extend(self.SlicesInActions(thread.all_slices))
189 self.toplevel_slices.extend(self.SlicesInActions(thread.toplevel_slices)) 180 self.toplevel_slices.extend(self.SlicesInActions(thread.toplevel_slices))
190 181
191 # Currently we report cpu-time per frame, tasks per frame, and possibly 182 # Currently we report cpu-time per frame, tasks per frame, and possibly
192 # the mean frame (if there is a trace specified to find it). 183 # the mean frame (if there is a trace specified to find it).
193 def AddResults(self, num_frames, results): 184 def AddResults(self, num_frames, results):
194 cpu_per_frame = Rate(self.cpu_time, num_frames) 185 num_intervals = num_frames if self.measure_per_frame else 1
195 tasks_per_frame = Rate(len(self.toplevel_slices), num_frames) 186 cpu_per_interval = Rate(self.cpu_time, num_intervals)
187 tasks_per_interval = Rate(len(self.toplevel_slices), num_intervals)
196 results.AddValue(scalar.ScalarValue( 188 results.AddValue(scalar.ScalarValue(
197 results.current_page, ThreadCpuTimeResultName(self.name), 189 results.current_page,
198 'ms', cpu_per_frame)) 190 self.ThreadCpuTimeResultName(self.name), 'ms', cpu_per_interval))
199 results.AddValue(scalar.ScalarValue( 191 results.AddValue(scalar.ScalarValue(
200 results.current_page, ThreadTasksResultName(self.name), 192 results.current_page, self.ThreadTasksResultName(self.name),
201 'tasks', tasks_per_frame)) 193 'tasks', tasks_per_interval))
202 # Report mean frame time if this is the thread we are using for normalizing 194 # Report mean frame time if this is the thread we are using for normalizing
203 # other results. We could report other frame rates (eg. renderer_main) but 195 # other results. We could report other frame rates (eg. renderer_main) but
204 # this might get confusing. 196 # this might get confusing.
205 if self.name == FrameTraceThreadName: 197 if self.name == FrameTraceThreadName:
206 num_frames = self.CountTracesWithName(FrameTraceName) 198 num_intervals = self.CountTracesWithName(FrameTraceName) \
207 mean_frame_time = Rate(self.all_action_time, num_frames) 199 if self.measure_per_frame else 1
200 frame_time = Rate(self.all_action_time, num_intervals)
208 results.AddValue(scalar.ScalarValue( 201 results.AddValue(scalar.ScalarValue(
209 results.current_page, ThreadMeanFrameTimeResultName(self.name), 202 results.current_page, self.ThreadFrameTimeResultName(self.name),
210 'ms', mean_frame_time)) 203 'ms', frame_time))
211 204
212 def AddDetailedResults(self, num_frames, results): 205 def AddDetailedResults(self, num_frames, results):
206 num_intervals = num_frames if self.measure_per_frame else 1
213 slices_by_category = collections.defaultdict(list) 207 slices_by_category = collections.defaultdict(list)
214 for s in self.all_slices: 208 for s in self.all_slices:
215 slices_by_category[s.category].append(s) 209 slices_by_category[s.category].append(s)
216 all_self_times = [] 210 all_self_times = []
217 for category, slices_in_category in slices_by_category.iteritems(): 211 for category, slices_in_category in slices_by_category.iteritems():
218 self_time = sum([x.self_time for x in slices_in_category]) 212 self_time = sum([x.self_time for x in slices_in_category])
219 all_self_times.append(self_time) 213 all_self_times.append(self_time)
220 self_time_result = (float(self_time) / num_frames) if num_frames else 0 214 self_time_result = \
rnephew (Reviews Here) 2015/04/23 18:28:05 nit: use (...) instead of \
jdduke (slow) 2015/04/24 16:10:52 Done.
215 (float(self_time) / num_intervals) if num_intervals else 0
221 results.AddValue(scalar.ScalarValue( 216 results.AddValue(scalar.ScalarValue(
222 results.current_page, ThreadDetailResultName(self.name, category), 217 results.current_page, ThreadDetailResultName(self.name, category),
223 'ms', self_time_result)) 218 'ms', self_time_result))
224 all_measured_time = sum(all_self_times) 219 all_measured_time = sum(all_self_times)
225 idle_time = max(0, self.all_action_time - all_measured_time) 220 idle_time = max(0, self.all_action_time - all_measured_time)
226 idle_time_result = (float(idle_time) / num_frames) if num_frames else 0 221 idle_time_result = \
rnephew (Reviews Here) 2015/04/23 18:28:05 Same
jdduke (slow) 2015/04/24 16:10:52 Done.
222 (float(idle_time) / num_intervals) if num_intervals else 0
227 results.AddValue(scalar.ScalarValue( 223 results.AddValue(scalar.ScalarValue(
228 results.current_page, ThreadDetailResultName(self.name, "idle"), 224 results.current_page, ThreadDetailResultName(self.name, "idle"),
229 'ms', idle_time_result)) 225 'ms', idle_time_result))
230 226
231 def CountTracesWithName(self, substring): 227 def CountTracesWithName(self, substring):
232 count = 0 228 count = 0
233 for event in self.all_slices: 229 for event in self.all_slices:
234 if substring in event.name: 230 if substring in event.name:
235 count += 1 231 count += 1
236 return count 232 return count
237 233
234 def ThreadCpuTimeResultName(self, thread_category):
235 # This isn't a good name, but I don't want to change it and lose continuity.
236 if self.measure_per_frame:
237 return "thread_" + thread_category + "_cpu_time_per_frame"
238 return "thread_" + thread_category + "_cpu_time_total"
239
240 def ThreadTasksResultName(self, thread_category):
241 if self.measure_per_frame:
242 return "tasks_per_frame_" + thread_category
243 return "tasks_" + thread_category
244
245 def ThreadFrameTimeResultName(self, thread_category):
246 if self.measure_per_frame:
247 return "mean_frame_time_" + thread_category
248 return "total_frame_time_" + thread_category
249
250
238 class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): 251 class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric):
239 def __init__(self): 252 def __init__(self, measure_per_frame=True):
240 super(ThreadTimesTimelineMetric, self).__init__() 253 super(ThreadTimesTimelineMetric, self).__init__()
241 # Minimal traces, for minimum noise in CPU-time measurements. 254 # Minimal traces, for minimum noise in CPU-time measurements.
242 self.results_to_report = AllThreads 255 self.results_to_report = AllThreads
243 self.details_to_report = NoThreads 256 self.details_to_report = NoThreads
257 self.measure_per_frame = measure_per_frame
244 258
245 def AddResults(self, model, _, interaction_records, results): 259 def AddResults(self, model, _, interaction_records, results):
246 # Set up each thread category for consistant results. 260 # Set up each thread category for consistant results.
247 thread_category_results = {} 261 thread_category_results = {}
248 for name in TimelineThreadCategories.values(): 262 for name in TimelineThreadCategories.values():
249 thread_category_results[name] = ResultsForThread( 263 thread_category_results[name] = ResultsForThread(
250 model, [r.GetBounds() for r in interaction_records], name) 264 model, [r.GetBounds() for r in interaction_records], name,
rnephew (Reviews Here) 2015/04/23 18:28:05 nit: I know it was there before but it's under ind
jdduke (slow) 2015/04/24 16:10:52 Done.
265 self.measure_per_frame)
251 266
252 # Group the slices by their thread category. 267 # Group the slices by their thread category.
253 for thread in model.GetAllThreads(): 268 for thread in model.GetAllThreads():
254 thread_category = ThreadCategoryName(thread.name) 269 thread_category = ThreadCategoryName(thread.name)
255 thread_category_results[thread_category].AppendThreadSlices(thread) 270 thread_category_results[thread_category].AppendThreadSlices(thread)
256 271
257 # Group all threads. 272 # Group all threads.
258 for thread in model.GetAllThreads(): 273 for thread in model.GetAllThreads():
259 thread_category_results['total_all'].AppendThreadSlices(thread) 274 thread_category_results['total_all'].AppendThreadSlices(thread)
260 275
261 # Also group fast-path threads. 276 # Also group fast-path threads.
262 for thread in model.GetAllThreads(): 277 for thread in model.GetAllThreads():
263 if ThreadCategoryName(thread.name) in FastPathThreads: 278 if ThreadCategoryName(thread.name) in FastPathThreads:
264 thread_category_results['total_fast_path'].AppendThreadSlices(thread) 279 thread_category_results['total_fast_path'].AppendThreadSlices(thread)
265 280
266 # Calculate the number of frames. 281 # Calculate the number of frames.
267 frame_rate_thread = thread_category_results[FrameTraceThreadName] 282 frame_rate_thread = thread_category_results[FrameTraceThreadName]
268 num_frames = frame_rate_thread.CountTracesWithName(FrameTraceName) 283 num_frames = frame_rate_thread.CountTracesWithName(FrameTraceName)
269 284
270 # Report the desired results and details. 285 # Report the desired results and details.
271 for thread_results in thread_category_results.values(): 286 for thread_results in thread_category_results.values():
272 if thread_results.name in self.results_to_report: 287 if thread_results.name in self.results_to_report:
273 thread_results.AddResults(num_frames, results) 288 thread_results.AddResults(num_frames, results)
274 # TOOD(nduca): When generic results objects are done, this special case 289 # TOOD(nduca): When generic results objects are done, this special case
275 # can be replaced with a generic UI feature. 290 # can be replaced with a generic UI feature.
276 if thread_results.name in self.details_to_report: 291 if thread_results.name in self.details_to_report:
277 thread_results.AddDetailedResults(num_frames, results) 292 thread_results.AddDetailedResults(num_frames, results)
OLDNEW
« no previous file with comments | « tools/perf/measurements/thread_times.py ('k') | tools/perf/page_sets/key_power_cases.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698