| Index: build/android/pylib/device/device_utils.py
|
| diff --git a/build/android/pylib/device/device_utils.py b/build/android/pylib/device/device_utils.py
|
| index eba5e0203a2d247223b9628284fb96708db924e2..fb882e73b85008a1b66a24758a34f64e060a7fdb 100644
|
| --- a/build/android/pylib/device/device_utils.py
|
| +++ b/build/android/pylib/device/device_utils.py
|
| @@ -8,6 +8,8 @@ Eventually, this will be based on adb_wrapper.
|
| """
|
| # pylint: disable=unused-argument
|
|
|
| +import collections
|
| +import itertools
|
| import logging
|
| import multiprocessing
|
| import os
|
| @@ -1306,14 +1308,54 @@ class DeviceUtils(object):
|
| retries: number of retries
|
|
|
| Returns:
|
| - A 2-tuple containing:
|
| - - A dict containing the overall memory usage statistics for the PID.
|
| - - A dict containing memory usage statistics broken down by mapping.
|
| + A dict containing memory usage statistics for the PID. May include:
|
| + Size, Rss, Pss, Shared_Clean, Shared_Dirty, Private_Clean,
|
| + Private_Dirty, VmHWM
|
|
|
| Raises:
|
| CommandTimeoutError on timeout.
|
| """
|
| - return self.old_interface.GetMemoryUsageForPid(pid)
|
| + result = collections.defaultdict(int)
|
| +
|
| + try:
|
| + result.update(self._GetMemoryUsageForPidFromSmaps(pid))
|
| + except device_errors.CommandFailedError:
|
| + logging.exception('Error getting memory usage from smaps')
|
| +
|
| + try:
|
| + result.update(self._GetMemoryUsageForPidFromStatus(pid))
|
| + except device_errors.CommandFailedError:
|
| + logging.exception('Error getting memory usage from status')
|
| +
|
| + return result
|
| +
|
| + def _GetMemoryUsageForPidFromSmaps(self, pid):
|
| + SMAPS_COLUMNS = (
|
| + 'Size', 'Rss', 'Pss', 'Shared_Clean', 'Shared_Dirty', 'Private_Clean',
|
| + 'Private_Dirty')
|
| +
|
| + showmap_out = self.RunShellCommand(
|
| + ['showmap', str(pid)], as_root=True, check_return=True)
|
| + if not showmap_out:
|
| + raise device_errors.CommandFailedError('No output from showmap')
|
| +
|
| + split_totals = showmap_out[-1].split()
|
| + if (not split_totals
|
| + or len(split_totals) != 9
|
| + or split_totals[-1] != 'TOTAL'):
|
| + raise device_errors.CommandFailedError(
|
| + 'Invalid output from showmap: %s' % '\n'.join(showmap_out))
|
| +
|
| + return dict(itertools.izip(SMAPS_COLUMNS, (int(n) for n in split_totals)))
|
| +
|
| + def _GetMemoryUsageForPidFromStatus(self, pid):
|
| + for line in self.ReadFile(
|
| + '/proc/%s/status' % str(pid), as_root=True).splitlines():
|
| + if line.startswith('VmHWM:'):
|
| + return {'VmHWM': int(line.split()[1])}
|
| + else:
|
| + raise device_errors.CommandFailedError(
|
| + 'Could not find memory peak value for pid %s', str(pid))
|
|
|
| @decorators.WithTimeoutAndRetriesFromInstance()
|
| def GetLogcatMonitor(self, timeout=None, retries=None, *args, **kwargs):
|
| @@ -1386,6 +1428,8 @@ class DeviceUtils(object):
|
| """
|
| if not devices:
|
| devices = adb_wrapper.AdbWrapper.GetDevices()
|
| + if not devices:
|
| + raise device_errors.NoDevicesError()
|
| devices = [d if isinstance(d, cls) else cls(d) for d in devices]
|
| if async:
|
| return parallelizer.Parallelizer(devices)
|
|
|