OLD | NEW |
---|---|
1 # Copyright 2012 The Chromium Authors. All rights reserved. | 1 # Copyright 2012 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 | 4 |
5 import os | 5 import os |
6 | 6 |
7 from telemetry import decorators | 7 from telemetry import decorators |
8 from telemetry.core import browser_credentials | 8 from telemetry.core import browser_credentials |
9 from telemetry.core import exceptions | 9 from telemetry.core import exceptions |
10 from telemetry.core import extension_dict | 10 from telemetry.core import extension_dict |
11 from telemetry.core import local_server | 11 from telemetry.core import local_server |
12 from telemetry.core import memory_cache_http_server | 12 from telemetry.core import memory_cache_http_server |
13 from telemetry.core import platform | 13 from telemetry.core import platform as platform_module |
14 from telemetry.core import tab_list | 14 from telemetry.core import tab_list |
15 from telemetry.core import wpr_modes | 15 from telemetry.core import wpr_modes |
16 from telemetry.core import wpr_server | 16 from telemetry.core import wpr_server |
17 from telemetry.core.backends import browser_backend | 17 from telemetry.core.backends import browser_backend |
18 from telemetry.core.platform.profiler import profiler_finder | 18 from telemetry.core.platform.profiler import profiler_finder |
19 | 19 |
20 | 20 |
21 class Browser(object): | 21 class Browser(object): |
22 """A running browser instance that can be controlled in a limited way. | 22 """A running browser instance that can be controlled in a limited way. |
23 | 23 |
24 To create a browser instance, use browser_finder.FindBrowser. | 24 To create a browser instance, use browser_finder.FindBrowser. |
25 | 25 |
26 Be sure to clean up after yourself by calling Close() when you are done with | 26 Be sure to clean up after yourself by calling Close() when you are done with |
27 the browser. Or better yet: | 27 the browser. Or better yet: |
28 browser_to_create = FindBrowser(options) | 28 browser_to_create = FindBrowser(options) |
29 with browser_to_create.Create() as browser: | 29 with browser_to_create.Create() as browser: |
30 ... do all your operations on browser here | 30 ... do all your operations on browser here |
31 """ | 31 """ |
32 def __init__(self, backend, platform_backend): | 32 def __init__(self, backend, platform): |
33 assert isinstance(platform, platform_module.Platform) | |
33 self._browser_backend = backend | 34 self._browser_backend = backend |
34 self._http_server = None | 35 self._http_server = None |
35 self._wpr_server = None | 36 self._wpr_server = None |
36 self._platform_backend = platform_backend | 37 self._platform = platform |
37 self._platform = platform.Platform(platform_backend) | |
38 self._active_profilers = [] | 38 self._active_profilers = [] |
39 self._profilers_states = {} | 39 self._profilers_states = {} |
40 self._local_server_controller = local_server.LocalServerController(backend) | 40 self._local_server_controller = local_server.LocalServerController(backend) |
41 self._tabs = tab_list.TabList(backend.tab_list_backend) | 41 self._tabs = tab_list.TabList(backend.tab_list_backend) |
42 self.credentials = browser_credentials.BrowserCredentials() | 42 self.credentials = browser_credentials.BrowserCredentials() |
43 self._platform.SetFullPerformanceModeEnabled(True) | 43 self._platform.SetFullPerformanceModeEnabled(True) |
44 | 44 |
45 def __enter__(self): | 45 def __enter__(self): |
46 self.Start() | 46 self.Start() |
47 return self | 47 return self |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
94 return extension_dict.ExtensionDict(self._browser_backend.extension_backend) | 94 return extension_dict.ExtensionDict(self._browser_backend.extension_backend) |
95 | 95 |
96 @property | 96 @property |
97 def supports_tracing(self): | 97 def supports_tracing(self): |
98 return self._browser_backend.supports_tracing | 98 return self._browser_backend.supports_tracing |
99 | 99 |
100 def is_profiler_active(self, profiler_name): | 100 def is_profiler_active(self, profiler_name): |
101 return profiler_name in [profiler.name() for | 101 return profiler_name in [profiler.name() for |
102 profiler in self._active_profilers] | 102 profiler in self._active_profilers] |
103 | 103 |
104 | |
104 def _GetStatsCommon(self, pid_stats_function): | 105 def _GetStatsCommon(self, pid_stats_function): |
105 browser_pid = self._browser_backend.pid | 106 browser_pid = self._browser_backend.pid |
106 result = { | 107 result = { |
107 'Browser': dict(pid_stats_function(browser_pid), **{'ProcessCount': 1}), | 108 'Browser': dict(pid_stats_function(browser_pid), **{'ProcessCount': 1}), |
108 'Renderer': {'ProcessCount': 0}, | 109 'Renderer': {'ProcessCount': 0}, |
109 'Gpu': {'ProcessCount': 0}, | 110 'Gpu': {'ProcessCount': 0}, |
110 'Other': {'ProcessCount': 0} | 111 'Other': {'ProcessCount': 0} |
111 } | 112 } |
112 process_count = 1 | 113 process_count = 1 |
113 for child_pid in self._platform_backend.GetChildPids(browser_pid): | 114 for child_pid in self._platform.GetChildPids(browser_pid): |
114 try: | 115 try: |
115 child_cmd_line = self._platform_backend.GetCommandLine(child_pid) | 116 child_cmd_line = self._platform.GetCommandLine(child_pid) |
116 child_stats = pid_stats_function(child_pid) | 117 child_stats = pid_stats_function(child_pid) |
117 except exceptions.ProcessGoneException: | 118 except exceptions.ProcessGoneException: |
118 # It is perfectly fine for a process to have gone away between calling | 119 # It is perfectly fine for a process to have gone away between calling |
119 # GetChildPids() and then further examining it. | 120 # GetChildPids() and then further examining it. |
120 continue | 121 continue |
121 child_process_name = self._browser_backend.GetProcessName(child_cmd_line) | 122 child_process_name = self._browser_backend.GetProcessName(child_cmd_line) |
122 process_name_type_key_map = {'gpu-process': 'Gpu', 'renderer': 'Renderer'} | 123 process_name_type_key_map = {'gpu-process': 'Gpu', 'renderer': 'Renderer'} |
123 if child_process_name in process_name_type_key_map: | 124 if child_process_name in process_name_type_key_map: |
124 child_process_type_key = process_name_type_key_map[child_process_name] | 125 child_process_type_key = process_name_type_key_map[child_process_name] |
125 else: | 126 else: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 'WorkingSetSizePeak': U, | 169 'WorkingSetSizePeak': U, |
169 'ProportionalSetSize': V, | 170 'ProportionalSetSize': V, |
170 'PrivateDirty': W | 171 'PrivateDirty': W |
171 }, | 172 }, |
172 'SystemCommitCharge': X, | 173 'SystemCommitCharge': X, |
173 'SystemTotalPhysicalMemory': Y, | 174 'SystemTotalPhysicalMemory': Y, |
174 'ProcessCount': Z, | 175 'ProcessCount': Z, |
175 } | 176 } |
176 Any of the above keys may be missing on a per-platform basis. | 177 Any of the above keys may be missing on a per-platform basis. |
177 """ | 178 """ |
178 self._platform_backend.PurgeUnpinnedMemory() | 179 self._platform.WillGetMemoryStats() |
179 result = self._GetStatsCommon(self._platform_backend.GetMemoryStats) | 180 result = self._GetStatsCommon(self._platform.GetMemoryStats) |
180 result['SystemCommitCharge'] = \ | 181 result['SystemCommitCharge'] = \ |
181 self._platform_backend.GetSystemCommitCharge() | 182 self._platform.GetSystemCommitCharge() |
182 result['SystemTotalPhysicalMemory'] = \ | 183 result['SystemTotalPhysicalMemory'] = \ |
183 self._platform_backend.GetSystemTotalPhysicalMemory() | 184 self._platform.GetSystemTotalPhysicalMemory() |
184 return result | 185 return result |
185 | 186 |
187 | |
186 @property | 188 @property |
187 def cpu_stats(self): | 189 def cpu_stats(self): |
tonyg
2014/08/02 15:58:18
I think the root of the problem here is that these
| |
188 """Returns a dict of cpu statistics for the system. | 190 """Returns a dict of cpu statistics for the system. |
189 { 'Browser': { | 191 { 'Browser': { |
190 'CpuProcessTime': S, | 192 'CpuProcessTime': S, |
191 'TotalTime': T | 193 'TotalTime': T |
192 }, | 194 }, |
193 'Gpu': { | 195 'Gpu': { |
194 'CpuProcessTime': S, | 196 'CpuProcessTime': S, |
195 'TotalTime': T | 197 'TotalTime': T |
196 }, | 198 }, |
197 'Renderer': { | 199 'Renderer': { |
198 'CpuProcessTime': S, | 200 'CpuProcessTime': S, |
199 'TotalTime': T | 201 'TotalTime': T |
200 } | 202 } |
201 } | 203 } |
202 Any of the above keys may be missing on a per-platform basis. | 204 Any of the above keys may be missing on a per-platform basis. |
203 """ | 205 """ |
204 result = self._GetStatsCommon(self._platform_backend.GetCpuStats) | 206 result = self._GetStatsCommon(self._platform.GetCpuStats) |
205 del result['ProcessCount'] | 207 del result['ProcessCount'] |
206 | 208 |
207 # We want a single time value, not the sum for all processes. | 209 # We want a single time value, not the sum for all processes. |
208 cpu_timestamp = self._platform_backend.GetCpuTimestamp() | 210 cpu_timestamp = self._platform.GetCpuTimestamp() |
209 for process_type in result: | 211 for process_type in result: |
210 # Skip any process_types that are empty | 212 # Skip any process_types that are empty |
211 if not len(result[process_type]): | 213 if not len(result[process_type]): |
212 continue | 214 continue |
213 result[process_type].update(cpu_timestamp) | 215 result[process_type].update(cpu_timestamp) |
214 return result | 216 return result |
215 | 217 |
216 @property | 218 @property |
217 def io_stats(self): | 219 def io_stats(self): |
218 """Returns a dict of IO statistics for the browser: | 220 """Returns a dict of IO statistics for the browser: |
(...skipping 10 matching lines...) Expand all Loading... | |
229 'WriteTransferCount': Z | 231 'WriteTransferCount': Z |
230 }, | 232 }, |
231 'Renderer': { | 233 'Renderer': { |
232 'ReadOperationCount': W, | 234 'ReadOperationCount': W, |
233 'WriteOperationCount': X, | 235 'WriteOperationCount': X, |
234 'ReadTransferCount': Y, | 236 'ReadTransferCount': Y, |
235 'WriteTransferCount': Z | 237 'WriteTransferCount': Z |
236 } | 238 } |
237 } | 239 } |
238 """ | 240 """ |
239 result = self._GetStatsCommon(self._platform_backend.GetIOStats) | 241 result = self._GetStatsCommon(self._platform.GetIOStats) |
240 del result['ProcessCount'] | 242 del result['ProcessCount'] |
241 return result | 243 return result |
242 | 244 |
243 def StartProfiling(self, profiler_name, base_output_file): | 245 def StartProfiling(self, profiler_name, base_output_file): |
244 """Starts profiling using |profiler_name|. Results are saved to | 246 """Starts profiling using |profiler_name|. Results are saved to |
245 |base_output_file|.<process_name>.""" | 247 |base_output_file|.<process_name>.""" |
246 assert not self._active_profilers, 'Already profiling. Must stop first.' | 248 assert not self._active_profilers, 'Already profiling. Must stop first.' |
247 | 249 |
248 profiler_class = profiler_finder.FindProfiler(profiler_name) | 250 profiler_class = profiler_finder.FindProfiler(profiler_name) |
249 | 251 |
250 if not profiler_class.is_supported(self._browser_backend.browser_type): | 252 if not profiler_class.is_supported(self._browser_backend.browser_type): |
251 raise Exception('The %s profiler is not ' | 253 raise Exception('The %s profiler is not ' |
252 'supported on this platform.' % profiler_name) | 254 'supported on this platform.' % profiler_name) |
253 | 255 |
254 if not profiler_class in self._profilers_states: | 256 if not profiler_class in self._profilers_states: |
255 self._profilers_states[profiler_class] = {} | 257 self._profilers_states[profiler_class] = {} |
256 | 258 |
257 self._active_profilers.append( | 259 profiler = self.platform.InstantiateProfiler( |
258 profiler_class(self._browser_backend, self._platform_backend, | 260 profiler_class, |
259 base_output_file, self._profilers_states[profiler_class])) | 261 self._browser_backend, |
262 base_output_file, | |
263 self._profilers_states[profiler_class]) | |
264 self._active_profilers.append(profiler) | |
260 | 265 |
261 def StopProfiling(self): | 266 def StopProfiling(self): |
262 """Stops all active profilers and saves their results. | 267 """Stops all active profilers and saves their results. |
263 | 268 |
264 Returns: | 269 Returns: |
265 A list of filenames produced by the profiler. | 270 A list of filenames produced by the profiler. |
266 """ | 271 """ |
267 output_files = [] | 272 output_files = [] |
268 for profiler in self._active_profilers: | 273 for profiler in self._active_profilers: |
269 output_files.extend(profiler.CollectProfile()) | 274 output_files.extend(profiler.CollectProfile()) |
(...skipping 21 matching lines...) Expand all Loading... | |
291 self.platform.FlushSystemCacheForDirectory( | 296 self.platform.FlushSystemCacheForDirectory( |
292 self._browser_backend.browser_directory) | 297 self._browser_backend.browser_directory) |
293 else: | 298 else: |
294 self.platform.FlushEntireSystemCache() | 299 self.platform.FlushEntireSystemCache() |
295 | 300 |
296 self._browser_backend.SetBrowser(self) | 301 self._browser_backend.SetBrowser(self) |
297 self._browser_backend.Start() | 302 self._browser_backend.Start() |
298 | 303 |
299 def Close(self): | 304 def Close(self): |
300 """Closes this browser.""" | 305 """Closes this browser.""" |
301 for profiler_class in self._profilers_states: | 306 profiler_classes = list(self._profilers_states.keys()) |
302 profiler_class.WillCloseBrowser(self._browser_backend, | 307 self._platform.WillCloseBrowser(self._browser_backend, |
303 self._platform_backend) | 308 profiler_classes) |
304 | 309 |
305 self.platform.SetFullPerformanceModeEnabled(False) | 310 self.platform.SetFullPerformanceModeEnabled(False) |
306 | 311 |
307 if self._wpr_server: | 312 if self._wpr_server: |
308 self._wpr_server.Close() | 313 self._wpr_server.Close() |
309 self._wpr_server = None | 314 self._wpr_server = None |
310 | 315 |
311 if self._http_server: | 316 if self._http_server: |
312 self._http_server.Close() | 317 self._http_server.Close() |
313 self._http_server = None | 318 self._http_server = None |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
393 | 398 |
394 @property | 399 @property |
395 def supports_system_info(self): | 400 def supports_system_info(self): |
396 return self._browser_backend.supports_system_info | 401 return self._browser_backend.supports_system_info |
397 | 402 |
398 def GetSystemInfo(self): | 403 def GetSystemInfo(self): |
399 """Returns low-level information about the system, if available. | 404 """Returns low-level information about the system, if available. |
400 | 405 |
401 See the documentation of the SystemInfo class for more details.""" | 406 See the documentation of the SystemInfo class for more details.""" |
402 return self._browser_backend.GetSystemInfo() | 407 return self._browser_backend.GetSystemInfo() |
OLD | NEW |