2012-10-08 22:33:40

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [GIT PULL 00/25] perf/core improvements and fixes

Hi Ingo,

Please consider pulling,

- Arnaldo

The following changes since commit 139c0815903de1a7865fe1d6beac5e995fefdf46:

perf hists: Add more helpers for hist entry stat (2012-10-04 13:36:18 -0300)

are available in the git repository at:

git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo

for you to fetch changes up to 7747e2f4fb5fb840994613dd1474c17cddb7836b:

Documentation: add documentation on compiling for Android (2012-10-08 17:44:39 -0300)

----------------------------------------------------------------

perf/core improvements and fixes

. Handle PERF_RECORD_EXIT events in sched and annotate.

. struct machine refactorings to help in top and trace.

. Add on_exit implementation for systems without one, e.g. Android, from
Bernhard Rosenkraenzer.

. Only process events for vcpus of interest, helps handling large number
of events, from David Ahern.

. Cross compiling fixes for Android, from Irina Tirdea.

. Add documentation on compiling for Android, from Irina Tirdea.

. perf diff improvements from Jiri Olsa.

. Target (task/user/cpu/syswide) handling improvements, from Namhyung Kim.

. Add support in 'trace' for tracing workload given by command line, from
Namhyung Kim.

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

----------------------------------------------------------------

Arnaldo Carvalho de Melo (6):
perf tools: Have the page size value available for all tools
perf machine: Introduce find_thread method
perf event: No need to create a thread when handling PERF_RECORD_EXIT
perf annotate: Handle PERF_RECORD_EXIT events
perf sched: Handle PERF_RECORD_EXIT events
perf machine: Carve up event processing specific from perf_tool

Bernhard Rosenkraenzer (1):
perf tools: Add on_exit implementation

David Ahern (4):
perf kvm: Only process events for vcpus of interest
perf kvm: Remove typecast in init_kvm_event_record
perf kvm: Total count is a u64, print as so
perf kvm: Add braces around multi-line statements

Irina Tirdea (2):
perf tools: Update Makefile for Android
Documentation: add documentation on compiling for Android

Jiri Olsa (8):
perf diff: Add -b option for perf diff to display paired entries only
perf diff: Add ratio computation way to compare hist entries
perf diff: Add option to sort entries based on diff computation
perf diff: Add weighted diff computation way to compare hist entries
perf diff: Add -p option to display period values for hist entries
perf diff: Add -F option to display formula for computation
perf diff: Include samples without symbol in overall stats
perf diff: Display empty space for non paired samples

Namhyung Kim (3):
perf trace: Validate target task/user/cpu argument
perf trace: Explicitly enable system-wide mode if no option is given
perf trace: Add support for tracing workload given by command line

Wei Yongjun (1):
perf tools: Remove duplicated include from trace-event-python.c

tools/perf/Documentation/android.txt | 75 ++++
tools/perf/Documentation/perf-diff.txt | 60 +++
tools/perf/Makefile | 33 +-
tools/perf/builtin-annotate.c | 3 +-
tools/perf/builtin-diff.c | 405 +++++++++++++++++++-
tools/perf/builtin-inject.c | 6 +-
tools/perf/builtin-kvm.c | 35 +-
tools/perf/builtin-record.c | 32 ++
tools/perf/builtin-report.c | 4 +-
tools/perf/builtin-sched.c | 3 +-
tools/perf/builtin-script.c | 4 +-
tools/perf/builtin-test.c | 2 -
tools/perf/builtin-top.c | 3 +-
tools/perf/builtin-trace.c | 53 ++-
tools/perf/config/feature-tests.mak | 20 +-
tools/perf/perf.c | 2 +
tools/perf/ui/hist.c | 134 ++++++-
tools/perf/ui/stdio/hist.c | 2 +-
tools/perf/util/build-id.c | 2 +-
tools/perf/util/event.c | 215 +----------
tools/perf/util/event.h | 6 +-
tools/perf/util/evlist.c | 3 -
tools/perf/util/hist.h | 8 +
tools/perf/util/machine.c | 277 +++++++++++++
tools/perf/util/machine.h | 19 +
.../util/scripting-engines/trace-event-python.c | 1 -
tools/perf/util/session.c | 4 +-
tools/perf/util/sort.h | 18 +
tools/perf/util/thread.c | 41 +-
tools/perf/util/thread.h | 2 +
tools/perf/util/trace-event-read.c | 2 -
tools/perf/util/util.c | 2 +
tools/perf/util/util.h | 2 +
33 files changed, 1173 insertions(+), 305 deletions(-)
create mode 100644 tools/perf/Documentation/android.txt
create mode 100644 tools/perf/util/machine.c
create mode 100644 tools/perf/util/machine.h


2012-10-08 22:33:23

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 07/25] perf diff: Add weighted diff computation way to compare hist entries

From: Jiri Olsa <[email protected]>

Adding 'wdiff' as new computation way to compare hist entries.

If specified the 'Weighted diff' column is displayed with value 'd'
computed as:

d = B->period * WEIGHT-A - A->period * WEIGHT-B

- A/B being matching hist entry from first/second file specified
(or perf.data/perf.data.old) respectively.
- period being the hist entry period value
- WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option
behind ':' separator like '-c wdiff:1,2'.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-diff.txt | 15 ++++-
tools/perf/builtin-diff.c | 116 ++++++++++++++++++++++++++++++--
tools/perf/ui/hist.c | 30 +++++++++
tools/perf/util/hist.h | 2 +
tools/perf/util/sort.h | 3 +
5 files changed, 160 insertions(+), 6 deletions(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index cff3d9b..fa413ac 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -78,7 +78,7 @@ OPTIONS

-c::
--compute::
- Differential computation selection - delta,ratio (default is delta).
+ Differential computation selection - delta,ratio,wdiff (default is delta).
If '+' is specified as a first character, the output is sorted based
on the computation results.
See COMPARISON METHODS section for more info.
@@ -110,6 +110,19 @@ with:

- period being the hist entry period value

+wdiff
+~~~~~
+If specified the 'Weighted diff' column is displayed with value 'd' computed as:
+
+ d = B->period * WEIGHT-A - A->period * WEIGHT-B
+
+ - A/B being matching hist entry from first/second file specified
+ (or perf.data/perf.data.old) respectively.
+
+ - period being the hist entry period value
+
+ - WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option
+ behind ':' separator like '-c wdiff:1,2'.

SEE ALSO
--------
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index e13cfac..d78e838 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -27,24 +27,81 @@ static bool show_displacement;
static bool show_baseline_only;
static bool sort_compute;

+static s64 compute_wdiff_w1;
+static s64 compute_wdiff_w2;
+
enum {
COMPUTE_DELTA,
COMPUTE_RATIO,
+ COMPUTE_WEIGHTED_DIFF,
COMPUTE_MAX,
};

const char *compute_names[COMPUTE_MAX] = {
[COMPUTE_DELTA] = "delta",
[COMPUTE_RATIO] = "ratio",
+ [COMPUTE_WEIGHTED_DIFF] = "wdiff",
};

static int compute;

+static int setup_compute_opt_wdiff(char *opt)
+{
+ char *w1_str = opt;
+ char *w2_str;
+
+ int ret = -EINVAL;
+
+ if (!opt)
+ goto out;
+
+ w2_str = strchr(opt, ',');
+ if (!w2_str)
+ goto out;
+
+ *w2_str++ = 0x0;
+ if (!*w2_str)
+ goto out;
+
+ compute_wdiff_w1 = strtol(w1_str, NULL, 10);
+ compute_wdiff_w2 = strtol(w2_str, NULL, 10);
+
+ if (!compute_wdiff_w1 || !compute_wdiff_w2)
+ goto out;
+
+ pr_debug("compute wdiff w1(%" PRId64 ") w2(%" PRId64 ")\n",
+ compute_wdiff_w1, compute_wdiff_w2);
+
+ ret = 0;
+
+ out:
+ if (ret)
+ pr_err("Failed: wrong weight data, use 'wdiff:w1,w2'\n");
+
+ return ret;
+}
+
+static int setup_compute_opt(char *opt)
+{
+ if (compute == COMPUTE_WEIGHTED_DIFF)
+ return setup_compute_opt_wdiff(opt);
+
+ if (opt) {
+ pr_err("Failed: extra option specified '%s'", opt);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int setup_compute(const struct option *opt, const char *str,
int unset __maybe_unused)
{
int *cp = (int *) opt->value;
+ char *cstr = (char *) str;
+ char buf[50];
unsigned i;
+ char *option;

if (!str) {
*cp = COMPUTE_DELTA;
@@ -53,19 +110,37 @@ static int setup_compute(const struct option *opt, const char *str,

if (*str == '+') {
sort_compute = true;
- str++;
+ cstr = (char *) ++str;
if (!*str)
return 0;
}

+ option = strchr(str, ':');
+ if (option) {
+ unsigned len = option++ - str;
+
+ /*
+ * The str data are not writeable, so we need
+ * to use another buffer.
+ */
+
+ /* No option value is longer. */
+ if (len >= sizeof(buf))
+ return -EINVAL;
+
+ strncpy(buf, str, len);
+ buf[len] = 0x0;
+ cstr = buf;
+ }
+
for (i = 0; i < COMPUTE_MAX; i++)
- if (!strcmp(str, compute_names[i])) {
+ if (!strcmp(cstr, compute_names[i])) {
*cp = i;
- return 0;
+ return setup_compute_opt(option);
}

pr_err("Failed: '%s' is not computation method "
- "(use 'delta' or 'ratio').\n", str);
+ "(use 'delta','ratio' or 'wdiff')\n", str);
return -EINVAL;
}

@@ -97,6 +172,23 @@ double perf_diff__compute_ratio(struct hist_entry *he)
return he->diff.period_ratio;
}

+s64 perf_diff__compute_wdiff(struct hist_entry *he)
+{
+ struct hist_entry *pair = he->pair;
+ u64 new_period = he->stat.period;
+ u64 old_period = pair ? pair->stat.period : 0;
+
+ he->diff.computed = true;
+
+ if (!pair)
+ he->diff.wdiff = 0;
+ else
+ he->diff.wdiff = new_period * compute_wdiff_w2 -
+ old_period * compute_wdiff_w1;
+
+ return he->diff.wdiff;
+}
+
static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period)
{
@@ -275,6 +367,9 @@ static void hists__precompute(struct hists *hists)
case COMPUTE_RATIO:
perf_diff__compute_ratio(he);
break;
+ case COMPUTE_WEIGHTED_DIFF:
+ perf_diff__compute_wdiff(he);
+ break;
default:
BUG_ON(1);
}
@@ -310,6 +405,13 @@ hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,

return cmp_doubles(l, r);
}
+ case COMPUTE_WEIGHTED_DIFF:
+ {
+ s64 l = left->diff.wdiff;
+ s64 r = right->diff.wdiff;
+
+ return r - l;
+ }
default:
BUG_ON(1);
}
@@ -434,7 +536,8 @@ static const struct option options[] = {
"Show position displacement relative to baseline"),
OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
"Show only items with match in baseline"),
- OPT_CALLBACK('c', "compute", &compute, "delta,ratio (default delta)",
+ OPT_CALLBACK('c', "compute", &compute,
+ "delta,ratio,wdiff:w1,w2 (default delta)",
"Entries differential computation selection",
setup_compute),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
@@ -475,6 +578,9 @@ static void ui_init(void)
case COMPUTE_RATIO:
perf_hpp__column_enable(PERF_HPP__RATIO, true);
break;
+ case COMPUTE_WEIGHTED_DIFF:
+ perf_hpp__column_enable(PERF_HPP__WEIGHTED_DIFF, true);
+ break;
default:
BUG_ON(1);
};
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 659f2a2..522b4ec 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -286,6 +286,35 @@ static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
return scnprintf(hpp->buf, hpp->size, fmt, buf);
}

+static int hpp__header_wdiff(struct perf_hpp *hpp)
+{
+ const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+
+ return scnprintf(hpp->buf, hpp->size, fmt, "Weighted diff");
+}
+
+static int hpp__width_wdiff(struct perf_hpp *hpp __maybe_unused)
+{
+ return 14;
+}
+
+static int hpp__entry_wdiff(struct perf_hpp *hpp, struct hist_entry *he)
+{
+ const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+ char buf[32] = " ";
+ s64 wdiff;
+
+ if (he->diff.computed)
+ wdiff = he->diff.wdiff;
+ else
+ wdiff = perf_diff__compute_wdiff(he);
+
+ if (wdiff != 0)
+ scnprintf(buf, sizeof(buf), "%14ld", wdiff);
+
+ return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
static int hpp__header_displ(struct perf_hpp *hpp)
{
return scnprintf(hpp->buf, hpp->size, "Displ.");
@@ -332,6 +361,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
{ .cond = false, HPP__PRINT_FNS(period) },
{ .cond = false, HPP__PRINT_FNS(delta) },
{ .cond = false, HPP__PRINT_FNS(ratio) },
+ { .cond = false, HPP__PRINT_FNS(wdiff) },
{ .cond = false, HPP__PRINT_FNS(displ) }
};

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a7ea28a..ce76f36 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -142,6 +142,7 @@ enum {
PERF_HPP__PERIOD,
PERF_HPP__DELTA,
PERF_HPP__RATIO,
+ PERF_HPP__WEIGHTED_DIFF,
PERF_HPP__DISPL,

PERF_HPP__MAX_INDEX
@@ -207,4 +208,5 @@ unsigned int hists__sort_list_width(struct hists *self);

double perf_diff__compute_delta(struct hist_entry *he);
double perf_diff__compute_ratio(struct hist_entry *he);
+s64 perf_diff__compute_wdiff(struct hist_entry *he);
#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 337aeef..13761d8 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -63,6 +63,9 @@ struct hist_entry_diff {

/* PERF_HPP__RATIO */
double period_ratio;
+
+ /* HISTC_WEIGHTED_DIFF */
+ s64 wdiff;
};

/**
--
1.7.9.2.358.g22243

2012-10-08 22:33:35

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 03/25] perf trace: Add support for tracing workload given by command line

From: Namhyung Kim <[email protected]>

Now perf trace is able to trace specified workload by forking it like
perf record does. And also finish the tracing if the workload quits or
gets SIGINT.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-trace.c | 43 ++++++++++++++++++++++++++++++++++++-------
1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index da1183f..4e9320b 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -52,6 +52,13 @@ struct trace {
struct perf_record_opts opts;
};

+static bool done = false;
+
+static void sig_handler(int sig __maybe_unused)
+{
+ done = true;
+}
+
static int trace__read_syscall_info(struct trace *trace, int id)
{
char tp_name[128];
@@ -189,11 +196,12 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
return 0;
}

-static int trace__run(struct trace *trace)
+static int trace__run(struct trace *trace, int argc, const char **argv)
{
struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
struct perf_evsel *evsel;
int err = -1, i, nr_events = 0, before;
+ const bool forks = argc > 0;

if (evlist == NULL) {
printf("Not enough memory to run!\n");
@@ -214,6 +222,17 @@ static int trace__run(struct trace *trace)

perf_evlist__config_attrs(evlist, &trace->opts);

+ signal(SIGCHLD, sig_handler);
+ signal(SIGINT, sig_handler);
+
+ if (forks) {
+ err = perf_evlist__prepare_workload(evlist, &trace->opts, argv);
+ if (err < 0) {
+ printf("Couldn't run the workload!\n");
+ goto out_delete_evlist;
+ }
+ }
+
err = perf_evlist__open(evlist);
if (err < 0) {
printf("Couldn't create the events: %s\n", strerror(errno));
@@ -227,6 +246,10 @@ static int trace__run(struct trace *trace)
}

perf_evlist__enable(evlist);
+
+ if (forks)
+ perf_evlist__start_workload(evlist);
+
again:
before = nr_events;

@@ -272,8 +295,15 @@ again:
}
}

- if (nr_events == before)
+ if (nr_events == before) {
+ if (done)
+ goto out_delete_evlist;
+
poll(evlist->pollfd, evlist->nr_fds, -1);
+ }
+
+ if (done)
+ perf_evlist__disable(evlist);

goto again;

@@ -286,7 +316,8 @@ out:
int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
{
const char * const trace_usage[] = {
- "perf trace [<options>]",
+ "perf trace [<options>] [<command>]",
+ "perf trace [<options>] -- <command> [<options>]",
NULL
};
struct trace trace = {
@@ -326,8 +357,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
char bf[BUFSIZ];

argc = parse_options(argc, argv, trace_options, trace_usage, 0);
- if (argc)
- usage_with_options(trace_usage, trace_options);

err = perf_target__validate(&trace.opts.target);
if (err) {
@@ -343,8 +372,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
return err;
}

- if (perf_target__none(&trace.opts.target))
+ if (!argc && perf_target__none(&trace.opts.target))
trace.opts.target.system_wide = true;

- return trace__run(&trace);
+ return trace__run(&trace, argc, argv);
}
--
1.7.9.2.358.g22243

2012-10-08 22:33:44

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 10/25] perf diff: Include samples without symbol in overall stats

From: Jiri Olsa <[email protected]>

Currently we omit samples without symbols. This way we get different and
confusing numbers for samples than from report command.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-diff.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index dd9c064..b4db513 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -269,7 +269,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
return -1;
}

- if (al.filtered || al.sym == NULL)
+ if (al.filtered)
return 0;

if (hists__add_entry(&evsel->hists, &al, sample->period)) {
--
1.7.9.2.358.g22243

2012-10-08 22:33:48

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 24/25] perf tools: Update Makefile for Android

From: Irina Tirdea <[email protected]>

For cross-compiling on Android, some specific changes are needed in
the Makefile.

Update the Makefile to support cross-compiling for Android.
The original ideea for this was send by Bernhard Rosenkraenzer in
https://lkml.org/lkml/2012/8/23/316, but this is a rewrite.

Changes:
() support bionic in addition to glibc
() remove rt and pthread libraries that do not exist in Android
() use $(CFLAGS) when detecting initial compiler flags. This is needed
when setting CFLAGS as an argument of make (e.g. for setting --sysroot).
() include perf's local directory when building for Android to be able to find
relative paths if using --sysroot (e.g.: ../../include/linux/perf_event.h)

Signed-off-by: Irina Tirdea <[email protected]>
Cc: Bernhard Rosenkraenzer <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 25 +++++++++++++++++++------
tools/perf/config/feature-tests.mak | 9 +++++++++
2 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index a7d8745..318bec8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -155,15 +155,15 @@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__powerpc__

-include config/feature-tests.mak

-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -fstack-protector-all),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -fstack-protector-all),y)
CFLAGS := $(CFLAGS) -fstack-protector-all
endif

-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wstack-protector),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wstack-protector),y)
CFLAGS := $(CFLAGS) -Wstack-protector
endif

-ifeq ($(call try-cc,$(SOURCE_HELLO),-Werror -Wvolatile-register-var),y)
+ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var),y)
CFLAGS := $(CFLAGS) -Wvolatile-register-var
endif

@@ -172,6 +172,13 @@ endif
BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
BASIC_LDFLAGS =

+ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS)),y)
+ BIONIC := 1
+ EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
+ EXTLIBS := $(filter-out -lpthread,$(EXTLIBS))
+ BASIC_CFLAGS += -I.
+endif
+
# Guard against environment variables
BUILTIN_OBJS =
LIB_H =
@@ -469,12 +476,18 @@ else
FLAGS_LIBELF=$(ALL_CFLAGS) $(ALL_LDFLAGS) $(EXTLIBS)
ifneq ($(call try-cc,$(SOURCE_LIBELF),$(FLAGS_LIBELF)),y)
FLAGS_GLIBC=$(ALL_CFLAGS) $(ALL_LDFLAGS)
- ifneq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
- msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
- else
+ ifeq ($(call try-cc,$(SOURCE_GLIBC),$(FLAGS_GLIBC)),y)
+ LIBC_SUPPORT := 1
+ endif
+ ifeq ($(BIONIC),1)
+ LIBC_SUPPORT := 1
+ endif
+ ifeq ($(LIBC_SUPPORT),1)
NO_LIBELF := 1
NO_DWARF := 1
NO_DEMANGLE := 1
+ else
+ msg := $(error No gnu/libc-version.h found, please install glibc-dev[el]/glibc-static);
endif
else
FLAGS_DWARF=$(ALL_CFLAGS) -ldw -lelf $(ALL_LDFLAGS) $(EXTLIBS)
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index eaeb0fd..3ef5ec9 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -43,6 +43,15 @@ int main(void)
}
endef

+define SOURCE_BIONIC
+#include <android/api-level.h>
+
+int main(void)
+{
+ return __ANDROID_API__;
+}
+endef
+
define SOURCE_ELF_MMAP
#include <libelf.h>
int main(void)
--
1.7.9.2.358.g22243

2012-10-08 22:34:09

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 23/25] perf tools: Add on_exit implementation

From: Bernhard Rosenkraenzer <[email protected]>

on_exit() is only available in new versions of glibc.
It is not implemented in Bionic and will lead to linking errors when
compiling for Android.

Implement a wrapper for on_exit using atexit.

The implementation for on_exit is the one sent by Bernhard Rosenkraenzer in
https://lkml.org/lkml/2012/8/23/316. The configuration part from the Makefile
is different than the one from the original patch.

Signed-off-by: Bernhard Rosenkraenzer <[email protected]>
Signed-off-by: Irina Tirdea <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Irina Tirdea <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 6 ++++++
tools/perf/builtin-record.c | 32 ++++++++++++++++++++++++++++++++
tools/perf/config/feature-tests.mak | 11 ++++++++++-
3 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index d80a333..a7d8745 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -753,6 +753,12 @@ ifndef NO_STRLCPY
endif
endif

+ifndef NO_ON_EXIT
+ ifeq ($(call try-cc,$(SOURCE_ON_EXIT),),y)
+ BASIC_CFLAGS += -DHAVE_ON_EXIT
+ endif
+endif
+
ifndef NO_BACKTRACE
ifeq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
BASIC_CFLAGS += -DBACKTRACE_SUPPORT
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index e9231659..73b5d7f 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -31,6 +31,38 @@
#include <sched.h>
#include <sys/mman.h>

+#ifndef HAVE_ON_EXIT
+#ifndef ATEXIT_MAX
+#define ATEXIT_MAX 32
+#endif
+static int __on_exit_count = 0;
+typedef void (*on_exit_func_t) (int, void *);
+static on_exit_func_t __on_exit_funcs[ATEXIT_MAX];
+static void *__on_exit_args[ATEXIT_MAX];
+static int __exitcode = 0;
+static void __handle_on_exit_funcs(void);
+static int on_exit(on_exit_func_t function, void *arg);
+#define exit(x) (exit)(__exitcode = (x))
+
+static int on_exit(on_exit_func_t function, void *arg)
+{
+ if (__on_exit_count == ATEXIT_MAX)
+ return -ENOMEM;
+ else if (__on_exit_count == 0)
+ atexit(__handle_on_exit_funcs);
+ __on_exit_funcs[__on_exit_count] = function;
+ __on_exit_args[__on_exit_count++] = arg;
+ return 0;
+}
+
+static void __handle_on_exit_funcs(void)
+{
+ int i;
+ for (i = 0; i < __on_exit_count; i++)
+ __on_exit_funcs[i] (__exitcode, __on_exit_args[i]);
+}
+#endif
+
enum write_mode_t {
WRITE_FORCE,
WRITE_APPEND
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 4add41b..eaeb0fd 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -203,4 +203,13 @@ int main(void)
return audit_open();
}
endef
-endif
\ No newline at end of file
+endif
+
+define SOURCE_ON_EXIT
+#include <stdio.h>
+
+int main(void)
+{
+ return on_exit(NULL, NULL);
+}
+endef
--
1.7.9.2.358.g22243

2012-10-08 22:34:29

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 22/25] perf kvm: Add braces around multi-line statements

From: David Ahern <[email protected]>

Multi-line statements should have braces. Improves readability.

Signed-off-by: David Ahern <[email protected]>
Cc: Dong Hao <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Xiao Guangrong <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-kvm.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 72a302e..836c82f 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -369,9 +369,10 @@ static struct kvm_event *find_create_kvm_event(struct perf_kvm *kvm,
BUG_ON(key->key == INVALID_KEY);

head = &kvm->kvm_events_cache[kvm_events_hash_fn(key->key)];
- list_for_each_entry(event, head, hash_entry)
+ list_for_each_entry(event, head, hash_entry) {
if (event->key.key == key->key && event->key.info == key->info)
return event;
+ }

event = kvm_alloc_init_event(key);
if (!event)
@@ -610,13 +611,15 @@ static void sort_result(struct perf_kvm *kvm)
int vcpu = kvm->trace_vcpu;
struct kvm_event *event;

- for (i = 0; i < EVENTS_CACHE_SIZE; i++)
- list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry)
+ for (i = 0; i < EVENTS_CACHE_SIZE; i++) {
+ list_for_each_entry(event, &kvm->kvm_events_cache[i], hash_entry) {
if (event_is_valid(event, vcpu)) {
update_total_count(kvm, event);
insert_to_result(&kvm->result, event,
kvm->compare, vcpu);
}
+ }
+ }
}

/* returns left most element of result, and erase it */
--
1.7.9.2.358.g22243

2012-10-08 22:34:50

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 11/25] perf diff: Display empty space for non paired samples

From: Jiri Olsa <[email protected]>

Currently in 'Baseline' and 'Period Base' columns zero values are
displayed in case no pair is found for the sample. This might be
confusing, using empty space instead.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/ui/hist.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 305eb79..4f5f475 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -179,7 +179,10 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he)
{
double percent = baseline_percent(he);

- return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+ if (he->pair)
+ return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent);
+ else
+ return scnprintf(hpp->buf, hpp->size, " ");
}

static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
@@ -187,7 +190,10 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he)
double percent = baseline_percent(he);
const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%";

- return scnprintf(hpp->buf, hpp->size, fmt, percent);
+ if (he->pair || symbol_conf.field_sep)
+ return scnprintf(hpp->buf, hpp->size, fmt, percent);
+ else
+ return scnprintf(hpp->buf, hpp->size, " ");
}

static int hpp__header_samples(struct perf_hpp *hpp)
--
1.7.9.2.358.g22243

2012-10-08 22:34:48

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 20/25] perf kvm: Remove typecast in init_kvm_event_record

From: David Ahern <[email protected]>

Not needed after changing i to unsigned int.

Signed-off-by: David Ahern <[email protected]>
Cc: Dong Hao <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Xiao Guangrong <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-kvm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index b98095e..8416754 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -313,9 +313,9 @@ struct vcpu_event_record {

static void init_kvm_event_record(struct perf_kvm *kvm)
{
- int i;
+ unsigned int i;

- for (i = 0; i < (int)EVENTS_CACHE_SIZE; i++)
+ for (i = 0; i < EVENTS_CACHE_SIZE; i++)
INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
}

--
1.7.9.2.358.g22243

2012-10-08 22:34:46

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 19/25] perf kvm: Only process events for vcpus of interest

From: David Ahern <[email protected]>

Minimizing processing overhead for each sample - which becomes important
for the upcoming live mode when it has to deal with 100+k events per
second.

Signed-off-by: David Ahern <[email protected]>
Cc: Dong Hao <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Xiao Guangrong <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-kvm.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 260abc5..b98095e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -416,7 +416,10 @@ static double kvm_event_rel_stddev(int vcpu_id, struct kvm_event *event)
static bool update_kvm_event(struct kvm_event *event, int vcpu_id,
u64 time_diff)
{
- kvm_update_event_stats(&event->total, time_diff);
+ if (vcpu_id == -1) {
+ kvm_update_event_stats(&event->total, time_diff);
+ return true;
+ }

if (!kvm_event_expand(event, vcpu_id))
return false;
@@ -432,6 +435,12 @@ static bool handle_end_event(struct perf_kvm *kvm,
{
struct kvm_event *event;
u64 time_begin, time_diff;
+ int vcpu;
+
+ if (kvm->trace_vcpu == -1)
+ vcpu = -1;
+ else
+ vcpu = vcpu_record->vcpu_id;

event = vcpu_record->last_event;
time_begin = vcpu_record->start_time;
@@ -461,7 +470,7 @@ static bool handle_end_event(struct perf_kvm *kvm,
BUG_ON(timestamp < time_begin);

time_diff = timestamp - time_begin;
- return update_kvm_event(event, vcpu_record->vcpu_id, time_diff);
+ return update_kvm_event(event, vcpu, time_diff);
}

static
@@ -498,6 +507,11 @@ static bool handle_kvm_event(struct perf_kvm *kvm,
if (!vcpu_record)
return true;

+ /* only process events for vcpus user cares about */
+ if ((kvm->trace_vcpu != -1) &&
+ (kvm->trace_vcpu != vcpu_record->vcpu_id))
+ return true;
+
if (kvm->events_ops->is_begin_event(evsel, sample, &key))
return handle_begin_event(kvm, vcpu_record, &key, sample->time);

--
1.7.9.2.358.g22243

2012-10-08 22:35:36

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 14/25] perf event: No need to create a thread when handling PERF_RECORD_EXIT

From: Arnaldo Carvalho de Melo <[email protected]>

When we were processing a PERF_RECORD_EXIT event we first used
machine__findnew_thread for both the thread exiting and for its parent,
only to use just the thread struct associated with the one exiting, and
to just delete it.

If it existed, i.e. not created at this very moment in
machine__findnew_thread, it will be moved to the machine->dead_threads
linked list, because we may have hist_entries pointing to it, but if it
was created just do be deleted, it will just sit there with no
references at all.

Use the new machine__find_thread() method so that if it is not there, we
don't create it.

As a bonus the parent thread will also not be created at this point.

Create process_fork() and process_exit() helpers to use this and make
the builtins use it instead of the generic process_task(), ditched by
this patch.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-annotate.c | 2 +-
tools/perf/builtin-diff.c | 4 ++--
tools/perf/builtin-inject.c | 6 +++---
tools/perf/builtin-report.c | 4 ++--
tools/perf/builtin-sched.c | 2 +-
tools/perf/builtin-script.c | 4 ++--
tools/perf/util/build-id.c | 2 +-
tools/perf/util/event.c | 30 ++++++++++++++++++++++--------
tools/perf/util/event.h | 6 +++++-
9 files changed, 39 insertions(+), 21 deletions(-)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 9ea3854..cca2fb5 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -246,7 +246,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.comm = perf_event__process_comm,
- .fork = perf_event__process_task,
+ .fork = perf_event__process_fork,
.ordered_samples = true,
.ordering_requires_timestamps = true,
},
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index b4db513..380683d 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -285,8 +285,8 @@ static struct perf_tool tool = {
.sample = diff__process_sample_event,
.mmap = perf_event__process_mmap,
.comm = perf_event__process_comm,
- .exit = perf_event__process_task,
- .fork = perf_event__process_task,
+ .exit = perf_event__process_exit,
+ .fork = perf_event__process_fork,
.lost = perf_event__process_lost,
.ordered_samples = true,
.ordering_requires_timestamps = true,
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 4688bea..386a5c0 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -102,14 +102,14 @@ static int perf_event__repipe_mmap(struct perf_tool *tool,
return err;
}

-static int perf_event__repipe_task(struct perf_tool *tool,
+static int perf_event__repipe_fork(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine)
{
int err;

- err = perf_event__process_task(tool, event, sample, machine);
+ err = perf_event__process_fork(tool, event, sample, machine);
perf_event__repipe(tool, event, sample, machine);

return err;
@@ -227,7 +227,7 @@ static int __cmd_inject(struct perf_inject *inject)
if (inject->build_ids) {
inject->tool.sample = perf_event__inject_buildid;
inject->tool.mmap = perf_event__repipe_mmap;
- inject->tool.fork = perf_event__repipe_task;
+ inject->tool.fork = perf_event__repipe_fork;
inject->tool.tracing_data = perf_event__repipe_tracing_data;
}

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index a61725d..5104a40 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -556,8 +556,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.comm = perf_event__process_comm,
- .exit = perf_event__process_task,
- .fork = perf_event__process_task,
+ .exit = perf_event__process_exit,
+ .fork = perf_event__process_fork,
.lost = perf_event__process_lost,
.read = process_read_event,
.attr = perf_event__process_attr,
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 3488ead..3a25cd8 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1672,7 +1672,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
.sample = perf_sched__process_tracepoint_sample,
.comm = perf_event__process_comm,
.lost = perf_event__process_lost,
- .fork = perf_event__process_task,
+ .fork = perf_event__process_fork,
.ordered_samples = true,
},
.cmp_pid = LIST_HEAD_INIT(sched.cmp_pid),
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index fb96250..04ceb07 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -520,8 +520,8 @@ static struct perf_tool perf_script = {
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.comm = perf_event__process_comm,
- .exit = perf_event__process_task,
- .fork = perf_event__process_task,
+ .exit = perf_event__process_exit,
+ .fork = perf_event__process_fork,
.attr = perf_event__process_attr,
.event_type = perf_event__process_event_type,
.tracing_data = perf_event__process_tracing_data,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 8e3a740..6a63999 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -64,7 +64,7 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
struct perf_tool build_id__mark_dso_hit_ops = {
.sample = build_id__mark_dso_hit,
.mmap = perf_event__process_mmap,
- .fork = perf_event__process_task,
+ .fork = perf_event__process_fork,
.exit = perf_event__exit_del_thread,
.attr = perf_event__process_attr,
.build_id = perf_event__process_build_id,
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 6715b19..eaaee22 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,6 +1,7 @@
#include <linux/types.h>
#include "event.h"
#include "debug.h"
+#include "machine.h"
#include "sort.h"
#include "string.h"
#include "strlist.h"
@@ -702,10 +703,10 @@ size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
event->fork.ppid, event->fork.ptid);
}

-int perf_event__process_task(struct perf_tool *tool __maybe_unused,
+int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
- struct machine *machine)
+ struct machine *machine)
{
struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
@@ -713,11 +714,6 @@ int perf_event__process_task(struct perf_tool *tool __maybe_unused,
if (dump_trace)
perf_event__fprintf_task(event, stdout);

- if (event->header.type == PERF_RECORD_EXIT) {
- machine__remove_thread(machine, thread);
- return 0;
- }
-
if (thread == NULL || parent == NULL ||
thread__fork(thread, parent) < 0) {
dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
@@ -727,6 +723,22 @@ int perf_event__process_task(struct perf_tool *tool __maybe_unused,
return 0;
}

+int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample __maybe_unused,
+ struct machine *machine)
+{
+ struct thread *thread = machine__find_thread(machine, event->fork.tid);
+
+ if (dump_trace)
+ perf_event__fprintf_task(event, stdout);
+
+ if (thread != NULL)
+ machine__remove_thread(machine, thread);
+
+ return 0;
+}
+
size_t perf_event__fprintf(union perf_event *event, FILE *fp)
{
size_t ret = fprintf(fp, "PERF_RECORD_%s",
@@ -761,8 +773,10 @@ int perf_event__process(struct perf_tool *tool, union perf_event *event,
perf_event__process_mmap(tool, event, sample, machine);
break;
case PERF_RECORD_FORK:
+ perf_event__process_fork(tool, event, sample, machine);
+ break;
case PERF_RECORD_EXIT:
- perf_event__process_task(tool, event, sample, machine);
+ perf_event__process_exit(tool, event, sample, machine);
break;
case PERF_RECORD_LOST:
perf_event__process_lost(tool, event, sample, machine);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 21b99e7..da97aff 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -191,7 +191,11 @@ int perf_event__process_mmap(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
-int perf_event__process_task(struct perf_tool *tool,
+int perf_event__process_fork(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine);
+int perf_event__process_exit(struct perf_tool *tool,
union perf_event *event,
struct perf_sample *sample,
struct machine *machine);
--
1.7.9.2.358.g22243

2012-10-08 22:35:41

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 09/25] perf diff: Add -F option to display formula for computation

From: Jiri Olsa <[email protected]>

Adding -F option to display the formula for specified computation.

This is mainly to facilitate debugging, but can be useful anyway.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-diff.txt | 4 ++
tools/perf/builtin-diff.c | 67 +++++++++++++++++++++++++++++++-
tools/perf/ui/hist.c | 24 +++++++++++-
tools/perf/ui/stdio/hist.c | 2 +-
tools/perf/util/hist.h | 2 +
5 files changed, 96 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 21cc2ef..194f37d 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -87,6 +87,10 @@ OPTIONS
--period::
Show period values for both compared hist entries.

+-F::
+--formula::
+ Show formula for given computation.
+
COMPARISON METHODS
------------------
delta
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 2411dd1..dd9c064 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -25,6 +25,7 @@ static char diff__default_sort_order[] = "dso,symbol";
static bool force;
static bool show_displacement;
static bool show_period;
+static bool show_formula;
static bool show_baseline_only;
static bool sort_compute;

@@ -190,6 +191,62 @@ s64 perf_diff__compute_wdiff(struct hist_entry *he)
return he->diff.wdiff;
}

+static int formula_delta(struct hist_entry *he, char *buf, size_t size)
+{
+ struct hist_entry *pair = he->pair;
+
+ if (!pair)
+ return -1;
+
+ return scnprintf(buf, size,
+ "(%" PRIu64 " * 100 / %" PRIu64 ") - "
+ "(%" PRIu64 " * 100 / %" PRIu64 ")",
+ he->stat.period, he->hists->stats.total_period,
+ pair->stat.period, pair->hists->stats.total_period);
+}
+
+static int formula_ratio(struct hist_entry *he, char *buf, size_t size)
+{
+ struct hist_entry *pair = he->pair;
+ double new_period = he->stat.period;
+ double old_period = pair ? pair->stat.period : 0;
+
+ if (!pair)
+ return -1;
+
+ return scnprintf(buf, size, "%.0F / %.0F", new_period, old_period);
+}
+
+static int formula_wdiff(struct hist_entry *he, char *buf, size_t size)
+{
+ struct hist_entry *pair = he->pair;
+ u64 new_period = he->stat.period;
+ u64 old_period = pair ? pair->stat.period : 0;
+
+ if (!pair)
+ return -1;
+
+ return scnprintf(buf, size,
+ "(%" PRIu64 " * " "%" PRId64 ") - (%" PRIu64 " * " "%" PRId64 ")",
+ new_period, compute_wdiff_w2, old_period, compute_wdiff_w1);
+}
+
+int perf_diff__formula(char *buf, size_t size, struct hist_entry *he)
+{
+ switch (compute) {
+ case COMPUTE_DELTA:
+ return formula_delta(he, buf, size);
+ case COMPUTE_RATIO:
+ return formula_ratio(he, buf, size);
+ case COMPUTE_WEIGHTED_DIFF:
+ return formula_wdiff(he, buf, size);
+ default:
+ BUG_ON(1);
+ }
+
+ return -1;
+}
+
static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period)
{
@@ -543,6 +600,8 @@ static const struct option options[] = {
setup_compute),
OPT_BOOLEAN('p', "period", &show_period,
"Show period values."),
+ OPT_BOOLEAN('F', "formula", &show_formula,
+ "Show formula."),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -571,7 +630,10 @@ static void ui_init(void)
/* No overhead column. */
perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);

- /* Display baseline/delta/ratio/displacement/periods columns. */
+ /*
+ * Display baseline/delta/ratio/displacement/
+ * formula/periods columns.
+ */
perf_hpp__column_enable(PERF_HPP__BASELINE, true);

switch (compute) {
@@ -591,6 +653,9 @@ static void ui_init(void)
if (show_displacement)
perf_hpp__column_enable(PERF_HPP__DISPL, true);

+ if (show_formula)
+ perf_hpp__column_enable(PERF_HPP__FORMULA, true);
+
if (show_period) {
perf_hpp__column_enable(PERF_HPP__PERIOD, true);
perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 2fadaff..305eb79 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -359,6 +359,27 @@ static int hpp__entry_displ(struct perf_hpp *hpp,
return scnprintf(hpp->buf, hpp->size, fmt, buf);
}

+static int hpp__header_formula(struct perf_hpp *hpp)
+{
+ const char *fmt = symbol_conf.field_sep ? "%s" : "%70s";
+
+ return scnprintf(hpp->buf, hpp->size, fmt, "Formula");
+}
+
+static int hpp__width_formula(struct perf_hpp *hpp __maybe_unused)
+{
+ return 70;
+}
+
+static int hpp__entry_formula(struct perf_hpp *hpp, struct hist_entry *he)
+{
+ const char *fmt = symbol_conf.field_sep ? "%s" : "%-70s";
+ char buf[96] = " ";
+
+ perf_diff__formula(buf, sizeof(buf), he);
+ return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
#define HPP__COLOR_PRINT_FNS(_name) \
.header = hpp__header_ ## _name, \
.width = hpp__width_ ## _name, \
@@ -383,7 +404,8 @@ struct perf_hpp_fmt perf_hpp__format[] = {
{ .cond = false, HPP__PRINT_FNS(delta) },
{ .cond = false, HPP__PRINT_FNS(ratio) },
{ .cond = false, HPP__PRINT_FNS(wdiff) },
- { .cond = false, HPP__PRINT_FNS(displ) }
+ { .cond = false, HPP__PRINT_FNS(displ) },
+ { .cond = false, HPP__PRINT_FNS(formula) }
};

#undef HPP__COLOR_PRINT_FNS
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index fbd4e32..f0ee204 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -342,7 +342,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
const char *sep = symbol_conf.field_sep;
const char *col_width = symbol_conf.col_width_list_str;
int idx, nr_rows = 0;
- char bf[64];
+ char bf[96];
struct perf_hpp dummy_hpp = {
.buf = bf,
.size = sizeof(bf),
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 5604791..c751624 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -145,6 +145,7 @@ enum {
PERF_HPP__RATIO,
PERF_HPP__WEIGHTED_DIFF,
PERF_HPP__DISPL,
+ PERF_HPP__FORMULA,

PERF_HPP__MAX_INDEX
};
@@ -210,4 +211,5 @@ unsigned int hists__sort_list_width(struct hists *self);
double perf_diff__compute_delta(struct hist_entry *he);
double perf_diff__compute_ratio(struct hist_entry *he);
s64 perf_diff__compute_wdiff(struct hist_entry *he);
+int perf_diff__formula(char *buf, size_t size, struct hist_entry *he);
#endif /* __PERF_HIST_H */
--
1.7.9.2.358.g22243

2012-10-08 22:36:08

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 12/25] perf tools: Have the page size value available for all tools

From: Arnaldo Carvalho de Melo <[email protected]>

Its such a common need that we might as well have a global with that
value.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-test.c | 2 --
tools/perf/perf.c | 2 ++
tools/perf/util/evlist.c | 3 ---
tools/perf/util/session.c | 4 +---
tools/perf/util/trace-event-read.c | 2 --
tools/perf/util/util.c | 2 ++
tools/perf/util/util.h | 2 ++
7 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 484f26c..e2d9872d 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -35,7 +35,6 @@ static int test__vmlinux_matches_kallsyms(void)
struct map *kallsyms_map, *vmlinux_map;
struct machine kallsyms, vmlinux;
enum map_type type = MAP__FUNCTION;
- long page_size = sysconf(_SC_PAGE_SIZE);
struct ref_reloc_sym ref_reloc_sym = { .name = "_stext", };

/*
@@ -1007,7 +1006,6 @@ static void segfault_handler(int sig __maybe_unused,

static int __test__rdpmc(void)
{
- long page_size = sysconf(_SC_PAGE_SIZE);
volatile int tmp = 0;
u64 i, loops = 1000;
int n;
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 6d50eb0..d480d8a 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -440,6 +440,8 @@ int main(int argc, const char **argv)
{
const char *cmd;

+ page_size = sysconf(_SC_PAGE_SIZE);
+
cmd = perf_extract_argv0_path(argv[0]);
if (!cmd)
cmd = "perf-help";
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 186b877..a41dc4a 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -325,8 +325,6 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id)

union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
{
- /* XXX Move this to perf.c, making it generally available */
- unsigned int page_size = sysconf(_SC_PAGE_SIZE);
struct perf_mmap *md = &evlist->mmap[idx];
unsigned int head = perf_mmap__read_head(md);
unsigned int old = md->prev;
@@ -528,7 +526,6 @@ out_unmap:
int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
bool overwrite)
{
- unsigned int page_size = sysconf(_SC_PAGE_SIZE);
struct perf_evsel *evsel;
const struct cpu_map *cpus = evlist->cpus;
const struct thread_map *threads = evlist->threads;
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8cdd232..15abe40 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -1375,15 +1375,13 @@ int __perf_session__process_events(struct perf_session *session,
{
u64 head, page_offset, file_offset, file_pos, progress_next;
int err, mmap_prot, mmap_flags, map_idx = 0;
- size_t page_size, mmap_size;
+ size_t mmap_size;
char *buf, *mmaps[8];
union perf_event *event;
uint32_t size;

perf_tool__fill_defaults(tool);

- page_size = sysconf(_SC_PAGESIZE);
-
page_offset = page_size * (data_offset / page_size);
file_offset = page_offset;
head = data_offset - page_offset;
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c
index 719ed74..3741572 100644
--- a/tools/perf/util/trace-event-read.c
+++ b/tools/perf/util/trace-event-read.c
@@ -47,8 +47,6 @@ int file_bigendian;
int host_bigendian;
static int long_size;

-static unsigned long page_size;
-
static ssize_t calc_data_size;
static bool repipe;

diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 9966459..637b5cc 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -10,6 +10,8 @@
/*
* XXX We need to find a better place for these things...
*/
+unsigned int page_size;
+
bool perf_host = true;
bool perf_guest = false;

diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 70fa70b..a6b83f8 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -263,4 +263,6 @@ char *rtrim(char *s);

void dump_stack(void);

+extern unsigned int page_size;
+
#endif
--
1.7.9.2.358.g22243

2012-10-08 22:33:21

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 25/25] Documentation: add documentation on compiling for Android

From: Irina Tirdea <[email protected]>

Add documentation for cross-compiling on Android including:

() instructions on how to set the Android NDK environment
() how to cross-compile perf for Android
() how to install on an Android device/emulator, set the runtime
environment and run it

Signed-off-by: Irina Tirdea <[email protected]>
Cc: David Ahern <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Pekka Enberg <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Steven Rostedt <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/android.txt | 75 ++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
create mode 100644 tools/perf/Documentation/android.txt

diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
new file mode 100644
index 0000000..a39dbbb
--- /dev/null
+++ b/tools/perf/Documentation/android.txt
@@ -0,0 +1,75 @@
+How to compile perf for Android
+=========================================
+
+I. Set the Android NDK environment
+------------------------------------------------
+
+(a). Use the Android NDK
+------------------------------------------------
+1. You need to download and install the Android Native Development Kit (NDK).
+Set the NDK variable to point to the path where you installed the NDK:
+ export NDK=/path/to/android-ndk
+
+2. Set cross-compiling environment variables for NDK toolchain and sysroot.
+For arm:
+ export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi-
+ export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm
+For x86:
+ export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android-
+ export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86
+
+This method is not working for Android NDK versions up to Revision 8b.
+perf uses some bionic enhancements that are not included in these NDK versions.
+You can use method (b) described below instead.
+
+(b). Use the Android source tree
+-----------------------------------------------
+1. Download the master branch of the Android source tree.
+Set the environment for the target you want using:
+ source build/envsetup.sh
+ lunch
+
+2. Build your own NDK sysroot to contain latest bionic changes and set the
+NDK sysroot environment variable.
+ cd ${ANDROID_BUILD_TOP}/ndk
+For arm:
+ ./build/tools/build-ndk-sysroot.sh --abi=arm
+ export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-arm
+For x86:
+ ./build/tools/build-ndk-sysroot.sh --abi=x86
+ export NDK_SYSROOT=${ANDROID_BUILD_TOP}/ndk/build/platforms/android-3/arch-x86
+
+3. Set the NDK toolchain environment variable.
+For arm:
+ export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/arm-linux-androideabi-
+For x86:
+ export NDK_TOOLCHAIN=${ANDROID_TOOLCHAIN}/i686-linux-android-
+
+II. Compile perf for Android
+------------------------------------------------
+You need to run make with the NDK toolchain and sysroot defined above:
+ make CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}"
+
+III. Install perf
+-----------------------------------------------
+You need to connect to your Android device/emulator using adb.
+Install perf using:
+ adb push perf /data/perf
+
+If you also want to use perf-archive you need busybox tools for Android.
+For installing perf-archive, you first need to replace #!/bin/bash with #!/system/bin/sh:
+ sed 's/#!\/bin\/bash/#!\/system\/bin\/sh/g' perf-archive >> /tmp/perf-archive
+ chmod +x /tmp/perf-archive
+ adb push /tmp/perf-archive /data/perf-archive
+
+IV. Environment settings for running perf
+------------------------------------------------
+Some perf features need environment variables to run properly.
+You need to set these before running perf on the target:
+ adb shell
+ # PERF_PAGER=cat
+
+IV. Run perf
+------------------------------------------------
+Run perf on your device/emulator to which you previously connected using adb:
+ # ./data/perf
--
1.7.9.2.358.g22243

2012-10-08 22:33:19

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 18/25] perf tools: Remove duplicated include from trace-event-python.c

From: Wei Yongjun <[email protected]>

Remove duplicated include.

dpatch engine is used to auto generate this patch.
(https://github.com/weiyj/dpatch)

Signed-off-by: Wei Yongjun <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Wei Yongjun <[email protected]>
Link: http://lkml.kernel.org/r/CAPgLHd8fz+TznMVRdhzPb45WtZQXhVxadRQcLxUC4O9aX+SUbA@mail.gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
.../util/scripting-engines/trace-event-python.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index 730c663..14683df 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -32,7 +32,6 @@
#include "../event.h"
#include "../thread.h"
#include "../trace-event.h"
-#include "../evsel.h"

PyMODINIT_FUNC initperf_trace_context(void);

--
1.7.9.2.358.g22243

2012-10-08 22:33:17

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 15/25] perf annotate: Handle PERF_RECORD_EXIT events

From: Arnaldo Carvalho de Melo <[email protected]>

Noticed annotate wasn't handling those events while introducing
perf_event__process_{fork,exit}.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-annotate.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index cca2fb5..690fa9a 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -246,6 +246,7 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
.sample = process_sample_event,
.mmap = perf_event__process_mmap,
.comm = perf_event__process_comm,
+ .exit = perf_event__process_exit,
.fork = perf_event__process_fork,
.ordered_samples = true,
.ordering_requires_timestamps = true,
--
1.7.9.2.358.g22243

2012-10-08 22:33:15

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 16/25] perf sched: Handle PERF_RECORD_EXIT events

From: Arnaldo Carvalho de Melo <[email protected]>

Noticed sched wasn't handling those events while introducing
perf_event__process_{fork,exit}.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-sched.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 3a25cd8..30e5336 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -1672,6 +1672,7 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
.sample = perf_sched__process_tracepoint_sample,
.comm = perf_event__process_comm,
.lost = perf_event__process_lost,
+ .exit = perf_event__process_exit,
.fork = perf_event__process_fork,
.ordered_samples = true,
},
--
1.7.9.2.358.g22243

2012-10-08 22:38:31

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 06/25] perf diff: Add option to sort entries based on diff computation

From: Jiri Olsa <[email protected]>

Adding support to sort hist entries based on the outcome of selected
computation. It's now possible to specify '+' as a first character of
'-c' option value to make such sort.

Example:

$ perf diff -c ratio -b
# Event 'cache-misses'
#
# Baseline Ratio Shared Object Symbol
# ........ .............. ................. ................................
#
19.64% 0.69 [kernel.kallsyms] [k] clear_page
0.30% 0.17 [kernel.kallsyms] [k] mm_alloc
0.04% 0.20 [kernel.kallsyms] [k] kmem_cache_alloc

$ perf diff -c +ratio -b
# Event 'cache-misses'
#
# Baseline Ratio Shared Object Symbol
# ........ .............. ................. ................................
#
19.64% 0.69 [kernel.kallsyms] [k] clear_page
0.04% 0.20 [kernel.kallsyms] [k] kmem_cache_alloc
0.30% 0.17 [kernel.kallsyms] [k] mm_alloc

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-diff.txt | 2 +
tools/perf/builtin-diff.c | 137 ++++++++++++++++++++++++++++++++
tools/perf/ui/hist.c | 29 +++----
tools/perf/util/hist.h | 2 +
tools/perf/util/sort.h | 15 ++++
5 files changed, 167 insertions(+), 18 deletions(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 8fff061..cff3d9b 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -79,6 +79,8 @@ OPTIONS
-c::
--compute::
Differential computation selection - delta,ratio (default is delta).
+ If '+' is specified as a first character, the output is sorted based
+ on the computation results.
See COMPARISON METHODS section for more info.

COMPARISON METHODS
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index e90c06a..e13cfac 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -25,6 +25,7 @@ static char diff__default_sort_order[] = "dso,symbol";
static bool force;
static bool show_displacement;
static bool show_baseline_only;
+static bool sort_compute;

enum {
COMPUTE_DELTA,
@@ -50,6 +51,13 @@ static int setup_compute(const struct option *opt, const char *str,
return 0;
}

+ if (*str == '+') {
+ sort_compute = true;
+ str++;
+ if (!*str)
+ return 0;
+ }
+
for (i = 0; i < COMPUTE_MAX; i++)
if (!strcmp(str, compute_names[i])) {
*cp = i;
@@ -61,6 +69,34 @@ static int setup_compute(const struct option *opt, const char *str,
return -EINVAL;
}

+static double get_period_percent(struct hist_entry *he, u64 period)
+{
+ u64 total = he->hists->stats.total_period;
+ return (period * 100.0) / total;
+}
+
+double perf_diff__compute_delta(struct hist_entry *he)
+{
+ struct hist_entry *pair = he->pair;
+ double new_percent = get_period_percent(he, he->stat.period);
+ double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0;
+
+ he->diff.period_ratio_delta = new_percent - old_percent;
+ he->diff.computed = true;
+ return he->diff.period_ratio_delta;
+}
+
+double perf_diff__compute_ratio(struct hist_entry *he)
+{
+ struct hist_entry *pair = he->pair;
+ double new_period = he->stat.period;
+ double old_period = pair ? pair->stat.period : 0;
+
+ he->diff.computed = true;
+ he->diff.period_ratio = pair ? (new_period / old_period) : 0;
+ return he->diff.period_ratio;
+}
+
static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period)
{
@@ -223,6 +259,102 @@ static void hists__baseline_only(struct hists *hists)
}
}

+static void hists__precompute(struct hists *hists)
+{
+ struct rb_node *next = rb_first(&hists->entries);
+
+ while (next != NULL) {
+ struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+ next = rb_next(&he->rb_node);
+
+ switch (compute) {
+ case COMPUTE_DELTA:
+ perf_diff__compute_delta(he);
+ break;
+ case COMPUTE_RATIO:
+ perf_diff__compute_ratio(he);
+ break;
+ default:
+ BUG_ON(1);
+ }
+ }
+}
+
+static int64_t cmp_doubles(double l, double r)
+{
+ if (l > r)
+ return -1;
+ else if (l < r)
+ return 1;
+ else
+ return 0;
+}
+
+static int64_t
+hist_entry__cmp_compute(struct hist_entry *left, struct hist_entry *right,
+ int c)
+{
+ switch (c) {
+ case COMPUTE_DELTA:
+ {
+ double l = left->diff.period_ratio_delta;
+ double r = right->diff.period_ratio_delta;
+
+ return cmp_doubles(l, r);
+ }
+ case COMPUTE_RATIO:
+ {
+ double l = left->diff.period_ratio;
+ double r = right->diff.period_ratio;
+
+ return cmp_doubles(l, r);
+ }
+ default:
+ BUG_ON(1);
+ }
+
+ return 0;
+}
+
+static void insert_hist_entry_by_compute(struct rb_root *root,
+ struct hist_entry *he,
+ int c)
+{
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct hist_entry *iter;
+
+ while (*p != NULL) {
+ parent = *p;
+ iter = rb_entry(parent, struct hist_entry, rb_node);
+ if (hist_entry__cmp_compute(he, iter, c) < 0)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
+ }
+
+ rb_link_node(&he->rb_node, parent, p);
+ rb_insert_color(&he->rb_node, root);
+}
+
+static void hists__compute_resort(struct hists *hists)
+{
+ struct rb_root tmp = RB_ROOT;
+ struct rb_node *next = rb_first(&hists->entries);
+
+ while (next != NULL) {
+ struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+ next = rb_next(&he->rb_node);
+
+ rb_erase(&he->rb_node, &hists->entries);
+ insert_hist_entry_by_compute(&tmp, he, compute);
+ }
+
+ hists->entries = tmp;
+}
+
static void hists__process(struct hists *old, struct hists *new)
{
hists__match(old, new);
@@ -230,6 +362,11 @@ static void hists__process(struct hists *old, struct hists *new)
if (show_baseline_only)
hists__baseline_only(new);

+ if (sort_compute) {
+ hists__precompute(new);
+ hists__compute_resort(new);
+ }
+
hists__fprintf(new, true, 0, 0, stdout);
}

diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 1b633a4..659f2a2 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -242,24 +242,15 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused)

static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
- struct hists *pair_hists = pair ? pair->hists : NULL;
- struct hists *hists = he->hists;
- u64 old_total, new_total;
- double old_percent = 0, new_percent = 0;
- double diff;
const char *fmt = symbol_conf.field_sep ? "%s" : "%7.7s";
char buf[32] = " ";
+ double diff;

- old_total = pair_hists ? pair_hists->stats.total_period : 0;
- if (old_total > 0 && pair)
- old_percent = 100.0 * pair->stat.period / old_total;
-
- new_total = hists->stats.total_period;
- if (new_total > 0)
- new_percent = 100.0 * he->stat.period / new_total;
+ if (he->diff.computed)
+ diff = he->diff.period_ratio_delta;
+ else
+ diff = perf_diff__compute_delta(he);

- diff = new_percent - old_percent;
if (fabs(diff) >= 0.01)
scnprintf(buf, sizeof(buf), "%+4.2F%%", diff);

@@ -280,12 +271,14 @@ static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)

static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
{
- struct hist_entry *pair = he->pair;
- double new_period = he->stat.period;
- double old_period = pair ? pair->stat.period : 0;
- double ratio = pair ? new_period / old_period : 0;
const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
char buf[32] = " ";
+ double ratio;
+
+ if (he->diff.computed)
+ ratio = he->diff.period_ratio;
+ else
+ ratio = perf_diff__compute_ratio(he);

if (ratio > 0.0)
scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 7e4d4c2..a7ea28a 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -205,4 +205,6 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist __maybe_unused,

unsigned int hists__sort_list_width(struct hists *self);

+double perf_diff__compute_delta(struct hist_entry *he);
+double perf_diff__compute_ratio(struct hist_entry *he);
#endif /* __PERF_HIST_H */
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 5786f32..337aeef 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -52,6 +52,19 @@ struct he_stat {
u32 nr_events;
};

+struct hist_entry_diff {
+ bool computed;
+
+ /* PERF_HPP__DISPL */
+ int displacement;
+
+ /* PERF_HPP__DELTA */
+ double period_ratio_delta;
+
+ /* PERF_HPP__RATIO */
+ double period_ratio;
+};
+
/**
* struct hist_entry - histogram entry
*
@@ -67,6 +80,8 @@ struct hist_entry {
u64 ip;
s32 cpu;

+ struct hist_entry_diff diff;
+
/* XXX These two should move to some tree widget lib */
u16 row_offset;
u16 nr_rows;
--
1.7.9.2.358.g22243

2012-10-08 22:38:57

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 08/25] perf diff: Add -p option to display period values for hist entries

From: Jiri Olsa <[email protected]>

Adding -p option to show period values for both compared hist entries.
Showing hist column PERF_HPP__PERIOD and newly added hist column
PERF_HPP__PERIOD_BASELINE.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-diff.txt | 4 ++++
tools/perf/builtin-diff.c | 10 +++++++++-
tools/perf/ui/hist.c | 21 +++++++++++++++++++++
tools/perf/util/hist.h | 1 +
4 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index fa413ac..21cc2ef 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -83,6 +83,10 @@ OPTIONS
on the computation results.
See COMPARISON METHODS section for more info.

+-p::
+--period::
+ Show period values for both compared hist entries.
+
COMPARISON METHODS
------------------
delta
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index d78e838..2411dd1 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -24,6 +24,7 @@ static char const *input_old = "perf.data.old",
static char diff__default_sort_order[] = "dso,symbol";
static bool force;
static bool show_displacement;
+static bool show_period;
static bool show_baseline_only;
static bool sort_compute;

@@ -540,6 +541,8 @@ static const struct option options[] = {
"delta,ratio,wdiff:w1,w2 (default delta)",
"Entries differential computation selection",
setup_compute),
+ OPT_BOOLEAN('p', "period", &show_period,
+ "Show period values."),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -568,7 +571,7 @@ static void ui_init(void)
/* No overhead column. */
perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);

- /* Display baseline/delta/ratio/displacement columns. */
+ /* Display baseline/delta/ratio/displacement/periods columns. */
perf_hpp__column_enable(PERF_HPP__BASELINE, true);

switch (compute) {
@@ -587,6 +590,11 @@ static void ui_init(void)

if (show_displacement)
perf_hpp__column_enable(PERF_HPP__DISPL, true);
+
+ if (show_period) {
+ perf_hpp__column_enable(PERF_HPP__PERIOD, true);
+ perf_hpp__column_enable(PERF_HPP__PERIOD_BASELINE, true);
+ }
}

int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 522b4ec..2fadaff 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -228,6 +228,26 @@ static int hpp__entry_period(struct perf_hpp *hpp, struct hist_entry *he)
return scnprintf(hpp->buf, hpp->size, fmt, he->stat.period);
}

+static int hpp__header_period_baseline(struct perf_hpp *hpp)
+{
+ const char *fmt = symbol_conf.field_sep ? "%s" : "%12s";
+
+ return scnprintf(hpp->buf, hpp->size, fmt, "Period Base");
+}
+
+static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused)
+{
+ return 12;
+}
+
+static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he)
+{
+ struct hist_entry *pair = he->pair;
+ u64 period = pair ? pair->stat.period : 0;
+ const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64;
+
+ return scnprintf(hpp->buf, hpp->size, fmt, period);
+}
static int hpp__header_delta(struct perf_hpp *hpp)
{
const char *fmt = symbol_conf.field_sep ? "%s" : "%7s";
@@ -359,6 +379,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
{ .cond = false, HPP__COLOR_PRINT_FNS(overhead_guest_us) },
{ .cond = false, HPP__PRINT_FNS(samples) },
{ .cond = false, HPP__PRINT_FNS(period) },
+ { .cond = false, HPP__PRINT_FNS(period_baseline) },
{ .cond = false, HPP__PRINT_FNS(delta) },
{ .cond = false, HPP__PRINT_FNS(ratio) },
{ .cond = false, HPP__PRINT_FNS(wdiff) },
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ce76f36..5604791 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -140,6 +140,7 @@ enum {
PERF_HPP__OVERHEAD_GUEST_US,
PERF_HPP__SAMPLES,
PERF_HPP__PERIOD,
+ PERF_HPP__PERIOD_BASELINE,
PERF_HPP__DELTA,
PERF_HPP__RATIO,
PERF_HPP__WEIGHTED_DIFF,
--
1.7.9.2.358.g22243

2012-10-08 22:38:53

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 05/25] perf diff: Add ratio computation way to compare hist entries

From: Jiri Olsa <[email protected]>

Adding -c option to select computation method with the current 'Delta'
computation as default. Current possible values are of this option are:
'delta' and 'ratio'.

Adding 'ratio' as new computation way to compare hist entries. If
specified the 'Ratio' column is displayed with value 'r' computed as:

r = A->period / B->period

with:
- A/B being matching hist entry from first/second file specified
(or perf.data/perf.data.old) respectively.
- period being the hist entry period value

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-diff.txt | 33 ++++++++++++++++++++
tools/perf/builtin-diff.c | 52 ++++++++++++++++++++++++++++++--
tools/perf/ui/hist.c | 28 +++++++++++++++++
tools/perf/util/hist.h | 1 +
4 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 6ce9585..8fff061 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -76,6 +76,39 @@ OPTIONS
--baseline-only::
Show only items with match in baseline.

+-c::
+--compute::
+ Differential computation selection - delta,ratio (default is delta).
+ See COMPARISON METHODS section for more info.
+
+COMPARISON METHODS
+------------------
+delta
+~~~~~
+If specified the 'Delta' column is displayed with value 'd' computed as:
+
+ d = A->period_percent - B->period_percent
+
+with:
+ - A/B being matching hist entry from first/second file specified
+ (or perf.data/perf.data.old) respectively.
+
+ - period_percent being the % of the hist entry period value within
+ single data file
+
+ratio
+~~~~~
+If specified the 'Ratio' column is displayed with value 'r' computed as:
+
+ r = A->period / B->period
+
+with:
+ - A/B being matching hist entry from first/second file specified
+ (or perf.data/perf.data.old) respectively.
+
+ - period being the hist entry period value
+
+
SEE ALSO
--------
linkperf:perf-record[1]
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 1063c31..e90c06a 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -26,6 +26,41 @@ static bool force;
static bool show_displacement;
static bool show_baseline_only;

+enum {
+ COMPUTE_DELTA,
+ COMPUTE_RATIO,
+ COMPUTE_MAX,
+};
+
+const char *compute_names[COMPUTE_MAX] = {
+ [COMPUTE_DELTA] = "delta",
+ [COMPUTE_RATIO] = "ratio",
+};
+
+static int compute;
+
+static int setup_compute(const struct option *opt, const char *str,
+ int unset __maybe_unused)
+{
+ int *cp = (int *) opt->value;
+ unsigned i;
+
+ if (!str) {
+ *cp = COMPUTE_DELTA;
+ return 0;
+ }
+
+ for (i = 0; i < COMPUTE_MAX; i++)
+ if (!strcmp(str, compute_names[i])) {
+ *cp = i;
+ return 0;
+ }
+
+ pr_err("Failed: '%s' is not computation method "
+ "(use 'delta' or 'ratio').\n", str);
+ return -EINVAL;
+}
+
static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period)
{
@@ -262,6 +297,9 @@ static const struct option options[] = {
"Show position displacement relative to baseline"),
OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
"Show only items with match in baseline"),
+ OPT_CALLBACK('c', "compute", &compute, "delta,ratio (default delta)",
+ "Entries differential computation selection",
+ setup_compute),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
@@ -290,9 +328,19 @@ static void ui_init(void)
/* No overhead column. */
perf_hpp__column_enable(PERF_HPP__OVERHEAD, false);

- /* Display baseline/delta/displacement columns. */
+ /* Display baseline/delta/ratio/displacement columns. */
perf_hpp__column_enable(PERF_HPP__BASELINE, true);
- perf_hpp__column_enable(PERF_HPP__DELTA, true);
+
+ switch (compute) {
+ case COMPUTE_DELTA:
+ perf_hpp__column_enable(PERF_HPP__DELTA, true);
+ break;
+ case COMPUTE_RATIO:
+ perf_hpp__column_enable(PERF_HPP__RATIO, true);
+ break;
+ default:
+ BUG_ON(1);
+ };

if (show_displacement)
perf_hpp__column_enable(PERF_HPP__DISPL, true);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index f5a1e4f..1b633a4 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -266,6 +266,33 @@ static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he)
return scnprintf(hpp->buf, hpp->size, fmt, buf);
}

+static int hpp__header_ratio(struct perf_hpp *hpp)
+{
+ const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+
+ return scnprintf(hpp->buf, hpp->size, fmt, "Ratio");
+}
+
+static int hpp__width_ratio(struct perf_hpp *hpp __maybe_unused)
+{
+ return 14;
+}
+
+static int hpp__entry_ratio(struct perf_hpp *hpp, struct hist_entry *he)
+{
+ struct hist_entry *pair = he->pair;
+ double new_period = he->stat.period;
+ double old_period = pair ? pair->stat.period : 0;
+ double ratio = pair ? new_period / old_period : 0;
+ const char *fmt = symbol_conf.field_sep ? "%s" : "%14s";
+ char buf[32] = " ";
+
+ if (ratio > 0.0)
+ scnprintf(buf, sizeof(buf), "%+14.6F", ratio);
+
+ return scnprintf(hpp->buf, hpp->size, fmt, buf);
+}
+
static int hpp__header_displ(struct perf_hpp *hpp)
{
return scnprintf(hpp->buf, hpp->size, "Displ.");
@@ -311,6 +338,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
{ .cond = false, HPP__PRINT_FNS(samples) },
{ .cond = false, HPP__PRINT_FNS(period) },
{ .cond = false, HPP__PRINT_FNS(delta) },
+ { .cond = false, HPP__PRINT_FNS(ratio) },
{ .cond = false, HPP__PRINT_FNS(displ) }
};

diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 66cb31f..7e4d4c2 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -141,6 +141,7 @@ enum {
PERF_HPP__SAMPLES,
PERF_HPP__PERIOD,
PERF_HPP__DELTA,
+ PERF_HPP__RATIO,
PERF_HPP__DISPL,

PERF_HPP__MAX_INDEX
--
1.7.9.2.358.g22243

2012-10-08 22:39:24

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 04/25] perf diff: Add -b option for perf diff to display paired entries only

From: Jiri Olsa <[email protected]>

Adding -b option to perf diff command to display only entries with match
in the baseline.

Signed-off-by: Jiri Olsa <[email protected]>
Cc: Andi Kleen <[email protected]>
Cc: Corey Ashford <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-diff.txt | 4 ++++
tools/perf/builtin-diff.c | 31 +++++++++++++++++++++++++++++--
2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index ab7f667..6ce9585 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -72,6 +72,10 @@ OPTIONS
--symfs=<directory>::
Look for files with symbols relative to this directory.

+-b::
+--baseline-only::
+ Show only items with match in baseline.
+
SEE ALSO
--------
linkperf:perf-record[1]
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index a0b531c..1063c31 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -24,6 +24,7 @@ static char const *input_old = "perf.data.old",
static char diff__default_sort_order[] = "dso,symbol";
static bool force;
static bool show_displacement;
+static bool show_baseline_only;

static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period)
@@ -172,6 +173,31 @@ static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name)
}
}

+static void hists__baseline_only(struct hists *hists)
+{
+ struct rb_node *next = rb_first(&hists->entries);
+
+ while (next != NULL) {
+ struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node);
+
+ next = rb_next(&he->rb_node);
+ if (!he->pair) {
+ rb_erase(&he->rb_node, &hists->entries);
+ hist_entry__free(he);
+ }
+ }
+}
+
+static void hists__process(struct hists *old, struct hists *new)
+{
+ hists__match(old, new);
+
+ if (show_baseline_only)
+ hists__baseline_only(new);
+
+ hists__fprintf(new, true, 0, 0, stdout);
+}
+
static int __cmd_diff(void)
{
int ret, i;
@@ -213,8 +239,7 @@ static int __cmd_diff(void)

first = false;

- hists__match(&evsel_old->hists, &evsel->hists);
- hists__fprintf(&evsel->hists, true, 0, 0, stdout);
+ hists__process(&evsel_old->hists, &evsel->hists);
}

out_delete:
@@ -235,6 +260,8 @@ static const struct option options[] = {
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('M', "displacement", &show_displacement,
"Show position displacement relative to baseline"),
+ OPT_BOOLEAN('b', "baseline-only", &show_baseline_only,
+ "Show only items with match in baseline"),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
--
1.7.9.2.358.g22243

2012-10-08 22:33:12

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 02/25] perf trace: Explicitly enable system-wide mode if no option is given

From: Namhyung Kim <[email protected]>

When no target cpu/user/task option is given, perf trace will do its job
system wide for all online cpus. Make it explicit to reduce possible
confusion when reading code.

No functional changes intended.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-trace.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index f01fa6f..da1183f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -343,5 +343,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
return err;
}

+ if (perf_target__none(&trace.opts.target))
+ trace.opts.target.system_wide = true;
+
return trace__run(&trace);
}
--
1.7.9.2.358.g22243

2012-10-08 22:33:10

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 01/25] perf trace: Validate target task/user/cpu argument

From: Namhyung Kim <[email protected]>

Those target options are mutually exclusive so check it before setting
up target thread/cpu maps.

Signed-off-by: Namhyung Kim <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-trace.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index dec8ced..f01fa6f 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -323,14 +323,21 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_END()
};
int err;
+ char bf[BUFSIZ];

argc = parse_options(argc, argv, trace_options, trace_usage, 0);
if (argc)
usage_with_options(trace_usage, trace_options);

+ err = perf_target__validate(&trace.opts.target);
+ if (err) {
+ perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
+ printf("%s", bf);
+ return err;
+ }
+
err = perf_target__parse_uid(&trace.opts.target);
if (err) {
- char bf[BUFSIZ];
perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
printf("%s", bf);
return err;
--
1.7.9.2.358.g22243

2012-10-08 22:40:00

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 13/25] perf machine: Introduce find_thread method

From: Arnaldo Carvalho de Melo <[email protected]>

There are cases where we want just to find a thread if it exists
already, so provide a method for that.

While doing that start moving 'machine' methods to a separate file.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Makefile | 2 ++
tools/perf/util/machine.c | 57 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/machine.h | 11 +++++++++
tools/perf/util/thread.c | 41 +-------------------------------
tools/perf/util/thread.h | 2 ++
5 files changed, 73 insertions(+), 40 deletions(-)
create mode 100644 tools/perf/util/machine.c
create mode 100644 tools/perf/util/machine.h

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index f9126f8..d80a333 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -300,6 +300,7 @@ LIB_H += util/evlist.h
LIB_H += util/exec_cmd.h
LIB_H += util/types.h
LIB_H += util/levenshtein.h
+LIB_H += util/machine.h
LIB_H += util/map.h
LIB_H += util/parse-options.h
LIB_H += util/parse-events.h
@@ -383,6 +384,7 @@ LIB_OBJS += $(OUTPUT)util/header.o
LIB_OBJS += $(OUTPUT)util/callchain.o
LIB_OBJS += $(OUTPUT)util/values.o
LIB_OBJS += $(OUTPUT)util/debug.o
+LIB_OBJS += $(OUTPUT)util/machine.o
LIB_OBJS += $(OUTPUT)util/map.o
LIB_OBJS += $(OUTPUT)util/pstack.o
LIB_OBJS += $(OUTPUT)util/session.o
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
new file mode 100644
index 0000000..9d36d7e
--- /dev/null
+++ b/tools/perf/util/machine.c
@@ -0,0 +1,57 @@
+#include "machine.h"
+#include "map.h"
+#include "thread.h"
+#include <stdbool.h>
+
+static struct thread *__machine__findnew_thread(struct machine *machine, pid_t pid,
+ bool create)
+{
+ struct rb_node **p = &machine->threads.rb_node;
+ struct rb_node *parent = NULL;
+ struct thread *th;
+
+ /*
+ * Font-end cache - PID lookups come in blocks,
+ * so most of the time we dont have to look up
+ * the full rbtree:
+ */
+ if (machine->last_match && machine->last_match->pid == pid)
+ return machine->last_match;
+
+ while (*p != NULL) {
+ parent = *p;
+ th = rb_entry(parent, struct thread, rb_node);
+
+ if (th->pid == pid) {
+ machine->last_match = th;
+ return th;
+ }
+
+ if (pid < th->pid)
+ p = &(*p)->rb_left;
+ else
+ p = &(*p)->rb_right;
+ }
+
+ if (!create)
+ return NULL;
+
+ th = thread__new(pid);
+ if (th != NULL) {
+ rb_link_node(&th->rb_node, parent, p);
+ rb_insert_color(&th->rb_node, &machine->threads);
+ machine->last_match = th;
+ }
+
+ return th;
+}
+
+struct thread *machine__findnew_thread(struct machine *machine, pid_t pid)
+{
+ return __machine__findnew_thread(machine, pid, true);
+}
+
+struct thread *machine__find_thread(struct machine *machine, pid_t pid)
+{
+ return __machine__findnew_thread(machine, pid, false);
+}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
new file mode 100644
index 0000000..54df0cd
--- /dev/null
+++ b/tools/perf/util/machine.h
@@ -0,0 +1,11 @@
+#ifndef __PERF_MACHINE_H
+#define __PERF_MACHINE_H
+
+#include <sys/types.h>
+
+struct thread;
+struct machine;
+
+struct thread *machine__find_thread(struct machine *machine, pid_t pid);
+
+#endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index fb4b7ea..fe3bb1e 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,7 +7,7 @@
#include "util.h"
#include "debug.h"

-static struct thread *thread__new(pid_t pid)
+struct thread *thread__new(pid_t pid)
{
struct thread *self = zalloc(sizeof(*self));

@@ -61,45 +61,6 @@ static size_t thread__fprintf(struct thread *self, FILE *fp)
map_groups__fprintf(&self->mg, verbose, fp);
}

-struct thread *machine__findnew_thread(struct machine *self, pid_t pid)
-{
- struct rb_node **p = &self->threads.rb_node;
- struct rb_node *parent = NULL;
- struct thread *th;
-
- /*
- * Font-end cache - PID lookups come in blocks,
- * so most of the time we dont have to look up
- * the full rbtree:
- */
- if (self->last_match && self->last_match->pid == pid)
- return self->last_match;
-
- while (*p != NULL) {
- parent = *p;
- th = rb_entry(parent, struct thread, rb_node);
-
- if (th->pid == pid) {
- self->last_match = th;
- return th;
- }
-
- if (pid < th->pid)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
-
- th = thread__new(pid);
- if (th != NULL) {
- rb_link_node(&th->rb_node, parent, p);
- rb_insert_color(&th->rb_node, &self->threads);
- self->last_match = th;
- }
-
- return th;
-}
-
void thread__insert_map(struct thread *self, struct map *map)
{
map_groups__fixup_overlappings(&self->mg, map, verbose, stderr);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index f66610b..f2fa17c 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -3,6 +3,7 @@

#include <linux/rbtree.h>
#include <unistd.h>
+#include <sys/types.h>
#include "symbol.h"

struct thread {
@@ -22,6 +23,7 @@ struct thread {

struct machine;

+struct thread *thread__new(pid_t pid);
void thread__delete(struct thread *self);

int thread__set_comm(struct thread *self, const char *comm);
--
1.7.9.2.358.g22243

2012-10-08 22:40:19

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 17/25] perf machine: Carve up event processing specific from perf_tool

From: Arnaldo Carvalho de Melo <[email protected]>

The perf_tool vtable expects methods that receive perf_tool and
perf_sample entries, but for tools not interested in doing any special
processing on non PERF_RECORD_SAMPLE events, like 'perf top', and for
those not using perf_session, like 'perf trace', they were using
perf_event__process passing tool and sample paramenters that were just
not used.

Provide 'machine' methods for this purpose and make the perf_event
ones use them.

Cc: David Ahern <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Jiri Olsa <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Stephane Eranian <[email protected]>
Link: http://lkml.kernel.org/n/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-top.c | 3 +-
tools/perf/util/event.c | 211 +++----------------------------------------
tools/perf/util/machine.c | 220 +++++++++++++++++++++++++++++++++++++++++++++
tools/perf/util/machine.h | 8 ++
4 files changed, 242 insertions(+), 200 deletions(-)

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ff6db80..fb9da71 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -26,6 +26,7 @@
#include "util/color.h"
#include "util/evlist.h"
#include "util/evsel.h"
+#include "util/machine.h"
#include "util/session.h"
#include "util/symbol.h"
#include "util/thread.h"
@@ -871,7 +872,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
&sample, machine);
} else if (event->header.type < PERF_RECORD_MAX) {
hists__inc_nr_events(&evsel->hists, event->header.type);
- perf_event__process(&top->tool, event, &sample, machine);
+ machine__process_event(machine, event);
} else
++session->hists.stats.nr_unknown_events;
}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index eaaee22..0ae444e 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -520,134 +520,15 @@ int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine)
{
- struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
-
- if (dump_trace)
- perf_event__fprintf_comm(event, stdout);
-
- if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
- dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
- return -1;
- }
-
- return 0;
+ return machine__process_comm_event(machine, event);
}

int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
- struct machine *machine __maybe_unused)
-{
- dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
- event->lost.id, event->lost.lost);
- return 0;
-}
-
-static void perf_event__set_kernel_mmap_len(union perf_event *event,
- struct map **maps)
-{
- maps[MAP__FUNCTION]->start = event->mmap.start;
- maps[MAP__FUNCTION]->end = event->mmap.start + event->mmap.len;
- /*
- * Be a bit paranoid here, some perf.data file came with
- * a zero sized synthesized MMAP event for the kernel.
- */
- if (maps[MAP__FUNCTION]->end == 0)
- maps[MAP__FUNCTION]->end = ~0ULL;
-}
-
-static int perf_event__process_kernel_mmap(struct perf_tool *tool
- __maybe_unused,
- union perf_event *event,
- struct machine *machine)
+ struct machine *machine)
{
- struct map *map;
- char kmmap_prefix[PATH_MAX];
- enum dso_kernel_type kernel_type;
- bool is_kernel_mmap;
-
- machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
- if (machine__is_host(machine))
- kernel_type = DSO_TYPE_KERNEL;
- else
- kernel_type = DSO_TYPE_GUEST_KERNEL;
-
- is_kernel_mmap = memcmp(event->mmap.filename,
- kmmap_prefix,
- strlen(kmmap_prefix) - 1) == 0;
- if (event->mmap.filename[0] == '/' ||
- (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
-
- char short_module_name[1024];
- char *name, *dot;
-
- if (event->mmap.filename[0] == '/') {
- name = strrchr(event->mmap.filename, '/');
- if (name == NULL)
- goto out_problem;
-
- ++name; /* skip / */
- dot = strrchr(name, '.');
- if (dot == NULL)
- goto out_problem;
- snprintf(short_module_name, sizeof(short_module_name),
- "[%.*s]", (int)(dot - name), name);
- strxfrchar(short_module_name, '-', '_');
- } else
- strcpy(short_module_name, event->mmap.filename);
-
- map = machine__new_module(machine, event->mmap.start,
- event->mmap.filename);
- if (map == NULL)
- goto out_problem;
-
- name = strdup(short_module_name);
- if (name == NULL)
- goto out_problem;
-
- map->dso->short_name = name;
- map->dso->sname_alloc = 1;
- map->end = map->start + event->mmap.len;
- } else if (is_kernel_mmap) {
- const char *symbol_name = (event->mmap.filename +
- strlen(kmmap_prefix));
- /*
- * Should be there already, from the build-id table in
- * the header.
- */
- struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
- kmmap_prefix);
- if (kernel == NULL)
- goto out_problem;
-
- kernel->kernel = kernel_type;
- if (__machine__create_kernel_maps(machine, kernel) < 0)
- goto out_problem;
-
- perf_event__set_kernel_mmap_len(event, machine->vmlinux_maps);
-
- /*
- * Avoid using a zero address (kptr_restrict) for the ref reloc
- * symbol. Effectively having zero here means that at record
- * time /proc/sys/kernel/kptr_restrict was non zero.
- */
- if (event->mmap.pgoff != 0) {
- maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
- symbol_name,
- event->mmap.pgoff);
- }
-
- if (machine__is_default_guest(machine)) {
- /*
- * preload dso of guest kernel and modules
- */
- dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
- NULL);
- }
- }
- return 0;
-out_problem:
- return -1;
+ return machine__process_lost_event(machine, event);
}

size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
@@ -657,43 +538,12 @@ size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
event->mmap.len, event->mmap.pgoff, event->mmap.filename);
}

-int perf_event__process_mmap(struct perf_tool *tool,
+int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample __maybe_unused,
struct machine *machine)
{
- struct thread *thread;
- struct map *map;
- u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
- int ret = 0;
-
- if (dump_trace)
- perf_event__fprintf_mmap(event, stdout);
-
- if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
- cpumode == PERF_RECORD_MISC_KERNEL) {
- ret = perf_event__process_kernel_mmap(tool, event, machine);
- if (ret < 0)
- goto out_problem;
- return 0;
- }
-
- thread = machine__findnew_thread(machine, event->mmap.pid);
- if (thread == NULL)
- goto out_problem;
- map = map__new(&machine->user_dsos, event->mmap.start,
- event->mmap.len, event->mmap.pgoff,
- event->mmap.pid, event->mmap.filename,
- MAP__FUNCTION);
- if (map == NULL)
- goto out_problem;
-
- thread__insert_map(thread, map);
- return 0;
-
-out_problem:
- dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
- return 0;
+ return machine__process_mmap_event(machine, event);
}

size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
@@ -708,19 +558,7 @@ int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine)
{
- struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
- struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
-
- if (dump_trace)
- perf_event__fprintf_task(event, stdout);
-
- if (thread == NULL || parent == NULL ||
- thread__fork(thread, parent) < 0) {
- dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
- return -1;
- }
-
- return 0;
+ return machine__process_fork_event(machine, event);
}

int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
@@ -728,15 +566,7 @@ int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
struct perf_sample *sample __maybe_unused,
struct machine *machine)
{
- struct thread *thread = machine__find_thread(machine, event->fork.tid);
-
- if (dump_trace)
- perf_event__fprintf_task(event, stdout);
-
- if (thread != NULL)
- machine__remove_thread(machine, thread);
-
- return 0;
+ return machine__process_exit_event(machine, event);
}

size_t perf_event__fprintf(union perf_event *event, FILE *fp)
@@ -762,29 +592,12 @@ size_t perf_event__fprintf(union perf_event *event, FILE *fp)
return ret;
}

-int perf_event__process(struct perf_tool *tool, union perf_event *event,
- struct perf_sample *sample, struct machine *machine)
+int perf_event__process(struct perf_tool *tool __maybe_unused,
+ union perf_event *event,
+ struct perf_sample *sample __maybe_unused,
+ struct machine *machine)
{
- switch (event->header.type) {
- case PERF_RECORD_COMM:
- perf_event__process_comm(tool, event, sample, machine);
- break;
- case PERF_RECORD_MMAP:
- perf_event__process_mmap(tool, event, sample, machine);
- break;
- case PERF_RECORD_FORK:
- perf_event__process_fork(tool, event, sample, machine);
- break;
- case PERF_RECORD_EXIT:
- perf_event__process_exit(tool, event, sample, machine);
- break;
- case PERF_RECORD_LOST:
- perf_event__process_lost(tool, event, sample, machine);
- default:
- break;
- }
-
- return 0;
+ return machine__process_event(machine, event);
}

void thread__find_addr_map(struct thread *self,
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9d36d7e..502eec0 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,3 +1,5 @@
+#include "debug.h"
+#include "event.h"
#include "machine.h"
#include "map.h"
#include "thread.h"
@@ -55,3 +57,221 @@ struct thread *machine__find_thread(struct machine *machine, pid_t pid)
{
return __machine__findnew_thread(machine, pid, false);
}
+
+int machine__process_comm_event(struct machine *machine, union perf_event *event)
+{
+ struct thread *thread = machine__findnew_thread(machine, event->comm.tid);
+
+ if (dump_trace)
+ perf_event__fprintf_comm(event, stdout);
+
+ if (thread == NULL || thread__set_comm(thread, event->comm.comm)) {
+ dump_printf("problem processing PERF_RECORD_COMM, skipping event.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int machine__process_lost_event(struct machine *machine __maybe_unused,
+ union perf_event *event)
+{
+ dump_printf(": id:%" PRIu64 ": lost:%" PRIu64 "\n",
+ event->lost.id, event->lost.lost);
+ return 0;
+}
+
+static void machine__set_kernel_mmap_len(struct machine *machine,
+ union perf_event *event)
+{
+ machine->vmlinux_maps[MAP__FUNCTION]->start = event->mmap.start;
+ machine->vmlinux_maps[MAP__FUNCTION]->end = (event->mmap.start +
+ event->mmap.len);
+ /*
+ * Be a bit paranoid here, some perf.data file came with
+ * a zero sized synthesized MMAP event for the kernel.
+ */
+ if (machine->vmlinux_maps[MAP__FUNCTION]->end == 0)
+ machine->vmlinux_maps[MAP__FUNCTION]->end = ~0ULL;
+}
+
+static int machine__process_kernel_mmap_event(struct machine *machine,
+ union perf_event *event)
+{
+ struct map *map;
+ char kmmap_prefix[PATH_MAX];
+ enum dso_kernel_type kernel_type;
+ bool is_kernel_mmap;
+
+ machine__mmap_name(machine, kmmap_prefix, sizeof(kmmap_prefix));
+ if (machine__is_host(machine))
+ kernel_type = DSO_TYPE_KERNEL;
+ else
+ kernel_type = DSO_TYPE_GUEST_KERNEL;
+
+ is_kernel_mmap = memcmp(event->mmap.filename,
+ kmmap_prefix,
+ strlen(kmmap_prefix) - 1) == 0;
+ if (event->mmap.filename[0] == '/' ||
+ (!is_kernel_mmap && event->mmap.filename[0] == '[')) {
+
+ char short_module_name[1024];
+ char *name, *dot;
+
+ if (event->mmap.filename[0] == '/') {
+ name = strrchr(event->mmap.filename, '/');
+ if (name == NULL)
+ goto out_problem;
+
+ ++name; /* skip / */
+ dot = strrchr(name, '.');
+ if (dot == NULL)
+ goto out_problem;
+ snprintf(short_module_name, sizeof(short_module_name),
+ "[%.*s]", (int)(dot - name), name);
+ strxfrchar(short_module_name, '-', '_');
+ } else
+ strcpy(short_module_name, event->mmap.filename);
+
+ map = machine__new_module(machine, event->mmap.start,
+ event->mmap.filename);
+ if (map == NULL)
+ goto out_problem;
+
+ name = strdup(short_module_name);
+ if (name == NULL)
+ goto out_problem;
+
+ map->dso->short_name = name;
+ map->dso->sname_alloc = 1;
+ map->end = map->start + event->mmap.len;
+ } else if (is_kernel_mmap) {
+ const char *symbol_name = (event->mmap.filename +
+ strlen(kmmap_prefix));
+ /*
+ * Should be there already, from the build-id table in
+ * the header.
+ */
+ struct dso *kernel = __dsos__findnew(&machine->kernel_dsos,
+ kmmap_prefix);
+ if (kernel == NULL)
+ goto out_problem;
+
+ kernel->kernel = kernel_type;
+ if (__machine__create_kernel_maps(machine, kernel) < 0)
+ goto out_problem;
+
+ machine__set_kernel_mmap_len(machine, event);
+
+ /*
+ * Avoid using a zero address (kptr_restrict) for the ref reloc
+ * symbol. Effectively having zero here means that at record
+ * time /proc/sys/kernel/kptr_restrict was non zero.
+ */
+ if (event->mmap.pgoff != 0) {
+ maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps,
+ symbol_name,
+ event->mmap.pgoff);
+ }
+
+ if (machine__is_default_guest(machine)) {
+ /*
+ * preload dso of guest kernel and modules
+ */
+ dso__load(kernel, machine->vmlinux_maps[MAP__FUNCTION],
+ NULL);
+ }
+ }
+ return 0;
+out_problem:
+ return -1;
+}
+
+int machine__process_mmap_event(struct machine *machine, union perf_event *event)
+{
+ u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
+ struct thread *thread;
+ struct map *map;
+ int ret = 0;
+
+ if (dump_trace)
+ perf_event__fprintf_mmap(event, stdout);
+
+ if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL ||
+ cpumode == PERF_RECORD_MISC_KERNEL) {
+ ret = machine__process_kernel_mmap_event(machine, event);
+ if (ret < 0)
+ goto out_problem;
+ return 0;
+ }
+
+ thread = machine__findnew_thread(machine, event->mmap.pid);
+ if (thread == NULL)
+ goto out_problem;
+ map = map__new(&machine->user_dsos, event->mmap.start,
+ event->mmap.len, event->mmap.pgoff,
+ event->mmap.pid, event->mmap.filename,
+ MAP__FUNCTION);
+ if (map == NULL)
+ goto out_problem;
+
+ thread__insert_map(thread, map);
+ return 0;
+
+out_problem:
+ dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
+ return 0;
+}
+
+int machine__process_fork_event(struct machine *machine, union perf_event *event)
+{
+ struct thread *thread = machine__findnew_thread(machine, event->fork.tid);
+ struct thread *parent = machine__findnew_thread(machine, event->fork.ptid);
+
+ if (dump_trace)
+ perf_event__fprintf_task(event, stdout);
+
+ if (thread == NULL || parent == NULL ||
+ thread__fork(thread, parent) < 0) {
+ dump_printf("problem processing PERF_RECORD_FORK, skipping event.\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int machine__process_exit_event(struct machine *machine, union perf_event *event)
+{
+ struct thread *thread = machine__find_thread(machine, event->fork.tid);
+
+ if (dump_trace)
+ perf_event__fprintf_task(event, stdout);
+
+ if (thread != NULL)
+ machine__remove_thread(machine, thread);
+
+ return 0;
+}
+
+int machine__process_event(struct machine *machine, union perf_event *event)
+{
+ int ret;
+
+ switch (event->header.type) {
+ case PERF_RECORD_COMM:
+ ret = machine__process_comm_event(machine, event); break;
+ case PERF_RECORD_MMAP:
+ ret = machine__process_mmap_event(machine, event); break;
+ case PERF_RECORD_FORK:
+ ret = machine__process_fork_event(machine, event); break;
+ case PERF_RECORD_EXIT:
+ ret = machine__process_exit_event(machine, event); break;
+ case PERF_RECORD_LOST:
+ ret = machine__process_lost_event(machine, event); break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 54df0cd..df152f1 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -5,7 +5,15 @@

struct thread;
struct machine;
+union perf_event;

struct thread *machine__find_thread(struct machine *machine, pid_t pid);

+int machine__process_comm_event(struct machine *machine, union perf_event *event);
+int machine__process_exit_event(struct machine *machine, union perf_event *event);
+int machine__process_fork_event(struct machine *machine, union perf_event *event);
+int machine__process_lost_event(struct machine *machine, union perf_event *event);
+int machine__process_mmap_event(struct machine *machine, union perf_event *event);
+int machine__process_event(struct machine *machine, union perf_event *event);
+
#endif /* __PERF_MACHINE_H */
--
1.7.9.2.358.g22243

2012-10-08 22:40:54

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 21/25] perf kvm: Total count is a u64, print as so

From: David Ahern <[email protected]>

remove cast and use proper type in format.

Signed-off-by: David Ahern <[email protected]>
Cc: Dong Hao <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Ingo Molnar <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Xiao Guangrong <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/builtin-kvm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 8416754..72a302e 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -673,8 +673,8 @@ static void print_result(struct perf_kvm *kvm)
pr_info("\n");
}

- pr_info("\nTotal Samples:%lld, Total events handled time:%.2fus.\n\n",
- (unsigned long long)kvm->total_count, kvm->total_time / 1e3);
+ pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
+ kvm->total_count, kvm->total_time / 1e3);
}

static int process_sample_event(struct perf_tool *tool,
--
1.7.9.2.358.g22243

2012-10-09 13:35:17

by Ingo Molnar

[permalink] [raw]
Subject: Re: [GIT PULL 00/25] perf/core improvements and fixes


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Hi Ingo,
>
> Please consider pulling,
>
> - Arnaldo
>
> The following changes since commit 139c0815903de1a7865fe1d6beac5e995fefdf46:
>
> perf hists: Add more helpers for hist entry stat (2012-10-04 13:36:18 -0300)
>
> are available in the git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux tags/perf-core-for-mingo
>
> for you to fetch changes up to 7747e2f4fb5fb840994613dd1474c17cddb7836b:
>
> Documentation: add documentation on compiling for Android (2012-10-08 17:44:39 -0300)
>
> ----------------------------------------------------------------
>
> perf/core improvements and fixes
>
> . Handle PERF_RECORD_EXIT events in sched and annotate.
>
> . struct machine refactorings to help in top and trace.
>
> . Add on_exit implementation for systems without one, e.g. Android, from
> Bernhard Rosenkraenzer.
>
> . Only process events for vcpus of interest, helps handling large number
> of events, from David Ahern.
>
> . Cross compiling fixes for Android, from Irina Tirdea.
>
> . Add documentation on compiling for Android, from Irina Tirdea.
>
> . perf diff improvements from Jiri Olsa.
>
> . Target (task/user/cpu/syswide) handling improvements, from Namhyung Kim.
>
> . Add support in 'trace' for tracing workload given by command line, from
> Namhyung Kim.
>
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> ----------------------------------------------------------------
>
> Arnaldo Carvalho de Melo (6):
> perf tools: Have the page size value available for all tools
> perf machine: Introduce find_thread method
> perf event: No need to create a thread when handling PERF_RECORD_EXIT
> perf annotate: Handle PERF_RECORD_EXIT events
> perf sched: Handle PERF_RECORD_EXIT events
> perf machine: Carve up event processing specific from perf_tool
>
> Bernhard Rosenkraenzer (1):
> perf tools: Add on_exit implementation
>
> David Ahern (4):
> perf kvm: Only process events for vcpus of interest
> perf kvm: Remove typecast in init_kvm_event_record
> perf kvm: Total count is a u64, print as so
> perf kvm: Add braces around multi-line statements
>
> Irina Tirdea (2):
> perf tools: Update Makefile for Android
> Documentation: add documentation on compiling for Android
>
> Jiri Olsa (8):
> perf diff: Add -b option for perf diff to display paired entries only
> perf diff: Add ratio computation way to compare hist entries
> perf diff: Add option to sort entries based on diff computation
> perf diff: Add weighted diff computation way to compare hist entries
> perf diff: Add -p option to display period values for hist entries
> perf diff: Add -F option to display formula for computation
> perf diff: Include samples without symbol in overall stats
> perf diff: Display empty space for non paired samples
>
> Namhyung Kim (3):
> perf trace: Validate target task/user/cpu argument
> perf trace: Explicitly enable system-wide mode if no option is given
> perf trace: Add support for tracing workload given by command line
>
> Wei Yongjun (1):
> perf tools: Remove duplicated include from trace-event-python.c
>
> tools/perf/Documentation/android.txt | 75 ++++
> tools/perf/Documentation/perf-diff.txt | 60 +++
> tools/perf/Makefile | 33 +-
> tools/perf/builtin-annotate.c | 3 +-
> tools/perf/builtin-diff.c | 405 +++++++++++++++++++-
> tools/perf/builtin-inject.c | 6 +-
> tools/perf/builtin-kvm.c | 35 +-
> tools/perf/builtin-record.c | 32 ++
> tools/perf/builtin-report.c | 4 +-
> tools/perf/builtin-sched.c | 3 +-
> tools/perf/builtin-script.c | 4 +-
> tools/perf/builtin-test.c | 2 -
> tools/perf/builtin-top.c | 3 +-
> tools/perf/builtin-trace.c | 53 ++-
> tools/perf/config/feature-tests.mak | 20 +-
> tools/perf/perf.c | 2 +
> tools/perf/ui/hist.c | 134 ++++++-
> tools/perf/ui/stdio/hist.c | 2 +-
> tools/perf/util/build-id.c | 2 +-
> tools/perf/util/event.c | 215 +----------
> tools/perf/util/event.h | 6 +-
> tools/perf/util/evlist.c | 3 -
> tools/perf/util/hist.h | 8 +
> tools/perf/util/machine.c | 277 +++++++++++++
> tools/perf/util/machine.h | 19 +
> .../util/scripting-engines/trace-event-python.c | 1 -
> tools/perf/util/session.c | 4 +-
> tools/perf/util/sort.h | 18 +
> tools/perf/util/thread.c | 41 +-
> tools/perf/util/thread.h | 2 +
> tools/perf/util/trace-event-read.c | 2 -
> tools/perf/util/util.c | 2 +
> tools/perf/util/util.h | 2 +
> 33 files changed, 1173 insertions(+), 305 deletions(-)
> create mode 100644 tools/perf/Documentation/android.txt
> create mode 100644 tools/perf/util/machine.c
> create mode 100644 tools/perf/util/machine.h

Pulled, thanks Arnaldo!

Ingo