OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """PyAuto: Python Interface to Chromium's Automation Proxy. | 6 """PyAuto: Python Interface to Chromium's Automation Proxy. |
7 | 7 |
8 PyAuto uses swig to expose Automation Proxy interfaces to Python. | 8 PyAuto uses swig to expose Automation Proxy interfaces to Python. |
9 For complete documentation on the functionality available, | 9 For complete documentation on the functionality available, |
10 run pydoc on this file. | 10 run pydoc on this file. |
(...skipping 4909 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4920 A user needs to be logged-in as a precondition. Note that the UI is not | 4920 A user needs to be logged-in as a precondition. Note that the UI is not |
4921 destroyed afterwards, a browser restart is necessary if you want | 4921 destroyed afterwards, a browser restart is necessary if you want |
4922 to interact with the browser after this call in the same test case. | 4922 to interact with the browser after this call in the same test case. |
4923 | 4923 |
4924 Raises: | 4924 Raises: |
4925 pyauto_errors.JSONInterfaceError if the automation call returns an error. | 4925 pyauto_errors.JSONInterfaceError if the automation call returns an error. |
4926 """ | 4926 """ |
4927 cmd_dict = { 'command': 'CaptureProfilePhoto' } | 4927 cmd_dict = { 'command': 'CaptureProfilePhoto' } |
4928 return self._GetResultFromJSONRequest(cmd_dict) | 4928 return self._GetResultFromJSONRequest(cmd_dict) |
4929 | 4929 |
| 4930 def GetMemoryStatsChromeOS(self, duration): |
| 4931 """Identifies and returns different kinds of current memory usage stats. |
| 4932 |
| 4933 This function samples values each second for |duration| seconds, then |
| 4934 outputs the min, max, and ending values for each measurement type. |
| 4935 |
| 4936 Args: |
| 4937 duration: The number of seconds to sample data before outputting the |
| 4938 minimum, maximum, and ending values for each measurement type. |
| 4939 |
| 4940 Returns: |
| 4941 A dictionary containing memory usage information. Each measurement type |
| 4942 is associated with the min, max, and ending values from among all |
| 4943 sampled values. Values are specified in KB. |
| 4944 { |
| 4945 'gem_obj': { # GPU memory usage. |
| 4946 'min': ..., |
| 4947 'max': ..., |
| 4948 'end': ..., |
| 4949 }, |
| 4950 'gtt': { ... }, # GPU memory usage (graphics translation table). |
| 4951 'mem_free': { ... }, # CPU free memory. |
| 4952 'mem_available': { ... }, # CPU available memory. |
| 4953 'mem_shared': { ... }, # CPU shared memory. |
| 4954 'mem_cached': { ... }, # CPU cached memory. |
| 4955 'mem_anon': { ... }, # CPU anon memory (active + inactive). |
| 4956 'mem_file': { ... }, # CPU file memory (active + inactive). |
| 4957 'mem_slab': { ... }, # CPU slab memory. |
| 4958 'browser_priv': { ... }, # Chrome browser private memory. |
| 4959 'browser_shared': { ... }, # Chrome browser shared memory. |
| 4960 'gpu_priv': { ... }, # Chrome GPU private memory. |
| 4961 'gpu_shared': { ... }, # Chrome GPU shared memory. |
| 4962 'renderer_priv': { ... }, # Total private memory of all renderers. |
| 4963 'renderer_shared': { ... }, # Total shared memory of all renderers. |
| 4964 } |
| 4965 """ |
| 4966 logging.debug('Sampling memory information for %d seconds...' % duration) |
| 4967 stats = {} |
| 4968 |
| 4969 for _ in xrange(duration): |
| 4970 # GPU memory. |
| 4971 gem_obj_path = '/sys/kernel/debug/dri/0/i915_gem_objects' |
| 4972 if os.path.exists(gem_obj_path): |
| 4973 p = subprocess.Popen('grep bytes %s' % gem_obj_path, |
| 4974 stdout=subprocess.PIPE, shell=True) |
| 4975 stdout = p.communicate()[0] |
| 4976 |
| 4977 gem_obj = re.search( |
| 4978 '\d+ objects, (\d+) bytes\n', stdout).group(1) |
| 4979 if 'gem_obj' not in stats: |
| 4980 stats['gem_obj'] = [] |
| 4981 stats['gem_obj'].append(int(gem_obj) / 1024.0) |
| 4982 |
| 4983 gtt_path = '/sys/kernel/debug/dri/0/i915_gem_gtt' |
| 4984 if os.path.exists(gtt_path): |
| 4985 p = subprocess.Popen('grep bytes %s' % gtt_path, |
| 4986 stdout=subprocess.PIPE, shell=True) |
| 4987 stdout = p.communicate()[0] |
| 4988 |
| 4989 gtt = re.search( |
| 4990 'Total [\d]+ objects, ([\d]+) bytes', stdout).group(1) |
| 4991 if 'gtt' not in stats: |
| 4992 stats['gtt'] = [] |
| 4993 stats['gtt'].append(int(gtt) / 1024.0) |
| 4994 |
| 4995 # CPU memory. |
| 4996 stdout = '' |
| 4997 with open('/proc/meminfo') as f: |
| 4998 stdout = f.read() |
| 4999 mem_free = re.search('MemFree:\s*([\d]+) kB', stdout).group(1) |
| 5000 |
| 5001 if 'mem_free' not in stats: |
| 5002 stats['mem_free'] = [] |
| 5003 stats['mem_free'].append(int(mem_free)) |
| 5004 |
| 5005 mem_dirty = re.search('Dirty:\s*([\d]+) kB', stdout).group(1) |
| 5006 mem_active_file = re.search( |
| 5007 'Active\(file\):\s*([\d]+) kB', stdout).group(1) |
| 5008 mem_inactive_file = re.search( |
| 5009 'Inactive\(file\):\s*([\d]+) kB', stdout).group(1) |
| 5010 |
| 5011 with open('/proc/sys/vm/min_filelist_kbytes') as f: |
| 5012 mem_min_file = f.read() |
| 5013 |
| 5014 # Available memory = |
| 5015 # MemFree + ActiveFile + InactiveFile - DirtyMem - MinFileMem |
| 5016 if 'mem_available' not in stats: |
| 5017 stats['mem_available'] = [] |
| 5018 stats['mem_available'].append( |
| 5019 int(mem_free) + int(mem_active_file) + int(mem_inactive_file) - |
| 5020 int(mem_dirty) - int(mem_min_file)) |
| 5021 |
| 5022 mem_shared = re.search('Shmem:\s*([\d]+) kB', stdout).group(1) |
| 5023 if 'mem_shared' not in stats: |
| 5024 stats['mem_shared'] = [] |
| 5025 stats['mem_shared'].append(int(mem_shared)) |
| 5026 |
| 5027 mem_cached = re.search('Cached:\s*([\d]+) kB', stdout).group(1) |
| 5028 if 'mem_cached' not in stats: |
| 5029 stats['mem_cached'] = [] |
| 5030 stats['mem_cached'].append(int(mem_cached)) |
| 5031 |
| 5032 mem_anon_active = re.search('Active\(anon\):\s*([\d]+) kB', |
| 5033 stdout).group(1) |
| 5034 mem_anon_inactive = re.search('Inactive\(anon\):\s*([\d]+) kB', |
| 5035 stdout).group(1) |
| 5036 if 'mem_anon' not in stats: |
| 5037 stats['mem_anon'] = [] |
| 5038 stats['mem_anon'].append(int(mem_anon_active) + int(mem_anon_inactive)) |
| 5039 |
| 5040 mem_file_active = re.search('Active\(file\):\s*([\d]+) kB', |
| 5041 stdout).group(1) |
| 5042 mem_file_inactive = re.search('Inactive\(file\):\s*([\d]+) kB', |
| 5043 stdout).group(1) |
| 5044 if 'mem_file' not in stats: |
| 5045 stats['mem_file'] = [] |
| 5046 stats['mem_file'].append(int(mem_file_active) + int(mem_file_inactive)) |
| 5047 |
| 5048 mem_slab = re.search('Slab:\s*([\d]+) kB', stdout).group(1) |
| 5049 if 'mem_slab' not in stats: |
| 5050 stats['mem_slab'] = [] |
| 5051 stats['mem_slab'].append(int(mem_slab)) |
| 5052 |
| 5053 # Chrome process memory. |
| 5054 pinfo = self.GetProcessInfo()['browsers'][0]['processes'] |
| 5055 total_renderer_priv = 0 |
| 5056 total_renderer_shared = 0 |
| 5057 for process in pinfo: |
| 5058 mem_priv = process['working_set_mem']['priv'] |
| 5059 mem_shared = process['working_set_mem']['shared'] |
| 5060 if process['child_process_type'] == 'Browser': |
| 5061 if 'browser_priv' not in stats: |
| 5062 stats['browser_priv'] = [] |
| 5063 stats['browser_priv'].append(int(mem_priv)) |
| 5064 if 'browser_shared' not in stats: |
| 5065 stats['browser_shared'] = [] |
| 5066 stats['browser_shared'].append(int(mem_shared)) |
| 5067 elif process['child_process_type'] == 'GPU': |
| 5068 if 'gpu_priv' not in stats: |
| 5069 stats['gpu_priv'] = [] |
| 5070 stats['gpu_priv'].append(int(mem_priv)) |
| 5071 if 'gpu_shared' not in stats: |
| 5072 stats['gpu_shared'] = [] |
| 5073 stats['gpu_shared'].append(int(mem_shared)) |
| 5074 elif process['child_process_type'] == 'Tab': |
| 5075 # Sum the memory of all renderer processes. |
| 5076 total_renderer_priv += int(mem_priv) |
| 5077 total_renderer_shared += int(mem_shared) |
| 5078 if 'renderer_priv' not in stats: |
| 5079 stats['renderer_priv'] = [] |
| 5080 stats['renderer_priv'].append(int(total_renderer_priv)) |
| 5081 if 'renderer_shared' not in stats: |
| 5082 stats['renderer_shared'] = [] |
| 5083 stats['renderer_shared'].append(int(total_renderer_shared)) |
| 5084 |
| 5085 time.sleep(1) |
| 5086 |
| 5087 # Compute min, max, and ending values to return. |
| 5088 result = {} |
| 5089 for measurement_type in stats: |
| 5090 values = stats[measurement_type] |
| 5091 result[measurement_type] = { |
| 5092 'min': min(values), |
| 5093 'max': max(values), |
| 5094 'end': values[-1], |
| 5095 } |
| 5096 |
| 5097 return result |
| 5098 |
4930 ## ChromeOS section -- end | 5099 ## ChromeOS section -- end |
4931 | 5100 |
4932 | 5101 |
4933 class ExtraBrowser(PyUITest): | 5102 class ExtraBrowser(PyUITest): |
4934 """Launches a new browser with some extra flags. | 5103 """Launches a new browser with some extra flags. |
4935 | 5104 |
4936 The new browser is launched with its own fresh profile. | 5105 The new browser is launched with its own fresh profile. |
4937 This class does not apply to ChromeOS. | 5106 This class does not apply to ChromeOS. |
4938 """ | 5107 """ |
4939 def __init__(self, chrome_flags=[], methodName='runTest', **kwargs): | 5108 def __init__(self, chrome_flags=[], methodName='runTest', **kwargs): |
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5496 successful = result.wasSuccessful() | 5665 successful = result.wasSuccessful() |
5497 if not successful: | 5666 if not successful: |
5498 pyauto_tests_file = os.path.join(self.TestsDir(), self._tests_filename) | 5667 pyauto_tests_file = os.path.join(self.TestsDir(), self._tests_filename) |
5499 print >>sys.stderr, 'Tests can be disabled by editing %s. ' \ | 5668 print >>sys.stderr, 'Tests can be disabled by editing %s. ' \ |
5500 'Ref: %s' % (pyauto_tests_file, _PYAUTO_DOC_URL) | 5669 'Ref: %s' % (pyauto_tests_file, _PYAUTO_DOC_URL) |
5501 sys.exit(not successful) | 5670 sys.exit(not successful) |
5502 | 5671 |
5503 | 5672 |
5504 if __name__ == '__main__': | 5673 if __name__ == '__main__': |
5505 Main() | 5674 Main() |
OLD | NEW |