Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux...
authorIngo Molnar <mingo@elte.hu>
Wed, 27 Oct 2010 06:25:15 +0000 (08:25 +0200)
committerIngo Molnar <mingo@elte.hu>
Wed, 27 Oct 2010 06:25:15 +0000 (08:25 +0200)
tools/perf/Documentation/perf-record.txt
tools/perf/builtin-record.c
tools/perf/builtin-trace.c
tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py
tools/perf/scripts/python/bin/futex-contention-record [new file with mode: 0644]
tools/perf/scripts/python/bin/futex-contention-report [new file with mode: 0644]
tools/perf/scripts/python/futex-contention.py [new file with mode: 0644]
tools/perf/scripts/python/sctop.py
tools/perf/util/debug.c
tools/perf/util/debug.h

index 3ee27dc..a91f9f9 100644 (file)
@@ -83,6 +83,10 @@ OPTIONS
 --call-graph::
        Do call-graph (stack chain/backtrace) recording.
 
+-q::
+--quiet::
+       Don't print any message, useful for scripting.
+
 -v::
 --verbose::
        Be more verbose (show counter open errors, etc).
index ff77b80..4e75583 100644 (file)
@@ -353,7 +353,7 @@ try_again:
                }
 
                if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) {
-                       perror("Unable to read perf file descriptor\n");
+                       perror("Unable to read perf file descriptor");
                        exit(-1);
                }
 
@@ -626,7 +626,7 @@ static int __cmd_record(int argc, const char **argv)
 
        nr_cpus = read_cpu_map(cpu_list);
        if (nr_cpus < 1) {
-               perror("failed to collect number of CPUs\n");
+               perror("failed to collect number of CPUs");
                return -1;
        }
 
@@ -761,6 +761,9 @@ static int __cmd_record(int argc, const char **argv)
                }
        }
 
+       if (quiet)
+               return 0;
+
        fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
 
        /*
@@ -820,6 +823,7 @@ static const struct option options[] = {
                    "do call-graph (stack chain/backtrace) recording"),
        OPT_INCR('v', "verbose", &verbose,
                    "be more verbose (show counter open errors, etc)"),
+       OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"),
        OPT_BOOLEAN('s', "stat", &inherit_stat,
                    "per thread counts"),
        OPT_BOOLEAN('d', "data", &sample_address,
index deda1a9..2f8df45 100644 (file)
@@ -625,12 +625,13 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used)
                        dup2(live_pipe[1], 1);
                        close(live_pipe[0]);
 
-                       __argv = malloc(5 * sizeof(const char *));
+                       __argv = malloc(6 * sizeof(const char *));
                        __argv[0] = "/bin/sh";
                        __argv[1] = record_script_path;
-                       __argv[2] = "-o";
-                       __argv[3] = "-";
-                       __argv[4] = NULL;
+                       __argv[2] = "-q";
+                       __argv[3] = "-o";
+                       __argv[4] = "-";
+                       __argv[5] = NULL;
 
                        execvp("/bin/sh", (char **)__argv);
                        exit(-1);
index 99ff1b7..13cc02b 100644 (file)
@@ -8,6 +8,12 @@
 
 import errno, os
 
+FUTEX_WAIT = 0
+FUTEX_WAKE = 1
+FUTEX_PRIVATE_FLAG = 128
+FUTEX_CLOCK_REALTIME = 256
+FUTEX_CMD_MASK = ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME)
+
 NSECS_PER_SEC    = 1000000000
 
 def avg(total, n):
@@ -26,6 +32,18 @@ def nsecs_str(nsecs):
     str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)),
     return str
 
+def add_stats(dict, key, value):
+       if not dict.has_key(key):
+               dict[key] = (value, value, value, 1)
+       else:
+               min, max, avg, count = dict[key]
+               if value < min:
+                       min = value
+               if value > max:
+                       max = value
+               avg = (avg + value) / 2
+               dict[key] = (min, max, avg, count + 1)
+
 def clear_term():
     print("\x1b[H\x1b[2J")
 
diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record
new file mode 100644 (file)
index 0000000..5ecbb43
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/bash
+perf record -a -e syscalls:sys_enter_futex -e syscalls:sys_exit_futex $@
diff --git a/tools/perf/scripts/python/bin/futex-contention-report b/tools/perf/scripts/python/bin/futex-contention-report
new file mode 100644 (file)
index 0000000..c826813
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/bash
+# description: futext contention measurement
+
+perf trace $@ -s "$PERF_EXEC_PATH"/scripts/python/futex-contention.py
diff --git a/tools/perf/scripts/python/futex-contention.py b/tools/perf/scripts/python/futex-contention.py
new file mode 100644 (file)
index 0000000..11e70a3
--- /dev/null
@@ -0,0 +1,50 @@
+# futex contention
+# (c) 2010, Arnaldo Carvalho de Melo <acme@redhat.com>
+# Licensed under the terms of the GNU GPL License version 2
+#
+# Translation of:
+#
+# http://sourceware.org/systemtap/wiki/WSFutexContention
+#
+# to perf python scripting.
+#
+# Measures futex contention
+
+import os, sys
+sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+from Util import *
+
+process_names = {}
+thread_thislock = {}
+thread_blocktime = {}
+
+lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time
+process_names = {} # long-lived pid-to-execname mapping
+
+def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm,
+                             nr, uaddr, op, val, utime, uaddr2, val3):
+       cmd = op & FUTEX_CMD_MASK
+       if cmd != FUTEX_WAIT:
+               return # we don't care about originators of WAKE events
+
+       process_names[tid] = comm
+       thread_thislock[tid] = uaddr
+       thread_blocktime[tid] = nsecs(s, ns)
+
+def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm,
+                            nr, ret):
+       if thread_blocktime.has_key(tid):
+               elapsed = nsecs(s, ns) - thread_blocktime[tid]
+               add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed)
+               del thread_blocktime[tid]
+               del thread_thislock[tid]
+
+def trace_begin():
+       print "Press control+C to stop and show the summary"
+
+def trace_end():
+       for (tid, lock) in lock_waits:
+               min, max, avg, count = lock_waits[tid, lock]
+               print "%s[%d] lock %x contended %d times, %d avg ns" % \
+                     (process_names[tid], tid, lock, count, avg)
+
index 547cbe9..7a6ec2c 100644 (file)
@@ -17,7 +17,7 @@ from perf_trace_context import *
 from Core import *
 from Util import *
 
-usage = "perf trace -s syscall-counts.py [comm] [interval]\n";
+usage = "perf trace -s sctop.py [comm] [interval]\n";
 
 for_comm = None
 default_interval = 3
index f9c7e3a..c8d81b0 100644 (file)
@@ -12,8 +12,8 @@
 #include "debug.h"
 #include "util.h"
 
-int verbose = 0;
-bool dump_trace = false;
+int verbose;
+bool dump_trace = false, quiet = false;
 
 int eprintf(int level, const char *fmt, ...)
 {
index 7a17ee0..7b51408 100644 (file)
@@ -6,7 +6,7 @@
 #include "event.h"
 
 extern int verbose;
-extern bool dump_trace;
+extern bool quiet, dump_trace;
 
 int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
 void trace_event(event_t *event);