| Index: build/android/pylib/device_stats_monitor.py
|
| diff --git a/build/android/pylib/device_stats_monitor.py b/build/android/pylib/device_stats_monitor.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..79225028baf7c19ac51276b956181e1ab8eb33da
|
| --- /dev/null
|
| +++ b/build/android/pylib/device_stats_monitor.py
|
| @@ -0,0 +1,116 @@
|
| +# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Utilities for iotop/top style profiling for android."""
|
| +
|
| +import collections
|
| +import json
|
| +import os
|
| +import subprocess
|
| +import sys
|
| +import urllib
|
| +
|
| +import constants
|
| +import io_stats_parser
|
| +
|
| +
|
| +class DeviceStatsMonitor(object):
|
| + """Class for collecting device stats such as IO/CPU usage.
|
| +
|
| + Args:
|
| + adb: Instance of AndroidComannds.
|
| + hz: Frequency at which to sample device stats.
|
| + """
|
| +
|
| + DEVICE_PATH = '/data/local/tmp/device_stats_monitor'
|
| + HOST_PATH = os.path.abspath(os.path.join(
|
| + constants.CHROME_DIR, 'out', 'Release', 'device_stats_monitor'))
|
| + PROFILE_PATH = '/sdcard/Download/device_stats_monitor.profile'
|
| + RESULT_VIEWER_PATH = os.path.abspath(os.path.join(
|
| + os.path.dirname(os.path.realpath(__file__)), 'device_stats_monitor.html'))
|
| +
|
| + def __init__(self, adb, hz):
|
| + self._adb = adb
|
| + self._adb.PushIfNeeded(DeviceStatsMonitor.HOST_PATH,
|
| + DeviceStatsMonitor.DEVICE_PATH)
|
| + self._hz = hz
|
| +
|
| + def Start(self):
|
| + """Starts device stats monitor on the device."""
|
| + self._adb.SetFileContents(DeviceStatsMonitor.PROFILE_PATH, '')
|
| + self._process = subprocess.Popen(
|
| + ['adb', 'shell', '%s --hz=%d %s' % (
|
| + DeviceStatsMonitor.DEVICE_PATH, self._hz,
|
| + DeviceStatsMonitor.PROFILE_PATH)])
|
| +
|
| + def StopAndCollect(self, output_path):
|
| + """Stops monitoring and saves results.
|
| +
|
| + Args:
|
| + output_path: Path to save results.
|
| +
|
| + Returns:
|
| + String of URL to load results in browser.
|
| + """
|
| + assert self._process
|
| + self._adb.KillAll(DeviceStatsMonitor.DEVICE_PATH)
|
| + self._process.wait()
|
| + profile = self._adb.GetFileContents(DeviceStatsMonitor.PROFILE_PATH)
|
| +
|
| + results = collections.defaultdict(list)
|
| + last_io_stats = None
|
| + last_cpu_stats = None
|
| + for line in profile:
|
| + if ' mmcblk0 ' in line:
|
| + stats = io_stats_parser.ParseIoStatsLine(line)
|
| + if last_io_stats:
|
| + results['sectors_read'].append(stats.num_sectors_read -
|
| + last_io_stats.num_sectors_read)
|
| + results['sectors_written'].append(stats.num_sectors_written -
|
| + last_io_stats.num_sectors_written)
|
| + last_io_stats = stats
|
| + elif line.startswith('cpu '):
|
| + stats = self._ParseCpuStatsLine(line)
|
| + if last_cpu_stats:
|
| + results['user'].append(stats.user - last_cpu_stats.user)
|
| + results['nice'].append(stats.nice - last_cpu_stats.nice)
|
| + results['system'].append(stats.system - last_cpu_stats.system)
|
| + results['idle'].append(stats.idle - last_cpu_stats.idle)
|
| + results['iowait'].append(stats.iowait - last_cpu_stats.iowait)
|
| + results['irq'].append(stats.irq - last_cpu_stats.irq)
|
| + results['softirq'].append(stats.softirq- last_cpu_stats.softirq)
|
| + last_cpu_stats = stats
|
| + units = {
|
| + 'sectors_read': 'sectors',
|
| + 'sectors_written': 'sectors',
|
| + 'user': 'jiffies',
|
| + 'nice': 'jiffies',
|
| + 'system': 'jiffies',
|
| + 'idle': 'jiffies',
|
| + 'iowait': 'jiffies',
|
| + 'irq': 'jiffies',
|
| + 'softirq': 'jiffies',
|
| + }
|
| + with open(output_path, 'w') as f:
|
| + f.write('display(%d, %s, %s);' % (self._hz, json.dumps(results), units))
|
| + return 'file://%s?results=file://%s' % (
|
| + DeviceStatsMonitor.RESULT_VIEWER_PATH, urllib.quote(output_path))
|
| +
|
| +
|
| + @staticmethod
|
| + def _ParseCpuStatsLine(line):
|
| + """Parses a line of cpu stats into a CpuStats named tuple."""
|
| + # Field definitions: http://www.linuxhowtos.org/System/procstat.htm
|
| + cpu_stats = collections.namedtuple('CpuStats',
|
| + ['device',
|
| + 'user',
|
| + 'nice',
|
| + 'system',
|
| + 'idle',
|
| + 'iowait',
|
| + 'irq',
|
| + 'softirq',
|
| + ])
|
| + fields = line.split()
|
| + return cpu_stats._make([fields[0]] + [int(f) for f in fields[1:8]])
|
|
|