summaryrefslogtreecommitdiffstats
path: root/tools/android/ps_ext
diff options
context:
space:
mode:
authorprimiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-07 14:28:40 +0000
committerprimiano@chromium.org <primiano@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-07 14:28:40 +0000
commit857a91e9c53d64f522efefdbc6952b7244599fa0 (patch)
treed791105d0315e54d665a9dde46b9a2631513a966 /tools/android/ps_ext
parent62c731445653227c03428878d15c229cf942310f (diff)
downloadchromium_src-857a91e9c53d64f522efefdbc6952b7244599fa0.zip
chromium_src-857a91e9c53d64f522efefdbc6952b7244599fa0.tar.gz
chromium_src-857a91e9c53d64f522efefdbc6952b7244599fa0.tar.bz2
[Android] Add ps_ext tool for tools-friendly cpu/mem/proc stats.
ps_ext is a simple ps-like tool, which generates a JSON dump containing OS and processes stats. It is intended to be used by other tools, in particular by the new memory_inspector (see related bug). BUG=340294 R=pliard@chromium.org Review URL: https://codereview.chromium.org/146803007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249686 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/android/ps_ext')
-rw-r--r--tools/android/ps_ext/ps_ext.c189
-rw-r--r--tools/android/ps_ext/ps_ext.gyp28
2 files changed, 217 insertions, 0 deletions
diff --git a/tools/android/ps_ext/ps_ext.c b/tools/android/ps_ext/ps_ext.c
new file mode 100644
index 0000000..caf6d88
--- /dev/null
+++ b/tools/android/ps_ext/ps_ext.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2014 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.
+ */
+
+#include <dirent.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+/*
+ * This tool is essentially an extended version of ps with JSON output.
+ * Its output is meant consumed by scripts / tools for gathering OS/ps stats.
+ * Output units:
+ * All times are expressed in ticks.
+ * All memory counters are expressed in Kb.
+ */
+
+#define CONV_PAGES_TO_KB(x) (x << (PAGE_SHIFT - 10))
+
+static void dump_time(void) {
+ struct timespec tm = {0, 0};
+ const long rate = sysconf(_SC_CLK_TCK);
+ clock_gettime(CLOCK_MONOTONIC, &tm);
+ const long ticks = rate * (tm.tv_sec * 1000L + tm.tv_nsec / 1000000) / 1000;
+ printf(" \"time\": { \"ticks\": %d, \"rate\": %d}", ticks, rate);
+}
+
+static void dump_cpu_stats(void) {
+ FILE *f = fopen("/proc/stat", "r");
+ if (!f)
+ return;
+ printf(" \"cpu\":\n [\n");
+
+ bool terminate_prev_line = false;
+ while (!feof(f)) {
+ char line[256];
+ char cpu[8];
+ long unsigned t_usr = 0;
+ long unsigned t_nice = 0;
+ long unsigned t_sys = 0;
+ long unsigned t_idle = 0;
+ fgets(line, sizeof(line), f);
+
+ /* Skip the total 'cpu ' line and the other irrelevant ones. */
+ if (strncmp(line, "cpu", 3) != 0 || line[3] == ' ')
+ continue;
+ if (sscanf(line, "%s %lu %lu %lu %lu",
+ cpu, &t_usr, &t_nice, &t_sys, &t_idle) != 5) {
+ continue;
+ }
+
+ if (terminate_prev_line)
+ printf(",\n");
+ terminate_prev_line = true;
+ printf(" {\"usr\": %lu, \"sys\": %lu, \"idle\": %lu}",
+ t_usr + t_nice, t_sys, t_idle);
+ }
+ fclose(f);
+ printf("\n ]");
+}
+
+static void dump_mem_stats(void) {
+ FILE *f = fopen("/proc/meminfo", "r");
+ if (!f)
+ return;
+ printf(" \"mem\":\n {\n");
+
+ bool terminate_prev_line = false;
+ while (!feof(f)) {
+ char line[256];
+ char key[32];
+ long value = 0;
+
+ fgets(line, sizeof(line), f);
+ if (sscanf(line, "%s %lu %*s", key, &value) < 2)
+ continue;
+
+ if (terminate_prev_line)
+ printf(",\n");
+ terminate_prev_line = true;
+ printf(" \"%s\": %lu", key, value);
+ }
+ fclose(f);
+ printf("\n }");
+}
+
+static void dump_proc_stats(void) {
+ struct dirent *de;
+ DIR *d = opendir("/proc");
+ if (!d)
+ return;
+
+ bool terminate_prev_line = false;
+ printf(" \"processes\":\n [\n");
+ while ((de = readdir(d))) {
+ if (!isdigit(de->d_name[0]))
+ continue;
+ const int pid = atoi(de->d_name);
+
+ /* Don't print out ourselves (how civilized). */
+ if (pid == getpid())
+ continue;
+
+ char cmdline[64];
+ char fpath[32];
+ FILE *f;
+
+ /* Read full process path / package from cmdline. */
+ sprintf(fpath, "/proc/%d/cmdline", pid);
+ f = fopen(fpath, "r");
+ if (!f)
+ continue;
+ cmdline[0] = '\0';
+ fgets(cmdline, sizeof(cmdline), f);
+ fclose(f);
+
+ /* Read cpu/io/mem stats. */
+ char proc_name[256];
+ long num_threads = 0;
+ long unsigned min_faults = 0;
+ long unsigned maj_faults = 0;
+ long unsigned utime = 0;
+ long unsigned ktime = 0;
+ long unsigned vm_rss = 0;
+ long long unsigned start_time = 0;
+
+ sprintf(fpath, "/proc/%d/stat", pid);
+ f = fopen(fpath, "r");
+ if (!f)
+ continue;
+ fscanf(f, "%*d %s %*c %*d %*d %*d %*d %*d %*u %lu %*lu %lu %*lu %lu %lu "
+ "%*ld %*ld %*ld %*ld %ld %*ld %llu %*lu %ld", proc_name, &min_faults,
+ &maj_faults, &utime, &ktime, &num_threads, &start_time, &vm_rss);
+ fclose(f);
+
+ /* Prefer the cmdline when available, since it contains the package name. */
+ char const * const cmd = (strlen(cmdline) > 0) ? cmdline : proc_name;
+
+ if (terminate_prev_line)
+ printf(",\n");
+ terminate_prev_line = true;
+ printf(" {"
+ "\"pid\": %d, "
+ "\"name\": \"%s\", "
+ "\"n_threads\": %ld, "
+ "\"start_time\": %llu, "
+ "\"user_time\": %lu, "
+ "\"sys_time\": %lu, "
+ "\"min_faults\": %lu, "
+ "\"maj_faults\": %lu, "
+ "\"vm_rss\": %lu"
+ "}",
+ pid,
+ cmd,
+ num_threads,
+ start_time,
+ utime,
+ ktime,
+ min_faults,
+ maj_faults,
+ CONV_PAGES_TO_KB(vm_rss));
+ }
+ closedir(d);
+ printf("\n ]");
+}
+
+int main()
+{
+ printf("{\n");
+
+ dump_time();
+ printf(",\n");
+
+ dump_mem_stats();
+ printf(",\n");
+
+ dump_cpu_stats();
+ printf(",\n");
+
+ dump_proc_stats();
+ printf("\n}\n");
+
+ return 0;
+}
diff --git a/tools/android/ps_ext/ps_ext.gyp b/tools/android/ps_ext/ps_ext.gyp
new file mode 100644
index 0000000..f1a24fe
--- /dev/null
+++ b/tools/android/ps_ext/ps_ext.gyp
@@ -0,0 +1,28 @@
+# Copyright 2014 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.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'ps_ext',
+ 'type': 'executable',
+ 'conditions': [
+ # Warning: A PIE tool cannot run on ICS 4.0.4, so only
+ # build it as position-independent when ASAN
+ # is activated. See b/6587214 for details.
+ [ 'asan==1', {
+ 'cflags': [
+ '-fPIE',
+ ],
+ 'ldflags': [
+ '-pie',
+ ],
+ }],
+ ],
+ 'sources': [
+ 'ps_ext.c',
+ ],
+ },
+ ],
+}