| 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 | 5 |
| 6 from metrics import Metric | 6 from metrics import Metric |
| 7 from telemetry.page import page_measurement | 7 from telemetry.page import page_measurement |
| 8 | 8 |
| 9 TRACING_MODE = 'tracing-mode' | 9 TRACING_MODE = 'tracing-mode' |
| 10 TIMELINE_MODE = 'timeline-mode' | 10 TIMELINE_MODE = 'timeline-mode' |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 144 AllThreads = TimelineThreadCategories.values() | 144 AllThreads = TimelineThreadCategories.values() |
| 145 NoThreads = [] | 145 NoThreads = [] |
| 146 MainThread = ["renderer_main"] | 146 MainThread = ["renderer_main"] |
| 147 FastPathResults = AllThreads | 147 FastPathResults = AllThreads |
| 148 FastPathDetails = NoThreads | 148 FastPathDetails = NoThreads |
| 149 SilkResults = ["renderer_main", "total_all"] | 149 SilkResults = ["renderer_main", "total_all"] |
| 150 SilkDetails = MainThread | 150 SilkDetails = MainThread |
| 151 | 151 |
| 152 # TODO(epenner): Thread names above are likely fairly stable but trace names | 152 # TODO(epenner): Thread names above are likely fairly stable but trace names |
| 153 # could change. We should formalize this trace to keep this robust. | 153 # could change. We should formalize this trace to keep this robust. |
| 154 GpuFrameTraceName = ":RealSwapBuffers" | 154 CompositorFrameTraceName = "::SwapBuffers" |
| 155 # TODO(epenner): The decoder swap-buffers can be used by several producers. | |
| 156 # we need to find the canonical swap buffers on Mac. | |
| 157 GpuFrameTraceNameMac = "GLES2DecoderImpl::DoSwapBuffers" | |
| 158 | 155 |
| 159 def ThreadCategoryName(thread_name): | 156 def ThreadCategoryName(thread_name): |
| 160 thread_category = "other" | 157 thread_category = "other" |
| 161 for substring, category in TimelineThreadCategories.iteritems(): | 158 for substring, category in TimelineThreadCategories.iteritems(): |
| 162 if substring in MatchBySubString and substring in thread_name: | 159 if substring in MatchBySubString and substring in thread_name: |
| 163 thread_category = category | 160 thread_category = category |
| 164 if thread_name in TimelineThreadCategories: | 161 if thread_name in TimelineThreadCategories: |
| 165 thread_category = TimelineThreadCategories[thread_name] | 162 thread_category = TimelineThreadCategories[thread_name] |
| 166 return thread_category | 163 return thread_category |
| 167 | 164 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 198 res += x.thread_duration | 195 res += x.thread_duration |
| 199 return res | 196 return res |
| 200 | 197 |
| 201 def AppendThreadSlices(self, thread): | 198 def AppendThreadSlices(self, thread): |
| 202 self.all_slices.extend(thread.all_slices) | 199 self.all_slices.extend(thread.all_slices) |
| 203 self.toplevel_slices.extend(thread.toplevel_slices) | 200 self.toplevel_slices.extend(thread.toplevel_slices) |
| 204 | 201 |
| 205 def AddResults(self, num_frames, results): | 202 def AddResults(self, num_frames, results): |
| 206 clock_report_name = ThreadTimeResultName(self.name) | 203 clock_report_name = ThreadTimeResultName(self.name) |
| 207 cpu_report_name = ThreadCpuTimeResultName(self.name) | 204 cpu_report_name = ThreadCpuTimeResultName(self.name) |
| 208 clock_per_frame = float(self.clock_time) / num_frames | 205 clock_per_frame = (float(self.clock_time) / num_frames) if num_frames else 0 |
| 209 cpu_per_frame = float(self.cpu_time) / num_frames | 206 cpu_per_frame = (float(self.cpu_time) / num_frames) if num_frames else 0 |
| 210 results.Add(clock_report_name, 'ms', clock_per_frame) | 207 results.Add(clock_report_name, 'ms', clock_per_frame) |
| 211 results.Add(cpu_report_name, 'ms', cpu_per_frame) | 208 results.Add(cpu_report_name, 'ms', cpu_per_frame) |
| 212 | 209 |
| 213 def AddDetailedResults(self, num_frames, results): | 210 def AddDetailedResults(self, num_frames, results): |
| 214 slices_by_category = collections.defaultdict(list) | 211 slices_by_category = collections.defaultdict(list) |
| 215 for s in self.all_slices: | 212 for s in self.all_slices: |
| 216 slices_by_category[s.category].append(s) | 213 slices_by_category[s.category].append(s) |
| 217 all_self_times = [] | 214 all_self_times = [] |
| 218 for category, slices_in_category in slices_by_category.iteritems(): | 215 for category, slices_in_category in slices_by_category.iteritems(): |
| 219 self_time = sum([x.self_time for x in slices_in_category]) | 216 self_time = sum([x.self_time for x in slices_in_category]) |
| 220 all_self_times.append(self_time) | 217 all_self_times.append(self_time) |
| 221 self_time_result = float(self_time) / num_frames | 218 self_time_result = (float(self_time) / num_frames) if num_frames else 0 |
| 222 results.Add(ThreadDetailResultName(self.name, category), | 219 results.Add(ThreadDetailResultName(self.name, category), |
| 223 'ms', self_time_result) | 220 'ms', self_time_result) |
| 224 all_measured_time = sum(all_self_times) | 221 all_measured_time = sum(all_self_times) |
| 225 idle_time = max(0, self.model.bounds.bounds - all_measured_time) | 222 idle_time = max(0, self.model.bounds.bounds - all_measured_time) |
| 226 idle_time_result = float(idle_time) / num_frames | 223 idle_time_result = (float(idle_time) / num_frames) if num_frames else 0 |
| 227 results.Add(ThreadDetailResultName(self.name, "idle"), | 224 results.Add(ThreadDetailResultName(self.name, "idle"), |
| 228 'ms', idle_time_result) | 225 'ms', idle_time_result) |
| 229 | 226 |
| 230 class ThreadTimesTimelineMetric(TimelineMetric): | 227 class ThreadTimesTimelineMetric(TimelineMetric): |
| 231 def __init__(self): | 228 def __init__(self): |
| 232 super(ThreadTimesTimelineMetric, self).__init__(TRACING_MODE) | 229 super(ThreadTimesTimelineMetric, self).__init__(TRACING_MODE) |
| 233 self.results_to_report = AllThreads | 230 self.results_to_report = AllThreads |
| 234 self.details_to_report = NoThreads | 231 self.details_to_report = NoThreads |
| 235 | 232 |
| 236 def CountSlices(self, slices, substring): | 233 def CountSlices(self, slices, substring): |
| (...skipping 16 matching lines...) Expand all Loading... |
| 253 | 250 |
| 254 # Group all threads. | 251 # Group all threads. |
| 255 for thread in self._model.GetAllThreads(): | 252 for thread in self._model.GetAllThreads(): |
| 256 thread_category_results['total_all'].AppendThreadSlices(thread) | 253 thread_category_results['total_all'].AppendThreadSlices(thread) |
| 257 | 254 |
| 258 # Also group fast-path threads. | 255 # Also group fast-path threads. |
| 259 for thread in self._model.GetAllThreads(): | 256 for thread in self._model.GetAllThreads(): |
| 260 if ThreadCategoryName(thread.name) in FastPath: | 257 if ThreadCategoryName(thread.name) in FastPath: |
| 261 thread_category_results['total_fast_path'].AppendThreadSlices(thread) | 258 thread_category_results['total_fast_path'].AppendThreadSlices(thread) |
| 262 | 259 |
| 263 # Calculate the number of frames from the GPU thread. | 260 # Calculate the number of frames from the CC thread. |
| 264 gpu_slices = thread_category_results['GPU'].all_slices | 261 cc_slices = thread_category_results['renderer_compositor'].all_slices |
| 265 num_frames = self.CountSlices(gpu_slices, GpuFrameTraceName) | 262 num_frames = self.CountSlices(cc_slices, CompositorFrameTraceName) |
| 266 if not num_frames: | |
| 267 num_frames = self.CountSlices(gpu_slices, GpuFrameTraceNameMac) | |
| 268 if not num_frames: | |
| 269 raise MissingFramesError() | |
| 270 | 263 |
| 271 # Report the desired results and details. | 264 # Report the desired results and details. |
| 272 for thread_results in thread_category_results.values(): | 265 for thread_results in thread_category_results.values(): |
| 273 if thread_results.name in self.results_to_report: | 266 if thread_results.name in self.results_to_report: |
| 274 thread_results.AddResults(num_frames, results) | 267 thread_results.AddResults(num_frames, results) |
| 275 # TOOD(nduca): When generic results objects are done, this special case | 268 # TOOD(nduca): When generic results objects are done, this special case |
| 276 # can be replaced with a generic UI feature. | 269 # can be replaced with a generic UI feature. |
| 277 if thread_results.name in self.details_to_report: | 270 if thread_results.name in self.details_to_report: |
| 278 thread_results.AddDetailedResults(num_frames, results) | 271 thread_results.AddDetailedResults(num_frames, results) |
| OLD | NEW |