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 |