diff options
| -rw-r--r-- | tools/perf/Documentation/perf-record.txt | 4 | ||||
| -rw-r--r-- | tools/perf/builtin-record.c | 8 | ||||
| -rw-r--r-- | tools/perf/builtin-trace.c | 9 | ||||
| -rw-r--r-- | tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py | 18 | ||||
| -rw-r--r-- | tools/perf/scripts/python/bin/futex-contention-record | 2 | ||||
| -rw-r--r-- | tools/perf/scripts/python/bin/futex-contention-report | 4 | ||||
| -rw-r--r-- | tools/perf/scripts/python/futex-contention.py | 50 | ||||
| -rw-r--r-- | tools/perf/scripts/python/sctop.py | 2 | ||||
| -rw-r--r-- | tools/perf/util/debug.c | 4 | ||||
| -rw-r--r-- | tools/perf/util/debug.h | 2 |
10 files changed, 93 insertions, 10 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 3ee27dccfde9..a91f9f9e6e5c 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
| @@ -83,6 +83,10 @@ OPTIONS | |||
| 83 | --call-graph:: | 83 | --call-graph:: |
| 84 | Do call-graph (stack chain/backtrace) recording. | 84 | Do call-graph (stack chain/backtrace) recording. |
| 85 | 85 | ||
| 86 | -q:: | ||
| 87 | --quiet:: | ||
| 88 | Don't print any message, useful for scripting. | ||
| 89 | |||
| 86 | -v:: | 90 | -v:: |
| 87 | --verbose:: | 91 | --verbose:: |
| 88 | Be more verbose (show counter open errors, etc). | 92 | Be more verbose (show counter open errors, etc). |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index ff77b805de71..4e75583ddd6d 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
| @@ -353,7 +353,7 @@ try_again: | |||
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { | 355 | if (read(fd[nr_cpu][counter][thread_index], &read_data, sizeof(read_data)) == -1) { |
| 356 | perror("Unable to read perf file descriptor\n"); | 356 | perror("Unable to read perf file descriptor"); |
| 357 | exit(-1); | 357 | exit(-1); |
| 358 | } | 358 | } |
| 359 | 359 | ||
| @@ -626,7 +626,7 @@ static int __cmd_record(int argc, const char **argv) | |||
| 626 | 626 | ||
| 627 | nr_cpus = read_cpu_map(cpu_list); | 627 | nr_cpus = read_cpu_map(cpu_list); |
| 628 | if (nr_cpus < 1) { | 628 | if (nr_cpus < 1) { |
| 629 | perror("failed to collect number of CPUs\n"); | 629 | perror("failed to collect number of CPUs"); |
| 630 | return -1; | 630 | return -1; |
| 631 | } | 631 | } |
| 632 | 632 | ||
| @@ -761,6 +761,9 @@ static int __cmd_record(int argc, const char **argv) | |||
| 761 | } | 761 | } |
| 762 | } | 762 | } |
| 763 | 763 | ||
| 764 | if (quiet) | ||
| 765 | return 0; | ||
| 766 | |||
| 764 | fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); | 767 | fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); |
| 765 | 768 | ||
| 766 | /* | 769 | /* |
| @@ -820,6 +823,7 @@ static const struct option options[] = { | |||
| 820 | "do call-graph (stack chain/backtrace) recording"), | 823 | "do call-graph (stack chain/backtrace) recording"), |
| 821 | OPT_INCR('v', "verbose", &verbose, | 824 | OPT_INCR('v', "verbose", &verbose, |
| 822 | "be more verbose (show counter open errors, etc)"), | 825 | "be more verbose (show counter open errors, etc)"), |
| 826 | OPT_BOOLEAN('q', "quiet", &quiet, "don't print any message"), | ||
| 823 | OPT_BOOLEAN('s', "stat", &inherit_stat, | 827 | OPT_BOOLEAN('s', "stat", &inherit_stat, |
| 824 | "per thread counts"), | 828 | "per thread counts"), |
| 825 | OPT_BOOLEAN('d', "data", &sample_address, | 829 | OPT_BOOLEAN('d', "data", &sample_address, |
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c index deda1a93131e..2f8df45c4dcb 100644 --- a/tools/perf/builtin-trace.c +++ b/tools/perf/builtin-trace.c | |||
| @@ -625,12 +625,13 @@ int cmd_trace(int argc, const char **argv, const char *prefix __used) | |||
| 625 | dup2(live_pipe[1], 1); | 625 | dup2(live_pipe[1], 1); |
| 626 | close(live_pipe[0]); | 626 | close(live_pipe[0]); |
| 627 | 627 | ||
| 628 | __argv = malloc(5 * sizeof(const char *)); | 628 | __argv = malloc(6 * sizeof(const char *)); |
| 629 | __argv[0] = "/bin/sh"; | 629 | __argv[0] = "/bin/sh"; |
| 630 | __argv[1] = record_script_path; | 630 | __argv[1] = record_script_path; |
| 631 | __argv[2] = "-o"; | 631 | __argv[2] = "-q"; |
| 632 | __argv[3] = "-"; | 632 | __argv[3] = "-o"; |
| 633 | __argv[4] = NULL; | 633 | __argv[4] = "-"; |
| 634 | __argv[5] = NULL; | ||
| 634 | 635 | ||
| 635 | execvp("/bin/sh", (char **)__argv); | 636 | execvp("/bin/sh", (char **)__argv); |
| 636 | exit(-1); | 637 | exit(-1); |
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py index 99ff1b7a0d2c..13cc02b5893a 100644 --- a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py | |||
| @@ -8,6 +8,12 @@ | |||
| 8 | 8 | ||
| 9 | import errno, os | 9 | import errno, os |
| 10 | 10 | ||
| 11 | FUTEX_WAIT = 0 | ||
| 12 | FUTEX_WAKE = 1 | ||
| 13 | FUTEX_PRIVATE_FLAG = 128 | ||
| 14 | FUTEX_CLOCK_REALTIME = 256 | ||
| 15 | FUTEX_CMD_MASK = ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) | ||
| 16 | |||
| 11 | NSECS_PER_SEC = 1000000000 | 17 | NSECS_PER_SEC = 1000000000 |
| 12 | 18 | ||
| 13 | def avg(total, n): | 19 | def avg(total, n): |
| @@ -26,6 +32,18 @@ def nsecs_str(nsecs): | |||
| 26 | str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)), | 32 | str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)), |
| 27 | return str | 33 | return str |
| 28 | 34 | ||
| 35 | def add_stats(dict, key, value): | ||
| 36 | if not dict.has_key(key): | ||
| 37 | dict[key] = (value, value, value, 1) | ||
| 38 | else: | ||
| 39 | min, max, avg, count = dict[key] | ||
| 40 | if value < min: | ||
| 41 | min = value | ||
| 42 | if value > max: | ||
| 43 | max = value | ||
| 44 | avg = (avg + value) / 2 | ||
| 45 | dict[key] = (min, max, avg, count + 1) | ||
| 46 | |||
| 29 | def clear_term(): | 47 | def clear_term(): |
| 30 | print("\x1b[H\x1b[2J") | 48 | print("\x1b[H\x1b[2J") |
| 31 | 49 | ||
diff --git a/tools/perf/scripts/python/bin/futex-contention-record b/tools/perf/scripts/python/bin/futex-contention-record new file mode 100644 index 000000000000..5ecbb433caf4 --- /dev/null +++ b/tools/perf/scripts/python/bin/futex-contention-record | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | 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 index 000000000000..c8268138fb7e --- /dev/null +++ b/tools/perf/scripts/python/bin/futex-contention-report | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # description: futext contention measurement | ||
| 3 | |||
| 4 | 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 index 000000000000..11e70a388d41 --- /dev/null +++ b/tools/perf/scripts/python/futex-contention.py | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | # futex contention | ||
| 2 | # (c) 2010, Arnaldo Carvalho de Melo <acme@redhat.com> | ||
| 3 | # Licensed under the terms of the GNU GPL License version 2 | ||
| 4 | # | ||
| 5 | # Translation of: | ||
| 6 | # | ||
| 7 | # http://sourceware.org/systemtap/wiki/WSFutexContention | ||
| 8 | # | ||
| 9 | # to perf python scripting. | ||
| 10 | # | ||
| 11 | # Measures futex contention | ||
| 12 | |||
| 13 | import os, sys | ||
| 14 | sys.path.append(os.environ['PERF_EXEC_PATH'] + '/scripts/python/Perf-Trace-Util/lib/Perf/Trace') | ||
| 15 | from Util import * | ||
| 16 | |||
| 17 | process_names = {} | ||
| 18 | thread_thislock = {} | ||
| 19 | thread_blocktime = {} | ||
| 20 | |||
| 21 | lock_waits = {} # long-lived stats on (tid,lock) blockage elapsed time | ||
| 22 | process_names = {} # long-lived pid-to-execname mapping | ||
| 23 | |||
| 24 | def syscalls__sys_enter_futex(event, ctxt, cpu, s, ns, tid, comm, | ||
| 25 | nr, uaddr, op, val, utime, uaddr2, val3): | ||
| 26 | cmd = op & FUTEX_CMD_MASK | ||
| 27 | if cmd != FUTEX_WAIT: | ||
| 28 | return # we don't care about originators of WAKE events | ||
| 29 | |||
| 30 | process_names[tid] = comm | ||
| 31 | thread_thislock[tid] = uaddr | ||
| 32 | thread_blocktime[tid] = nsecs(s, ns) | ||
| 33 | |||
| 34 | def syscalls__sys_exit_futex(event, ctxt, cpu, s, ns, tid, comm, | ||
| 35 | nr, ret): | ||
| 36 | if thread_blocktime.has_key(tid): | ||
| 37 | elapsed = nsecs(s, ns) - thread_blocktime[tid] | ||
| 38 | add_stats(lock_waits, (tid, thread_thislock[tid]), elapsed) | ||
| 39 | del thread_blocktime[tid] | ||
| 40 | del thread_thislock[tid] | ||
| 41 | |||
| 42 | def trace_begin(): | ||
| 43 | print "Press control+C to stop and show the summary" | ||
| 44 | |||
| 45 | def trace_end(): | ||
| 46 | for (tid, lock) in lock_waits: | ||
| 47 | min, max, avg, count = lock_waits[tid, lock] | ||
| 48 | print "%s[%d] lock %x contended %d times, %d avg ns" % \ | ||
| 49 | (process_names[tid], tid, lock, count, avg) | ||
| 50 | |||
diff --git a/tools/perf/scripts/python/sctop.py b/tools/perf/scripts/python/sctop.py index 547cbe99de68..7a6ec2c7d8ab 100644 --- a/tools/perf/scripts/python/sctop.py +++ b/tools/perf/scripts/python/sctop.py | |||
| @@ -17,7 +17,7 @@ from perf_trace_context import * | |||
| 17 | from Core import * | 17 | from Core import * |
| 18 | from Util import * | 18 | from Util import * |
| 19 | 19 | ||
| 20 | usage = "perf trace -s syscall-counts.py [comm] [interval]\n"; | 20 | usage = "perf trace -s sctop.py [comm] [interval]\n"; |
| 21 | 21 | ||
| 22 | for_comm = None | 22 | for_comm = None |
| 23 | default_interval = 3 | 23 | default_interval = 3 |
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c index f9c7e3ad1aa7..c8d81b00089d 100644 --- a/tools/perf/util/debug.c +++ b/tools/perf/util/debug.c | |||
| @@ -12,8 +12,8 @@ | |||
| 12 | #include "debug.h" | 12 | #include "debug.h" |
| 13 | #include "util.h" | 13 | #include "util.h" |
| 14 | 14 | ||
| 15 | int verbose = 0; | 15 | int verbose; |
| 16 | bool dump_trace = false; | 16 | bool dump_trace = false, quiet = false; |
| 17 | 17 | ||
| 18 | int eprintf(int level, const char *fmt, ...) | 18 | int eprintf(int level, const char *fmt, ...) |
| 19 | { | 19 | { |
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h index 7a17ee061bcb..7b514082bbaf 100644 --- a/tools/perf/util/debug.h +++ b/tools/perf/util/debug.h | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include "event.h" | 6 | #include "event.h" |
| 7 | 7 | ||
| 8 | extern int verbose; | 8 | extern int verbose; |
| 9 | extern bool dump_trace; | 9 | extern bool quiet, dump_trace; |
| 10 | 10 | ||
| 11 | int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); | 11 | int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); |
| 12 | void trace_event(event_t *event); | 12 | void trace_event(event_t *event); |
