Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3982)

Unified Diff: build/android/pylib/device_stats_monitor.py

Issue 10783020: Add an activity monitor which profiles IO and CPU utilization. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed review comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/android/pylib/device_stats_monitor.html ('k') | build/android/pylib/test_options_parser.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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]])
« no previous file with comments | « build/android/pylib/device_stats_monitor.html ('k') | build/android/pylib/test_options_parser.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698