OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 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 """Provides an interface to communicate with the device via the adb command. | 5 """Provides an interface to communicate with the device via the adb command. |
6 | 6 |
7 Assumes adb binary is currently on system path. | 7 Assumes adb binary is currently on system path. |
8 """ | 8 """ |
9 # pylint: disable-all | 9 # pylint: disable-all |
10 | 10 |
(...skipping 1572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1583 logging.warning('Could not find disk IO stats.') | 1583 logging.warning('Could not find disk IO stats.') |
1584 return None | 1584 return None |
1585 | 1585 |
1586 def GetMemoryUsageForPid(self, pid): | 1586 def GetMemoryUsageForPid(self, pid): |
1587 """Returns the memory usage for given pid. | 1587 """Returns the memory usage for given pid. |
1588 | 1588 |
1589 Args: | 1589 Args: |
1590 pid: The pid number of the specific process running on device. | 1590 pid: The pid number of the specific process running on device. |
1591 | 1591 |
1592 Returns: | 1592 Returns: |
1593 A tuple containg: | 1593 Dict of {metric:usage_kb}, for the process which has specified pid. |
1594 [0]: Dict of {metric:usage_kb}, for the process which has specified pid. | |
1595 The metric keys which may be included are: Size, Rss, Pss, Shared_Clean, | 1594 The metric keys which may be included are: Size, Rss, Pss, Shared_Clean, |
1596 Shared_Dirty, Private_Clean, Private_Dirty, Referenced, Swap, | 1595 Shared_Dirty, Private_Clean, Private_Dirty, VmHWM. |
1597 KernelPageSize, MMUPageSize, VmHWM. | |
1598 [1]: Detailed /proc/[PID]/smaps information. | |
1599 """ | 1596 """ |
| 1597 showmap = self.RunShellCommand('showmap %d' % pid) |
| 1598 if not showmap or not showmap[-1].endswith('TOTAL'): |
| 1599 logging.warning('Invalid output for showmap %s', str(showmap)) |
| 1600 return {} |
| 1601 items = showmap[-1].split() |
| 1602 if len(items) != 9: |
| 1603 logging.warning('Invalid TOTAL for showmap %s', str(items)) |
| 1604 return {} |
1600 usage_dict = collections.defaultdict(int) | 1605 usage_dict = collections.defaultdict(int) |
1601 smaps = collections.defaultdict(dict) | 1606 usage_dict.update({ |
1602 current_smap = '' | 1607 'Size': int(items[0].strip()), |
1603 for line in self.GetProtectedFileContents('/proc/%s/smaps' % pid): | 1608 'Rss': int(items[1].strip()), |
1604 items = line.split() | 1609 'Pss': int(items[2].strip()), |
1605 # See man 5 proc for more details. The format is: | 1610 'Shared_Clean': int(items[3].strip()), |
1606 # address perms offset dev inode pathname | 1611 'Shared_Dirty': int(items[4].strip()), |
1607 if len(items) > 5: | 1612 'Private_Clean': int(items[5].strip()), |
1608 current_smap = ' '.join(items[5:]) | 1613 'Private_Dirty': int(items[6].strip()), |
1609 elif len(items) > 3: | 1614 }) |
1610 current_smap = ' '.join(items[3:]) | |
1611 if line.endswith('kB'): | |
1612 key, value = line.split(':') | |
1613 key = key.strip() | |
1614 usage_kb = int(value.strip().split()[0]) | |
1615 usage_dict[key] += usage_kb | |
1616 if key not in smaps[current_smap]: | |
1617 smaps[current_smap][key] = 0 | |
1618 smaps[current_smap][key] += usage_kb | |
1619 if not usage_dict or not any(usage_dict.values()): | |
1620 # Presumably the process died between ps and calling this method. | |
1621 logging.warning('Could not find memory usage for pid ' + str(pid)) | |
1622 | |
1623 peak_value_kb = 0 | 1615 peak_value_kb = 0 |
1624 for line in self.GetProtectedFileContents('/proc/%s/status' % pid): | 1616 for line in self.GetProtectedFileContents('/proc/%s/status' % pid): |
1625 if not line.startswith('VmHWM:'): # Format: 'VmHWM: +[0-9]+ kB' | 1617 if not line.startswith('VmHWM:'): # Format: 'VmHWM: +[0-9]+ kB' |
1626 continue | 1618 continue |
1627 peak_value_kb = int(line.split(':')[1].strip().split(' ')[0]) | 1619 peak_value_kb = int(line.split(':')[1].strip().split(' ')[0]) |
1628 break | 1620 break |
1629 usage_dict['VmHWM'] = peak_value_kb | 1621 usage_dict['VmHWM'] = peak_value_kb |
1630 if not peak_value_kb: | 1622 if not peak_value_kb: |
1631 logging.warning('Could not find memory peak value for pid ' + str(pid)) | 1623 logging.warning('Could not find memory peak value for pid ' + str(pid)) |
1632 | 1624 |
1633 return (usage_dict, smaps) | 1625 return usage_dict |
1634 | |
1635 def GetMemoryUsageForPackage(self, package): | |
1636 """Returns the memory usage for all processes whose name contains |pacakge|. | |
1637 | |
1638 Args: | |
1639 package: A string holding process name to lookup pid list for. | |
1640 | |
1641 Returns: | |
1642 A tuple containg: | |
1643 [0]: Dict of {metric:usage_kb}, summed over all pids associated with | |
1644 |name|. | |
1645 The metric keys which may be included are: Size, Rss, Pss, Shared_Clean, | |
1646 Shared_Dirty, Private_Clean, Private_Dirty, Referenced, Swap, | |
1647 KernelPageSize, MMUPageSize, Nvidia (tablet only). | |
1648 [1]: a list with detailed /proc/[PID]/smaps information. | |
1649 """ | |
1650 usage_dict = collections.defaultdict(int) | |
1651 pid_list = self.ExtractPid(package) | |
1652 smaps = collections.defaultdict(dict) | |
1653 | |
1654 for pid in pid_list: | |
1655 usage_dict_per_pid, smaps_per_pid = self.GetMemoryUsageForPid(pid) | |
1656 smaps[pid] = smaps_per_pid | |
1657 for (key, value) in usage_dict_per_pid.items(): | |
1658 usage_dict[key] += value | |
1659 | |
1660 return usage_dict, smaps | |
1661 | 1626 |
1662 def ProcessesUsingDevicePort(self, device_port): | 1627 def ProcessesUsingDevicePort(self, device_port): |
1663 """Lists processes using the specified device port on loopback interface. | 1628 """Lists processes using the specified device port on loopback interface. |
1664 | 1629 |
1665 Args: | 1630 Args: |
1666 device_port: Port on device we want to check. | 1631 device_port: Port on device we want to check. |
1667 | 1632 |
1668 Returns: | 1633 Returns: |
1669 A list of (pid, process_name) tuples using the specified port. | 1634 A list of (pid, process_name) tuples using the specified port. |
1670 """ | 1635 """ |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1959 """ | 1924 """ |
1960 def __init__(self, output): | 1925 def __init__(self, output): |
1961 self._output = output | 1926 self._output = output |
1962 | 1927 |
1963 def write(self, data): | 1928 def write(self, data): |
1964 data = data.replace('\r\r\n', '\n') | 1929 data = data.replace('\r\r\n', '\n') |
1965 self._output.write(data) | 1930 self._output.write(data) |
1966 | 1931 |
1967 def flush(self): | 1932 def flush(self): |
1968 self._output.flush() | 1933 self._output.flush() |
OLD | NEW |