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 """Basic pyauto performance tests. | 6 """Basic pyauto performance tests. |
7 | 7 |
8 For tests that need to be run for multiple iterations (e.g., so that average | 8 For tests that need to be run for multiple iterations (e.g., so that average |
9 and standard deviation values can be reported), the default number of iterations | 9 and standard deviation values can be reported), the default number of iterations |
10 run for each of these tests is specified by |_DEFAULT_NUM_ITERATIONS|. | 10 run for each of these tests is specified by |_DEFAULT_NUM_ITERATIONS|. |
(...skipping 1759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1770 | 1770 |
1771 def ExtraChromeFlags(self): | 1771 def ExtraChromeFlags(self): |
1772 """Launches Chrome with custom flags. | 1772 """Launches Chrome with custom flags. |
1773 | 1773 |
1774 Returns: | 1774 Returns: |
1775 A list of extra flags to pass to Chrome when it is launched. | 1775 A list of extra flags to pass to Chrome when it is launched. |
1776 """ | 1776 """ |
1777 # Ensure Chrome assigns one renderer process to each tab. | 1777 # Ensure Chrome assigns one renderer process to each tab. |
1778 return super(MemoryTest, self).ExtraChromeFlags() + ['--process-per-tab'] | 1778 return super(MemoryTest, self).ExtraChromeFlags() + ['--process-per-tab'] |
1779 | 1779 |
1780 def _GetMemoryStats(self, duration): | |
1781 """Identifies and returns different kinds of current memory usage stats. | |
1782 | |
1783 This function samples values each second for |duration| seconds, then | |
1784 outputs the min, max, and ending values for each measurement type. | |
1785 | |
1786 Args: | |
1787 duration: The number of seconds to sample data before outputting the | |
1788 minimum, maximum, and ending values for each measurement type. | |
1789 | |
1790 Returns: | |
1791 A dictionary containing memory usage information. Each measurement type | |
1792 is associated with the min, max, and ending values from among all | |
1793 sampled values. Values are specified in KB. | |
1794 { | |
1795 'gem_obj': { # GPU memory usage. | |
1796 'min': ..., | |
1797 'max': ..., | |
1798 'end': ..., | |
1799 }, | |
1800 'gtt': { ... }, # GPU memory usage (graphics translation table). | |
1801 'mem_free': { ... }, # CPU free memory. | |
1802 'mem_available': { ... }, # CPU available memory. | |
1803 'mem_shared': { ... }, # CPU shared memory. | |
1804 'mem_cached': { ... }, # CPU cached memory. | |
1805 'mem_anon': { ... }, # CPU anon memory (active + inactive). | |
1806 'mem_file': { ... }, # CPU file memory (active + inactive). | |
1807 'mem_slab': { ... }, # CPU slab memory. | |
1808 'browser_priv': { ... }, # Chrome browser private memory. | |
1809 'browser_shared': { ... }, # Chrome browser shared memory. | |
1810 'gpu_priv': { ... }, # Chrome GPU private memory. | |
1811 'gpu_shared': { ... }, # Chrome GPU shared memory. | |
1812 'renderer_priv': { ... }, # Total private memory of all renderers. | |
1813 'renderer_shared': { ... }, # Total shared memory of all renderers. | |
1814 } | |
1815 """ | |
1816 logging.debug('Sampling memory information for %d seconds...' % duration) | |
1817 stats = {} | |
1818 | |
1819 for _ in xrange(duration): | |
1820 # GPU memory. | |
1821 gem_obj_path = '/sys/kernel/debug/dri/0/i915_gem_objects' | |
1822 if os.path.exists(gem_obj_path): | |
1823 p = subprocess.Popen('grep bytes %s' % gem_obj_path, | |
1824 stdout=subprocess.PIPE, shell=True) | |
1825 stdout = p.communicate()[0] | |
1826 | |
1827 gem_obj = re.search( | |
1828 '\d+ objects, (\d+) bytes\n', stdout).group(1) | |
1829 if 'gem_obj' not in stats: | |
1830 stats['gem_obj'] = [] | |
1831 stats['gem_obj'].append(int(gem_obj) / 1024.0) | |
1832 | |
1833 gtt_path = '/sys/kernel/debug/dri/0/i915_gem_gtt' | |
1834 if os.path.exists(gtt_path): | |
1835 p = subprocess.Popen('grep bytes %s' % gtt_path, | |
1836 stdout=subprocess.PIPE, shell=True) | |
1837 stdout = p.communicate()[0] | |
1838 | |
1839 gtt = re.search( | |
1840 'Total [\d]+ objects, ([\d]+) bytes', stdout).group(1) | |
1841 if 'gtt' not in stats: | |
1842 stats['gtt'] = [] | |
1843 stats['gtt'].append(int(gtt) / 1024.0) | |
1844 | |
1845 # CPU memory. | |
1846 stdout = '' | |
1847 with open('/proc/meminfo') as f: | |
1848 stdout = f.read() | |
1849 mem_free = re.search('MemFree:\s*([\d]+) kB', stdout).group(1) | |
1850 | |
1851 if 'mem_free' not in stats: | |
1852 stats['mem_free'] = [] | |
1853 stats['mem_free'].append(int(mem_free)) | |
1854 | |
1855 mem_dirty = re.search('Dirty:\s*([\d]+) kB', stdout).group(1) | |
1856 mem_active_file = re.search( | |
1857 'Active\(file\):\s*([\d]+) kB', stdout).group(1) | |
1858 mem_inactive_file = re.search( | |
1859 'Inactive\(file\):\s*([\d]+) kB', stdout).group(1) | |
1860 | |
1861 with open('/proc/sys/vm/min_filelist_kbytes') as f: | |
1862 mem_min_file = f.read() | |
1863 | |
1864 # Available memory = | |
1865 # MemFree + ActiveFile + InactiveFile - DirtyMem - MinFileMem | |
1866 if 'mem_available' not in stats: | |
1867 stats['mem_available'] = [] | |
1868 stats['mem_available'].append( | |
1869 int(mem_free) + int(mem_active_file) + int(mem_inactive_file) - | |
1870 int(mem_dirty) - int(mem_min_file)) | |
1871 | |
1872 mem_shared = re.search('Shmem:\s*([\d]+) kB', stdout).group(1) | |
1873 if 'mem_shared' not in stats: | |
1874 stats['mem_shared'] = [] | |
1875 stats['mem_shared'].append(int(mem_shared)) | |
1876 | |
1877 mem_cached = re.search('Cached:\s*([\d]+) kB', stdout).group(1) | |
1878 if 'mem_cached' not in stats: | |
1879 stats['mem_cached'] = [] | |
1880 stats['mem_cached'].append(int(mem_cached)) | |
1881 | |
1882 mem_anon_active = re.search('Active\(anon\):\s*([\d]+) kB', | |
1883 stdout).group(1) | |
1884 mem_anon_inactive = re.search('Inactive\(anon\):\s*([\d]+) kB', | |
1885 stdout).group(1) | |
1886 if 'mem_anon' not in stats: | |
1887 stats['mem_anon'] = [] | |
1888 stats['mem_anon'].append(int(mem_anon_active) + int(mem_anon_inactive)) | |
1889 | |
1890 mem_file_active = re.search('Active\(file\):\s*([\d]+) kB', | |
1891 stdout).group(1) | |
1892 mem_file_inactive = re.search('Inactive\(file\):\s*([\d]+) kB', | |
1893 stdout).group(1) | |
1894 if 'mem_file' not in stats: | |
1895 stats['mem_file'] = [] | |
1896 stats['mem_file'].append(int(mem_file_active) + int(mem_file_inactive)) | |
1897 | |
1898 mem_slab = re.search('Slab:\s*([\d]+) kB', stdout).group(1) | |
1899 if 'mem_slab' not in stats: | |
1900 stats['mem_slab'] = [] | |
1901 stats['mem_slab'].append(int(mem_slab)) | |
1902 | |
1903 # Chrome process memory. | |
1904 pinfo = self.GetProcessInfo()['browsers'][0]['processes'] | |
1905 total_renderer_priv = 0 | |
1906 total_renderer_shared = 0 | |
1907 for process in pinfo: | |
1908 mem_priv = process['working_set_mem']['priv'] | |
1909 mem_shared = process['working_set_mem']['shared'] | |
1910 if process['child_process_type'] == 'Browser': | |
1911 if 'browser_priv' not in stats: | |
1912 stats['browser_priv'] = [] | |
1913 stats['browser_priv'].append(int(mem_priv)) | |
1914 if 'browser_shared' not in stats: | |
1915 stats['browser_shared'] = [] | |
1916 stats['browser_shared'].append(int(mem_shared)) | |
1917 elif process['child_process_type'] == 'GPU': | |
1918 if 'gpu_priv' not in stats: | |
1919 stats['gpu_priv'] = [] | |
1920 stats['gpu_priv'].append(int(mem_priv)) | |
1921 if 'gpu_shared' not in stats: | |
1922 stats['gpu_shared'] = [] | |
1923 stats['gpu_shared'].append(int(mem_shared)) | |
1924 elif process['child_process_type'] == 'Tab': | |
1925 # Sum the memory of all renderer processes. | |
1926 total_renderer_priv += int(mem_priv) | |
1927 total_renderer_shared += int(mem_shared) | |
1928 if 'renderer_priv' not in stats: | |
1929 stats['renderer_priv'] = [] | |
1930 stats['renderer_priv'].append(int(total_renderer_priv)) | |
1931 if 'renderer_shared' not in stats: | |
1932 stats['renderer_shared'] = [] | |
1933 stats['renderer_shared'].append(int(total_renderer_shared)) | |
1934 | |
1935 time.sleep(1) | |
1936 | |
1937 # Compute min, max, and ending values to return. | |
1938 result = {} | |
1939 for measurement_type in stats: | |
1940 values = stats[measurement_type] | |
1941 result[measurement_type] = { | |
1942 'min': min(values), | |
1943 'max': max(values), | |
1944 'end': values[-1], | |
1945 } | |
1946 | |
1947 return result | |
1948 | |
1949 def _RecordMemoryStats(self, description, when, duration): | 1780 def _RecordMemoryStats(self, description, when, duration): |
1950 """Outputs memory statistics to be graphed. | 1781 """Outputs memory statistics to be graphed. |
1951 | 1782 |
1952 Args: | 1783 Args: |
1953 description: A string description for the test. Should not contain | 1784 description: A string description for the test. Should not contain |
1954 spaces. For example, 'MemCtrl'. | 1785 spaces. For example, 'MemCtrl'. |
1955 when: A string description of when the memory stats are being recorded | 1786 when: A string description of when the memory stats are being recorded |
1956 during test execution (since memory stats may be recorded multiple | 1787 during test execution (since memory stats may be recorded multiple |
1957 times during a test execution at certain "interesting" times). Should | 1788 times during a test execution at certain "interesting" times). Should |
1958 not contain spaces. | 1789 not contain spaces. |
1959 duration: The number of seconds to sample data before outputting the | 1790 duration: The number of seconds to sample data before outputting the |
1960 memory statistics. | 1791 memory statistics. |
1961 """ | 1792 """ |
1962 mem = self._GetMemoryStats(duration) | 1793 mem = self.GetMemoryStatsChromeOS(duration) |
1963 measurement_types = [ | 1794 measurement_types = [ |
1964 ('gem_obj', 'GemObj'), | 1795 ('gem_obj', 'GemObj'), |
1965 ('gtt', 'GTT'), | 1796 ('gtt', 'GTT'), |
1966 ('mem_free', 'MemFree'), | 1797 ('mem_free', 'MemFree'), |
1967 ('mem_available', 'MemAvail'), | 1798 ('mem_available', 'MemAvail'), |
1968 ('mem_shared', 'MemShare'), | 1799 ('mem_shared', 'MemShare'), |
1969 ('mem_cached', 'MemCache'), | 1800 ('mem_cached', 'MemCache'), |
1970 ('mem_anon', 'MemAnon'), | 1801 ('mem_anon', 'MemAnon'), |
1971 ('mem_file', 'MemFile'), | 1802 ('mem_file', 'MemFile'), |
1972 ('mem_slab', 'MemSlab'), | 1803 ('mem_slab', 'MemSlab'), |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2267 """Identifies the port number to which the server is currently bound. | 2098 """Identifies the port number to which the server is currently bound. |
2268 | 2099 |
2269 Returns: | 2100 Returns: |
2270 The numeric port number to which the server is currently bound. | 2101 The numeric port number to which the server is currently bound. |
2271 """ | 2102 """ |
2272 return self._server.server_address[1] | 2103 return self._server.server_address[1] |
2273 | 2104 |
2274 | 2105 |
2275 if __name__ == '__main__': | 2106 if __name__ == '__main__': |
2276 pyauto_functional.Main() | 2107 pyauto_functional.Main() |
OLD | NEW |