Chromium Code Reviews| 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 import itertools | 5 import itertools |
| 6 | 6 |
| 7 from metrics import Metric | 7 from metrics import Metric |
| 8 from telemetry.core.timeline import bounds | 8 from telemetry.core.timeline import bounds |
| 9 from telemetry.page import page_measurement | 9 from telemetry.page import page_measurement |
| 10 | 10 |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 | 133 |
| 134 # We want to generate a consistant picture of our thread usage, despite | 134 # We want to generate a consistant picture of our thread usage, despite |
| 135 # having several process configurations (in-proc-gpu/single-proc). | 135 # having several process configurations (in-proc-gpu/single-proc). |
| 136 # Since we can't isolate renderer threads in single-process mode, we | 136 # Since we can't isolate renderer threads in single-process mode, we |
| 137 # always sum renderer-process threads' times. We also sum all io-threads | 137 # always sum renderer-process threads' times. We also sum all io-threads |
| 138 # for simplicity. | 138 # for simplicity. |
| 139 TimelineThreadCategories = { | 139 TimelineThreadCategories = { |
| 140 "Chrome_InProcGpuThread": "GPU", | 140 "Chrome_InProcGpuThread": "GPU", |
| 141 "CrGpuMain" : "GPU", | 141 "CrGpuMain" : "GPU", |
| 142 "AsyncTransferThread" : "GPU_transfer", | 142 "AsyncTransferThread" : "GPU_transfer", |
| 143 "CrBrowserMain" : "browser_main", | 143 "CrBrowserMain" : "browser", |
| 144 "Browser Compositor" : "browser_compositor", | 144 "Browser Compositor" : "browser", |
| 145 "CrRendererMain" : "renderer_main", | 145 "CrRendererMain" : "renderer_main", |
| 146 "Compositor" : "renderer_compositor", | 146 "Compositor" : "renderer_compositor", |
| 147 "IOThread" : "IO", | 147 "IOThread" : "IO", |
| 148 "CompositorRasterWorker": "raster", | 148 "CompositorRasterWorker": "raster", |
| 149 "DummyThreadName1" : "other", | 149 "DummyThreadName1" : "other", |
| 150 "DummyThreadName2" : "total_fast_path", | 150 "DummyThreadName2" : "total_fast_path", |
| 151 "DummyThreadName3" : "total_all" | 151 "DummyThreadName3" : "total_all" |
| 152 } | 152 } |
| 153 | 153 |
| 154 MatchBySubString = ["IOThread", "CompositorRasterWorker"] | 154 MatchBySubString = ["IOThread", "CompositorRasterWorker"] |
| 155 | 155 |
| 156 AllThreads = TimelineThreadCategories.values() | 156 AllThreads = TimelineThreadCategories.values() |
| 157 NoThreads = [] | 157 NoThreads = [] |
| 158 FastPathThreads = ["GPU", | 158 |
| 159 "browser_main", | 159 FastPathThreads = ["GPU", "renderer_compositor", "browser", "IO"] |
| 160 "browser_compositor", | |
| 161 "renderer_compositor", | |
| 162 "IO"] | |
| 163 MainThread = ["renderer_main"] | |
| 164 FastPathResults = AllThreads | 160 FastPathResults = AllThreads |
| 165 FastPathDetails = NoThreads | 161 FastPathDetails = NoThreads |
| 166 SilkResults = ["renderer_main", "total_all"] | 162 SilkResults = ["renderer_main", "total_all"] |
| 167 SilkDetails = MainThread | 163 SilkDetails = ["renderer_main"] |
| 168 | 164 |
| 169 # TODO(epenner): Thread names above are likely fairly stable but trace names | 165 # TODO(epenner): Thread names above are likely fairly stable but trace names |
| 170 # could change. We should formalize this trace to keep this robust. | 166 # could change. We should formalize these traces to keep this robust. |
| 171 CompositorFrameTraceName = "::SwapBuffers" | 167 OverheadTraceCategory = "trace_event_overhead" |
|
nduca
2014/02/05 00:34:11
global vars sould be prefixed with _ when not inte
| |
| 168 OverheadTraceName = "overhead" | |
| 169 FrameTraceName = "::SwapBuffers" | |
| 170 FrameTraceThread = "renderer_compositor" | |
| 171 | |
| 172 def ClockOverhead(event): | |
|
nduca
2014/02/05 00:34:11
GetClockOverheadFromEvent
| |
| 173 if (event.category == OverheadTraceCategory and | |
| 174 event.name == OverheadTraceName): | |
| 175 return event.duration | |
| 176 else: | |
| 177 return 0 | |
| 178 | |
| 179 def CpuOverhead(event): | |
|
nduca
2014/02/05 00:34:11
GetCpuOverheadFromEvent or someting like that
| |
| 180 if (event.category == OverheadTraceCategory and | |
| 181 event.name == OverheadTraceName and | |
| 182 event.thread_duration): | |
| 183 return event.thread_duration | |
| 184 else: | |
| 185 return 0 | |
| 172 | 186 |
| 173 def ThreadCategoryName(thread_name): | 187 def ThreadCategoryName(thread_name): |
| 174 thread_category = "other" | 188 thread_category = "other" |
| 175 for substring, category in TimelineThreadCategories.iteritems(): | 189 for substring, category in TimelineThreadCategories.iteritems(): |
| 176 if substring in MatchBySubString and substring in thread_name: | 190 if substring in MatchBySubString and substring in thread_name: |
| 177 thread_category = category | 191 thread_category = category |
| 178 if thread_name in TimelineThreadCategories: | 192 if thread_name in TimelineThreadCategories: |
| 179 thread_category = TimelineThreadCategories[thread_name] | 193 thread_category = TimelineThreadCategories[thread_name] |
| 180 return thread_category | 194 return thread_category |
| 181 | 195 |
| 182 def ThreadTimeResultName(thread_category): | 196 def ThreadTimeResultName(thread_category): |
| 183 return "thread_" + thread_category + "_clock_time_per_frame" | 197 return "thread_" + thread_category + "_clock_time_per_frame" |
| 184 | 198 |
| 185 def ThreadCpuTimeResultName(thread_category): | 199 def ThreadCpuTimeResultName(thread_category): |
| 186 return "thread_" + thread_category + "_cpu_time_per_frame" | 200 return "thread_" + thread_category + "_cpu_time_per_frame" |
| 187 | 201 |
| 188 def ThreadDetailResultName(thread_category, detail): | 202 def ThreadDetailResultName(thread_category, detail): |
| 189 return "thread_" + thread_category + "|" + detail | 203 return "thread_" + thread_category + "|" + detail |
| 190 | 204 |
| 191 class ResultsForThread(object): | 205 class ResultsForThread(object): |
| 192 def __init__(self, model, action_ranges, name): | 206 def __init__(self, model, action_ranges, name): |
| 193 self.model = model | 207 self.model = model |
| 194 self.toplevel_slices = [] | 208 self.toplevel_slices = [] |
| 195 self.all_slices = [] | 209 self.all_slices = [] |
| 196 self.name = name | 210 self.name = name |
| 197 self.action_ranges = action_ranges | 211 self.action_ranges = action_ranges |
| 198 | 212 |
| 199 @property | 213 @property |
| 200 def clock_time(self): | 214 def clock_time(self): |
| 201 return sum([x.duration for x in self.toplevel_slices]) | 215 clock_duration = sum([x.duration for x in self.toplevel_slices]) |
| 216 clock_overhead = sum([ClockOverhead(x) for x in self.all_slices]) | |
| 217 return clock_duration - clock_overhead | |
| 202 | 218 |
| 203 @property | 219 @property |
| 204 def cpu_time(self): | 220 def cpu_time(self): |
| 205 res = 0 | 221 cpu_duration = 0 |
| 222 cpu_overhead = sum([CpuOverhead(x) for x in self.all_slices]) | |
| 206 for x in self.toplevel_slices: | 223 for x in self.toplevel_slices: |
| 207 # Only report thread-duration if we have it for all events. | 224 # Only report thread-duration if we have it for all events. |
| 208 # | 225 # |
| 209 # A thread_duration of 0 is valid, so this only returns 0 if it is None. | 226 # A thread_duration of 0 is valid, so this only returns 0 if it is None. |
| 210 if x.thread_duration == None: | 227 if x.thread_duration == None: |
| 211 if not x.duration: | 228 if not x.duration: |
| 212 continue | 229 continue |
| 213 else: | 230 else: |
| 214 return 0 | 231 return 0 |
| 215 else: | 232 else: |
| 216 res += x.thread_duration | 233 cpu_duration += x.thread_duration |
| 217 return res | 234 return cpu_duration - cpu_overhead |
| 218 | 235 |
| 219 def ActionSlices(self, slices): | 236 def ActionSlices(self, slices): |
| 220 slices_in_actions = [] | 237 slices_in_actions = [] |
| 221 for event in slices: | 238 for event in slices: |
| 222 for action_range in self.action_ranges: | 239 for action_range in self.action_ranges: |
| 223 if action_range.Contains(bounds.Bounds.CreateFromEvent(event)): | 240 if action_range.Contains(bounds.Bounds.CreateFromEvent(event)): |
| 224 slices_in_actions.append(event) | 241 slices_in_actions.append(event) |
| 225 break | 242 break |
| 226 return slices_in_actions | 243 return slices_in_actions |
| 227 | 244 |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 286 | 303 |
| 287 # Group all threads. | 304 # Group all threads. |
| 288 for thread in self._model.GetAllThreads(): | 305 for thread in self._model.GetAllThreads(): |
| 289 thread_category_results['total_all'].AppendThreadSlices(thread) | 306 thread_category_results['total_all'].AppendThreadSlices(thread) |
| 290 | 307 |
| 291 # Also group fast-path threads. | 308 # Also group fast-path threads. |
| 292 for thread in self._model.GetAllThreads(): | 309 for thread in self._model.GetAllThreads(): |
| 293 if ThreadCategoryName(thread.name) in FastPathThreads: | 310 if ThreadCategoryName(thread.name) in FastPathThreads: |
| 294 thread_category_results['total_fast_path'].AppendThreadSlices(thread) | 311 thread_category_results['total_fast_path'].AppendThreadSlices(thread) |
| 295 | 312 |
| 296 # Calculate the number of frames from the CC thread. | 313 # Calculate the number of frames. |
| 297 cc_slices = thread_category_results['renderer_compositor'].all_slices | 314 frame_slices = thread_category_results[FrameTraceThread].all_slices |
| 298 num_frames = self.CountSlices(cc_slices, CompositorFrameTraceName) | 315 num_frames = self.CountSlices(frame_slices, FrameTraceName) |
| 299 | 316 |
| 300 # Report the desired results and details. | 317 # Report the desired results and details. |
| 301 for thread_results in thread_category_results.values(): | 318 for thread_results in thread_category_results.values(): |
| 302 if thread_results.name in self.results_to_report: | 319 if thread_results.name in self.results_to_report: |
| 303 thread_results.AddResults(num_frames, results) | 320 thread_results.AddResults(num_frames, results) |
| 304 # TOOD(nduca): When generic results objects are done, this special case | 321 # TOOD(nduca): When generic results objects are done, this special case |
| 305 # can be replaced with a generic UI feature. | 322 # can be replaced with a generic UI feature. |
| 306 if thread_results.name in self.details_to_report: | 323 if thread_results.name in self.details_to_report: |
| 307 thread_results.AddDetailedResults(num_frames, results) | 324 thread_results.AddDetailedResults(num_frames, results) |
| OLD | NEW |