| OLD | NEW |
| 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 from telemetry.util.statistics import DivideIfPossibleOrZero | 5 from telemetry.util.statistics import DivideIfPossibleOrZero |
| 6 | 6 |
| 7 from telemetry.web_perf.metrics import timeline_based_metric | 7 from telemetry.web_perf.metrics import timeline_based_metric |
| 8 from telemetry.value import improvement_direction |
| 8 from telemetry.value import scalar | 9 from telemetry.value import scalar |
| 9 | 10 |
| 10 | 11 |
| 11 class LoadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): | 12 class LoadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): |
| 12 def __init__(self): | 13 def __init__(self): |
| 13 super(LoadTimesTimelineMetric, self).__init__() | 14 super(LoadTimesTimelineMetric, self).__init__() |
| 14 self.report_main_thread_only = True | 15 self.report_main_thread_only = True |
| 15 | 16 |
| 16 def AddResults(self, model, renderer_thread, interaction_records, results): | 17 def AddResults(self, model, renderer_thread, interaction_records, results): |
| 17 assert model | 18 assert model |
| (...skipping 22 matching lines...) Expand all Loading... |
| 40 for event_name, event_group in events_by_name.iteritems(): | 41 for event_name, event_group in events_by_name.iteritems(): |
| 41 times = [event.self_time for event in event_group] | 42 times = [event.self_time for event in event_group] |
| 42 total = sum(times) | 43 total = sum(times) |
| 43 biggest_jank = max(times) | 44 biggest_jank = max(times) |
| 44 | 45 |
| 45 # Results objects cannot contain the '.' character, so remove that here. | 46 # Results objects cannot contain the '.' character, so remove that here. |
| 46 sanitized_event_name = event_name.replace('.', '_') | 47 sanitized_event_name = event_name.replace('.', '_') |
| 47 | 48 |
| 48 full_name = thread_name + '|' + sanitized_event_name | 49 full_name = thread_name + '|' + sanitized_event_name |
| 49 results.AddValue(scalar.ScalarValue( | 50 results.AddValue(scalar.ScalarValue( |
| 50 results.current_page, full_name, 'ms', total)) | 51 results.current_page, full_name, 'ms', total, |
| 52 improvement_direction=improvement_direction.DOWN)) |
| 51 results.AddValue(scalar.ScalarValue( | 53 results.AddValue(scalar.ScalarValue( |
| 52 results.current_page, full_name + '_max', 'ms', biggest_jank)) | 54 results.current_page, full_name + '_max', 'ms', biggest_jank, |
| 55 improvement_direction=improvement_direction.DOWN)) |
| 53 results.AddValue(scalar.ScalarValue( | 56 results.AddValue(scalar.ScalarValue( |
| 54 results.current_page, full_name + '_avg', 'ms', total / len(times))) | 57 results.current_page, full_name + '_avg', 'ms', total / len(times), |
| 58 improvement_direction=improvement_direction.DOWN)) |
| 55 | 59 |
| 56 for counter_name, counter in renderer_process.counters.iteritems(): | 60 for counter_name, counter in renderer_process.counters.iteritems(): |
| 57 total = sum(counter.totals) | 61 total = sum(counter.totals) |
| 58 | 62 |
| 59 # Results objects cannot contain the '.' character, so remove that here. | 63 # Results objects cannot contain the '.' character, so remove that here. |
| 60 sanitized_counter_name = counter_name.replace('.', '_') | 64 sanitized_counter_name = counter_name.replace('.', '_') |
| 61 | 65 |
| 62 results.AddValue(scalar.ScalarValue( | 66 results.AddValue(scalar.ScalarValue( |
| 63 results.current_page, sanitized_counter_name, 'count', total)) | 67 results.current_page, sanitized_counter_name, 'count', total, |
| 68 improvement_direction=improvement_direction.DOWN)) |
| 64 results.AddValue(scalar.ScalarValue( | 69 results.AddValue(scalar.ScalarValue( |
| 65 results.current_page, sanitized_counter_name + '_avg', 'count', | 70 results.current_page, sanitized_counter_name + '_avg', 'count', |
| 66 total / float(len(counter.totals)))) | 71 total / float(len(counter.totals)), |
| 72 improvement_direction=improvement_direction.DOWN)) |
| 67 | 73 |
| 68 # We want to generate a consistant picture of our thread usage, despite | 74 # We want to generate a consistant picture of our thread usage, despite |
| 69 # having several process configurations (in-proc-gpu/single-proc). | 75 # having several process configurations (in-proc-gpu/single-proc). |
| 70 # Since we can't isolate renderer threads in single-process mode, we | 76 # Since we can't isolate renderer threads in single-process mode, we |
| 71 # always sum renderer-process threads' times. We also sum all io-threads | 77 # always sum renderer-process threads' times. We also sum all io-threads |
| 72 # for simplicity. | 78 # for simplicity. |
| 73 TimelineThreadCategories = { | 79 TimelineThreadCategories = { |
| 74 "Chrome_InProcGpuThread": "GPU", | 80 "Chrome_InProcGpuThread": "GPU", |
| 75 "CrGpuMain" : "GPU", | 81 "CrGpuMain" : "GPU", |
| 76 "AsyncTransferThread" : "GPU_transfer", | 82 "AsyncTransferThread" : "GPU_transfer", |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 self.all_slices.extend(self.SlicesInActions(thread.all_slices)) | 194 self.all_slices.extend(self.SlicesInActions(thread.all_slices)) |
| 189 self.toplevel_slices.extend(self.SlicesInActions(thread.toplevel_slices)) | 195 self.toplevel_slices.extend(self.SlicesInActions(thread.toplevel_slices)) |
| 190 | 196 |
| 191 # Currently we report cpu-time per frame, tasks per frame, and possibly | 197 # 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). | 198 # the mean frame (if there is a trace specified to find it). |
| 193 def AddResults(self, num_frames, results): | 199 def AddResults(self, num_frames, results): |
| 194 cpu_per_frame = Rate(self.cpu_time, num_frames) | 200 cpu_per_frame = Rate(self.cpu_time, num_frames) |
| 195 tasks_per_frame = Rate(len(self.toplevel_slices), num_frames) | 201 tasks_per_frame = Rate(len(self.toplevel_slices), num_frames) |
| 196 results.AddValue(scalar.ScalarValue( | 202 results.AddValue(scalar.ScalarValue( |
| 197 results.current_page, ThreadCpuTimeResultName(self.name), | 203 results.current_page, ThreadCpuTimeResultName(self.name), |
| 198 'ms', cpu_per_frame)) | 204 'ms', cpu_per_frame, improvement_direction=improvement_direction.DOWN)) |
| 199 results.AddValue(scalar.ScalarValue( | 205 results.AddValue(scalar.ScalarValue( |
| 200 results.current_page, ThreadTasksResultName(self.name), | 206 results.current_page, ThreadTasksResultName(self.name), |
| 201 'tasks', tasks_per_frame)) | 207 'tasks', tasks_per_frame, |
| 208 improvement_direction=improvement_direction.DOWN)) |
| 202 # Report mean frame time if this is the thread we are using for normalizing | 209 # 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 | 210 # other results. We could report other frame rates (eg. renderer_main) but |
| 204 # this might get confusing. | 211 # this might get confusing. |
| 205 if self.name == FrameTraceThreadName: | 212 if self.name == FrameTraceThreadName: |
| 206 num_frames = self.CountTracesWithName(FrameTraceName) | 213 num_frames = self.CountTracesWithName(FrameTraceName) |
| 207 mean_frame_time = Rate(self.all_action_time, num_frames) | 214 mean_frame_time = Rate(self.all_action_time, num_frames) |
| 208 results.AddValue(scalar.ScalarValue( | 215 results.AddValue(scalar.ScalarValue( |
| 209 results.current_page, ThreadMeanFrameTimeResultName(self.name), | 216 results.current_page, ThreadMeanFrameTimeResultName(self.name), |
| 210 'ms', mean_frame_time)) | 217 'ms', mean_frame_time, |
| 218 improvement_direction=improvement_direction.DOWN)) |
| 211 | 219 |
| 212 def AddDetailedResults(self, num_frames, results): | 220 def AddDetailedResults(self, num_frames, results): |
| 213 slices_by_category = collections.defaultdict(list) | 221 slices_by_category = collections.defaultdict(list) |
| 214 for s in self.all_slices: | 222 for s in self.all_slices: |
| 215 slices_by_category[s.category].append(s) | 223 slices_by_category[s.category].append(s) |
| 216 all_self_times = [] | 224 all_self_times = [] |
| 217 for category, slices_in_category in slices_by_category.iteritems(): | 225 for category, slices_in_category in slices_by_category.iteritems(): |
| 218 self_time = sum([x.self_time for x in slices_in_category]) | 226 self_time = sum([x.self_time for x in slices_in_category]) |
| 219 all_self_times.append(self_time) | 227 all_self_times.append(self_time) |
| 220 self_time_result = (float(self_time) / num_frames) if num_frames else 0 | 228 self_time_result = (float(self_time) / num_frames) if num_frames else 0 |
| 221 results.AddValue(scalar.ScalarValue( | 229 results.AddValue(scalar.ScalarValue( |
| 222 results.current_page, ThreadDetailResultName(self.name, category), | 230 results.current_page, ThreadDetailResultName(self.name, category), |
| 223 'ms', self_time_result)) | 231 'ms', self_time_result, |
| 232 improvement_direction=improvement_direction.DOWN)) |
| 224 all_measured_time = sum(all_self_times) | 233 all_measured_time = sum(all_self_times) |
| 225 idle_time = max(0, self.all_action_time - all_measured_time) | 234 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 | 235 idle_time_result = (float(idle_time) / num_frames) if num_frames else 0 |
| 227 results.AddValue(scalar.ScalarValue( | 236 results.AddValue(scalar.ScalarValue( |
| 228 results.current_page, ThreadDetailResultName(self.name, "idle"), | 237 results.current_page, ThreadDetailResultName(self.name, "idle"), |
| 229 'ms', idle_time_result)) | 238 'ms', idle_time_result, |
| 239 improvement_direction=improvement_direction.DOWN)) |
| 230 | 240 |
| 231 def CountTracesWithName(self, substring): | 241 def CountTracesWithName(self, substring): |
| 232 count = 0 | 242 count = 0 |
| 233 for event in self.all_slices: | 243 for event in self.all_slices: |
| 234 if substring in event.name: | 244 if substring in event.name: |
| 235 count += 1 | 245 count += 1 |
| 236 return count | 246 return count |
| 237 | 247 |
| 238 class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): | 248 class ThreadTimesTimelineMetric(timeline_based_metric.TimelineBasedMetric): |
| 239 def __init__(self): | 249 def __init__(self): |
| (...skipping 28 matching lines...) Expand all Loading... |
| 268 num_frames = frame_rate_thread.CountTracesWithName(FrameTraceName) | 278 num_frames = frame_rate_thread.CountTracesWithName(FrameTraceName) |
| 269 | 279 |
| 270 # Report the desired results and details. | 280 # Report the desired results and details. |
| 271 for thread_results in thread_category_results.values(): | 281 for thread_results in thread_category_results.values(): |
| 272 if thread_results.name in self.results_to_report: | 282 if thread_results.name in self.results_to_report: |
| 273 thread_results.AddResults(num_frames, results) | 283 thread_results.AddResults(num_frames, results) |
| 274 # TOOD(nduca): When generic results objects are done, this special case | 284 # TOOD(nduca): When generic results objects are done, this special case |
| 275 # can be replaced with a generic UI feature. | 285 # can be replaced with a generic UI feature. |
| 276 if thread_results.name in self.details_to_report: | 286 if thread_results.name in self.details_to_report: |
| 277 thread_results.AddDetailedResults(num_frames, results) | 287 thread_results.AddDetailedResults(num_frames, results) |
| OLD | NEW |