Index: third_party/psutil/examples/iotop.py |
diff --git a/third_party/psutil/examples/iotop.py b/third_party/psutil/examples/iotop.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..2307c75aa7ed2d20cab343b1d7dc4804da4b9fb4 |
--- /dev/null |
+++ b/third_party/psutil/examples/iotop.py |
@@ -0,0 +1,136 @@ |
+#!/usr/bin/env python |
+# |
+# $Id: iotop.py 1143 2011-10-05 19:11:59Z g.rodola $ |
+# |
+# Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+""" |
+A clone of iotop (http://guichaz.free.fr/iotop/) showing real time |
+disk I/O statistics. |
+ |
+It works on UNIX only as curses module is not available on Windows. |
+ |
+Author: Giampaolo Rodola' <g.rodola@gmail.com> |
+""" |
+ |
+import time |
+import curses |
+import atexit |
+ |
+import psutil |
+ |
+win = curses.initscr() |
+ |
+def bytes2human(n): |
+ """ |
+ >>> bytes2human(10000) |
+ '9.8 K/s' |
+ >>> bytes2human(100001221) |
+ '95.4 M/s' |
+ """ |
+ symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') |
+ prefix = {} |
+ for i, s in enumerate(symbols): |
+ prefix[s] = 1 << (i+1)*10 |
+ for s in reversed(symbols): |
+ if n >= prefix[s]: |
+ value = float(n) / prefix[s] |
+ return '%.2f %s/s' % (value, s) |
+ return "0.00 B/s" |
+ |
+def poll(interval): |
+ """Calculate IO usage by comparing IO statics before and |
+ after the interval. |
+ Return a tuple including all currently running processes |
+ sorted by IO activity and total disks I/O activity. |
+ """ |
+ # first get a list of all processes and disk io counters |
+ procs = [p for p in psutil.process_iter()] |
+ for p in procs[:]: |
+ try: |
+ p._before = p.get_io_counters() |
+ except psutil.Error: |
+ procs.remove(p) |
+ continue |
+ disks_before = psutil.disk_io_counters() |
+ |
+ # sleep some time |
+ time.sleep(interval) |
+ |
+ # then retrieve the same info again |
+ for p in procs[:]: |
+ try: |
+ p._after = p.get_io_counters() |
+ p._cmdline = ' '.join(p.cmdline) |
+ if not p._cmdline: |
+ p._cmdline = p.name |
+ p._username = p.username |
+ except psutil.NoSuchProcess: |
+ procs.remove(p) |
+ disks_after = psutil.disk_io_counters() |
+ |
+ # finally calculate results by comparing data before and |
+ # after the interval |
+ for p in procs: |
+ p._read_per_sec = p._after.read_bytes - p._before.read_bytes |
+ p._write_per_sec = p._after.write_bytes - p._before.write_bytes |
+ p._total = p._read_per_sec + p._write_per_sec |
+ |
+ disks_read_per_sec = disks_after.read_bytes - disks_before.read_bytes |
+ disks_write_per_sec = disks_after.write_bytes - disks_before.write_bytes |
+ |
+ # sort processes by total disk IO so that the more intensive |
+ # ones get listed first |
+ processes = sorted(procs, key=lambda p: p._total, reverse=True) |
+ |
+ return (processes, disks_read_per_sec, disks_write_per_sec) |
+ |
+def run(win): |
+ """Print results on screen by using curses.""" |
+ curses.endwin() |
+ templ = "%-5s %-7s %11s %11s %s" |
+ interval = 0 |
+ while 1: |
+ procs, disks_read, disks_write = poll(interval) |
+ win.erase() |
+ |
+ disks_tot = "Total DISK READ: %s | Total DISK WRITE: %s" \ |
+ % (bytes2human(disks_read), bytes2human(disks_write)) |
+ win.addstr(0, 0, disks_tot) |
+ |
+ header = templ % ("PID", "USER", "DISK READ", "DISK WRITE", "COMMAND") |
+ header += " " * (win.getmaxyx()[1] - len(header)) |
+ win.addstr(1, 0, header, curses.A_REVERSE) |
+ |
+ lineno = 2 |
+ for p in procs: |
+ line = templ % (p.pid, |
+ p._username[:7], |
+ bytes2human(p._read_per_sec), |
+ bytes2human(p._write_per_sec), |
+ p._cmdline) |
+ try: |
+ win.addstr(lineno, 0, line) |
+ except curses.error: |
+ break |
+ win.refresh() |
+ lineno += 1 |
+ interval = 1 |
+ |
+def main(): |
+ def tear_down(): |
+ win.keypad(0) |
+ curses.nocbreak() |
+ curses.echo() |
+ curses.endwin() |
+ |
+ atexit.register(tear_down) |
+ try: |
+ run(win) |
+ except (KeyboardInterrupt, SystemExit): |
+ pass |
+ |
+if __name__ == '__main__': |
+ main() |