From 092f28c6258d5e56479ffeba6fd6ce056c21ea8c Mon Sep 17 00:00:00 2001
From: Avi Kivity <avi@cloudius-systems.com>
Date: Mon, 17 Jun 2013 13:31:26 +0300
Subject: [PATCH] cli: add stat command

Usage:

  perf list (lists all tracepoints)
  perf stat tp... (counts tracepoints)

Example:

[/]$ perf stat mutex_lock ctxsw=sched_switch mutex_unlock wake=sched_wake
  mutex_lock   ctxsw  mutex_unlock    wake
          40       3          1909       2
        2075     147           190      82
         193     138           193      78
         146     139           146      92
         317     179           317      78
         146     139           146      78
         146     139           186      78
         205     139           165      78
         146     139           146      78
         146     139           146      78
         146     139           146      80
         193     143           193      81
         151     147           151      78
         146     139           146      78
         146     139           146      78
         146     139           146      78
         159     139           159      78
         149     139           149      78
         146     139           146      78
         164     139           164      78
         146     139           176      78
         176     139           146      78
         149     139           149      78
         146     139           146      78
         146     139           146      78
  mutex_lock   ctxsw  mutex_unlock    wake
         146     139           146      79
         715     147           715      80
         188     139           204      78
---
 bootfs.manifest |   1 +
 console/cli.js  |   2 +
 console/perf.js | 104 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 107 insertions(+)
 create mode 100644 console/perf.js

diff --git a/bootfs.manifest b/bootfs.manifest
index 632420c69..cf2382b0f 100644
--- a/bootfs.manifest
+++ b/bootfs.manifest
@@ -119,4 +119,5 @@
 /console/cli.js: ../../console/cli.js
 /console/init.js: ../../console/init.js
 /console/md5sum.js: ../../console/md5sum.js
+/&/console/perf.js: ../../&
 /&/etc/hosts: ../../static/&
diff --git a/console/cli.js b/console/cli.js
index 82d97ec8d..850ea7d94 100644
--- a/console/cli.js
+++ b/console/cli.js
@@ -17,6 +17,7 @@ load("/console/arp.js");
 load("/console/md5sum.js");
 load("/console/route.js");
 load("/console/java.js");
+load("/console/perf.js");
 
 // Commands
 var _commands = new Array();
@@ -32,6 +33,7 @@ _commands["arp"] = arp_cmd;
 _commands["route"] = route_cmd;
 _commands["md5sum"] = md5sum_cmd;
 _commands["java"] = java_cmd;
+_commands["perf"] = perf_cmd;
 
 // Create interface to networking functions
 var networking_interface = new Networking();
diff --git a/console/perf.js b/console/perf.js
new file mode 100644
index 000000000..3f04addd0
--- /dev/null
+++ b/console/perf.js
@@ -0,0 +1,104 @@
+
+
+var perf_cmd = {
+    invoke: function(args) {
+        args.shift()
+        var cmd = args.shift()
+        if (cmd in this.subcommands) {
+            this.subcommands[cmd].invoke(args)
+        } else {
+            this.help([])
+        }
+    },
+    help: function(args) {
+        write_string('usage:\n\n')
+        for (var k in this.subcommands) {
+            write_string('  perf ' + this.subcommands[k].usage + '\n')
+        }
+    },
+    list: function(args) {
+        write_string('available tracpoints:\n\n')
+        trace = Packages.com.cloudius.trace
+        all = trace.Tracepoint.list()
+        for (var i = 0; i < all.size(); ++i) {
+            var tp = all.get(i)
+            write_string('    ' + String(tp.getName()))
+            write_char('\n')
+        }
+    },
+    stat: function(args) {
+        var pkg = Packages.com.cloudius.trace
+        var counters = []
+        for (var i in args) {
+            var x = args[i]
+            var m = /^(([^=]+)=)?(.+)$/.exec(x)
+            var tag = m[2]
+            var name = m[3]
+            if (!tag) {
+                tag = name
+            }
+            try {
+                var tp = new pkg.Tracepoint(name)
+                var counter = new pkg.Counter(tp)
+                counters.push({
+                    tag: tag,
+                    counter: counter,
+                    width: Math.max(8, tag.length + 2),
+                    last: 0,
+                })
+            } catch (err) {
+                write_string('bad tracepoint "' + name + '"\n')
+                return
+            }
+        }
+        var titles = function() {
+            for (var i in counters) {
+                var c = counters[i]
+                for (var j = c.tag.length; j < c.width; ++j) {
+                    write_string(' ')
+                }
+                write_string(c.tag)
+            }
+            write_string('\n')
+        }
+        var show = function() {
+            for (var i in counters) {
+                var ctr = counters[i]
+                var last = ctr.last
+                ctr.last = ctr.counter.read()
+                var delta = ctr.last - last
+                delta = delta.toString()
+                for (var j = delta.length; j < ctr.width; ++j) {
+                    write_string(' ')
+                }
+                write_string(delta)
+            }
+            write_string('\n')
+        }
+        var line = 0
+        while (true) {
+            if (line++ % 25 == 0) {
+                titles()
+            }
+            show()
+            flush()
+            java.lang.Thread.sleep(1000)
+        }
+    },
+    subcommands: {
+        list: {
+            invoke: function(args) { this.parent.list(args) },
+            usage: 'list',
+        },
+        stat: {
+            invoke: function(args) { this.parent.stat(args) },
+            usage: 'stat [[tag=]tracepoint]...',
+        },
+    },
+    init: function() {
+        for (var k in this.subcommands) {
+            this.subcommands[k].parent = this
+        }
+    },
+}
+
-- 
GitLab