2014-02-10 02:47:32

by Namhyung Kim

[permalink] [raw]
Subject: [PATCHSET 0/8] perf tools: Update on filtered entries' percentage output (v4)

Hello,

I added --percentage option to perf report to control display of
percentage of filtered entries.

usage: perf report [<options>]

--percentage <relative|absolute>
how to display percentage of filtered entries

"relative" means it's relative to filtered entries only so that the
sum of shown entries will be always 100%. "absolute" means it retains
original value before and after the filter applied. In patch 5, I
made the "absolute" as default since it makes more sense IMHO.

$ perf report -s comm
# Overhead Command
# ........ ............
#
74.19% cc1
7.61% gcc
6.11% as
4.35% sh
4.14% make
1.13% fixdep
...

$ perf report -s comm -c cc1,gcc --percentage absolute
# Overhead Command
# ........ ............
#
74.19% cc1
7.61% gcc

$ perf report -s comm -c cc1,gcc --percentage relative
# Overhead Command
# ........ ............
#
90.69% cc1
9.31% gcc

Note that it has zero effect if no filter was applied.

* changes in v4:
- support perf top and perf diff also (Jiri)
- add HIST_FILTER__HOST/GUEST (Jiri)
- retain both of filtered and total stats (Arnaldo)
- add 'F' hotkey on TUI (Jiri)
- rename config variable to have "hist." prefix


You can get this on the 'perf/percentage-v4' branch in my tree

git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git

Any comments are welcome, thanks
Namhyung


Namhyung Kim (8):
perf tools: Count periods of filtered entries separately
perf hists: Add support for showing relative percentage
perf report: Add --percentage option
perf top: Add --percentage option
perf diff: Add --percentage option
perf tools: Add hist.percentage config option
perf ui/tui: Add 'F' hotkey to toggle percentage output
perf tools: Show absolute percentage by default

tools/perf/Documentation/perf-diff.txt | 21 +++++++++--
tools/perf/Documentation/perf-report.txt | 24 +++++++++----
tools/perf/Documentation/perf-top.txt | 18 ++++++++--
tools/perf/builtin-diff.c | 48 +++++++++++++++++++++----
tools/perf/builtin-report.c | 32 +++++++++++++++--
tools/perf/builtin-top.c | 16 +++++++++
tools/perf/ui/browsers/hists.c | 61 ++++++++++++++++++++++++++------
tools/perf/ui/gtk/hists.c | 27 +++++++++-----
tools/perf/ui/hist.c | 12 +++++--
tools/perf/util/config.c | 4 +++
tools/perf/util/event.c | 22 ++++++------
tools/perf/util/hist.c | 52 ++++++++++++++++-----------
tools/perf/util/hist.h | 15 ++++++++
tools/perf/util/symbol.h | 5 +--
14 files changed, 278 insertions(+), 79 deletions(-)

--
1.7.11.7


2014-02-10 02:47:38

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 5/8] perf diff: Add --percentage option

The --percentage option is for controlling overhead percentage
displayed. It can only receive either of "relative" or "absolute" and
affects -c delta output only.

For more information, please see previous commit same thing done to
"perf report".

Cc: Jiri Olsa <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/Documentation/perf-diff.txt | 21 +++++++++++++---
tools/perf/builtin-diff.c | 46 +++++++++++++++++++++++++++++-----
2 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index fdfceee0ffd0..fbfa1192923c 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -33,17 +33,20 @@ OPTIONS
-d::
--dsos=::
Only consider symbols in these dsos. CSV that understands
- file://filename entries.
+ file://filename entries. This option will affect the percentage
+ of the Baseline/Delta column. See --percentage for more info.

-C::
--comms=::
Only consider symbols in these comms. CSV that understands
- file://filename entries.
+ file://filename entries. This option will affect the percentage
+ of the Baseline/Delta column. See --percentage for more info.

-S::
--symbols=::
Only consider these symbols. CSV that understands
- file://filename entries.
+ file://filename entries. This option will affect the percentage
+ of the Baseline/Delta column. See --percentage for more info.

-s::
--sort=::
@@ -89,6 +92,14 @@ OPTIONS
--order::
Specify compute sorting column number.

+--percentage::
+ Determine how to display the overhead percentage of filtered entries.
+ Filters can be applied by --comms, --dsos and/or --symbols options.
+
+ "relative" means it's relative to filtered entries only so that the
+ sum of shown entries will be always 100%. "absolute" means it retains
+ the original value before and after the filter is applied.
+
COMPARISON
----------
The comparison is governed by the baseline file. The baseline perf.data
@@ -157,6 +168,10 @@ with:
- period_percent being the % of the hist entry period value within
single data file

+ - with filtering by -C, -d and/or -S, period_percent might be changed
+ relative to how entries are filtered. Use --percentage=absolute to
+ prevent such fluctuation.
+
ratio
~~~~~
If specified the 'Ratio' column is displayed with value 'r' computed as:
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index a77e31246c00..2c7406d9eb5d 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -221,6 +221,10 @@ static int setup_compute(const struct option *opt, const char *str,
static double period_percent(struct hist_entry *he, u64 period)
{
u64 total = he->hists->stats.total_period;
+
+ if (symbol_conf.filter_relative)
+ total = he->hists->stats.total_filtered_period;
+
return (period * 100.0) / total;
}

@@ -259,11 +263,18 @@ static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
char *buf, size_t size)
{
+ u64 he_total = he->hists->stats.total_period;
+ u64 pair_total = pair->hists->stats.total_period;
+
+ if (symbol_conf.filter_relative) {
+ he_total = he->hists->stats.total_filtered_period;
+ pair_total = pair->hists->stats.total_filtered_period;
+ }
return scnprintf(buf, size,
"(%" PRIu64 " * 100 / %" PRIu64 ") - "
"(%" PRIu64 " * 100 / %" PRIu64 ")",
- pair->stat.period, pair->hists->stats.total_period,
- he->stat.period, he->hists->stats.total_period);
+ pair->stat.period, pair_total,
+ he->stat.period, he_total);
}

static int formula_ratio(struct hist_entry *he, struct hist_entry *pair,
@@ -327,15 +338,16 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
return -1;
}

- if (al.filtered)
- return 0;
-
if (hists__add_entry(&evsel->hists, &al, sample->period,
sample->weight, sample->transaction)) {
pr_warning("problem incrementing symbol period, skipping event\n");
return -1;
}

+ if (al.filtered == 0) {
+ evsel->hists.stats.total_filtered_period += sample->period;
+ evsel->hists.nr_filtered_entries++;
+ }
evsel->hists.stats.total_period += sample->period;
return 0;
}
@@ -565,7 +577,9 @@ static void hists__compute_resort(struct hists *hists)
next = rb_first(root);

hists->nr_entries = 0;
+ hists->nr_filtered_entries = 0;
hists->stats.total_period = 0;
+ hists->stats.total_filtered_period = 0;
hists__reset_col_len(hists);

while (next != NULL) {
@@ -695,6 +709,19 @@ static int __cmd_diff(void)
return ret;
}

+static int parse_percentage(const struct option *opt __maybe_unused,
+ const char *arg, int unset __maybe_unused)
+{
+ if (!strcmp(arg, "relative"))
+ symbol_conf.filter_relative = true;
+ else if (!strcmp(arg, "absolute"))
+ symbol_conf.filter_relative = false;
+ else
+ return -1;
+
+ return 0;
+}
+
static const char * const diff_usage[] = {
"perf diff [<options>] [old_file] [new_file]",
NULL,
@@ -732,13 +759,20 @@ static const struct option options[] = {
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
+ OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
+ "How to display percentage of filtered entries", parse_percentage),
OPT_END()
};

static double baseline_percent(struct hist_entry *he)
{
struct hists *hists = he->hists;
- return 100.0 * he->stat.period / hists->stats.total_period;
+ u64 total = hists->stats.total_period;
+
+ if (symbol_conf.filter_relative)
+ total = hists->stats.total_filtered_period;
+
+ return 100.0 * he->stat.period / total;
}

static int hpp__color_baseline(struct perf_hpp_fmt *fmt,
--
1.7.11.7

2014-02-10 02:47:37

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 4/8] perf top: Add --percentage option

The --percentage option is for controlling overhead percentage
displayed. It can only receive either of "relative" or "absolute".

For more information, please see previous commit same thing done to
"perf report".

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/Documentation/perf-top.txt | 18 +++++++++++++++---
tools/perf/builtin-top.c | 16 ++++++++++++++++
2 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index cdd8d4946dba..0acf54f203f0 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -124,13 +124,16 @@ Default is to monitor all CPUS.
Show a column with the sum of periods.

--dsos::
- Only consider symbols in these dsos.
+ Only consider symbols in these dsos. This option will affect the
+ percentage of the overhead column. See --percentage for more info.

--comms::
- Only consider symbols in these comms.
+ Only consider symbols in these comms. This option will affect the
+ percentage of the overhead column. See --percentage for more info.

--symbols::
- Only consider these symbols.
+ Only consider these symbols. This option will affect the
+ percentage of the overhead column. See --percentage for more info.

-M::
--disassembler-style=:: Set disassembler style for objdump.
@@ -166,6 +169,15 @@ Default is to monitor all CPUS.
Do not show entries which have an overhead under that percent.
(Default: 0).

+--percentage::
+ Determine how to display the overhead percentage of filtered entries.
+ Filters can be applied by --comms, --dsos and/or --symbols options and
+ Zoom operations on the TUI (thread, dso, etc).
+
+ "relative" means it's relative to filtered entries only so that the
+ sum of shown entries will be always 100%. "absolute" means it retains
+ the original value before and after the filter is applied.
+
INTERACTIVE PROMPTING KEYS
--------------------------

diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ed99ec4a309f..a516e0389c5e 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1011,6 +1011,20 @@ parse_percent_limit(const struct option *opt, const char *arg,
return 0;
}

+static int
+parse_percentage(const struct option *opt __maybe_unused, const char *arg,
+ int unset __maybe_unused)
+{
+ if (!strcmp(arg, "relative"))
+ symbol_conf.filter_relative = true;
+ else if (!strcmp(arg, "absolute"))
+ symbol_conf.filter_relative = false;
+ else
+ return -1;
+
+ return 0;
+}
+
int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
{
int status = -1;
@@ -1114,6 +1128,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_STRING('u', "uid", &target->uid_str, "user", "user to profile"),
OPT_CALLBACK(0, "percent-limit", &top, "percent",
"Don't show entries under that percent", parse_percent_limit),
+ OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
+ "How to display percentage of filtered entries", parse_percentage),
OPT_END()
};
const char * const top_usage[] = {
--
1.7.11.7

2014-02-10 02:48:07

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 7/8] perf ui/tui: Add 'F' hotkey to toggle percentage output

Add 'F' hotkey to toggle relative and absolute percentage of filtered
entries.

Suggested-by: Jiri Olsa <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/ui/browsers/hists.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 14ba6d524943..681c484c5c8e 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -1447,6 +1447,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
"C Collapse all callchains\n" \
"d Zoom into current DSO\n" \
"E Expand all callchains\n" \
+ "F Toggle percentage of filtered entries\n" \

/* help messages are sorted by lexical order of the hotkey */
const char report_help[] = HIST_BROWSER_HELP_COMMON
@@ -1552,6 +1553,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
if (env->arch)
tui__header_window(env);
continue;
+ case 'F':
+ symbol_conf.filter_relative ^= 1;
+ continue;
case K_F1:
case 'h':
case '?':
--
1.7.11.7

2014-02-10 02:48:05

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 8/8] perf tools: Show absolute percentage by default

Now perf report will show absolute percentage on filter entries by
default.

Suggested-by: Jiri Olsa <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/symbol.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b888cb241164..a9d758a3b371 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -33,7 +33,6 @@ struct symbol_conf symbol_conf = {
.try_vmlinux_path = true,
.annotate_src = true,
.demangle = true,
- .filter_relative = true,
.symfs = "",
};

--
1.7.11.7

2014-02-10 02:47:34

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 3/8] perf report: Add --percentage option

The --percentage option is for controlling overhead percentage
displayed. It can only receive either of "relative" or "absolute".

"relative" means it's relative to filtered entries only so that the
sum of shown entries will be always 100%. "absolute" means it retains
the original value before and after the filter is applied.

$ perf report -s comm
# Overhead Command
# ........ ............
#
74.19% cc1
7.61% gcc
6.11% as
4.35% sh
4.14% make
1.13% fixdep
...

$ perf report -s comm -c cc1,gcc --percentage absolute
# Overhead Command
# ........ ............
#
74.19% cc1
7.61% gcc

$ perf report -s comm -c cc1,gcc --percentage relative
# Overhead Command
# ........ ............
#
90.69% cc1
9.31% gcc

Note that it has zero effect if no filter was applied.

Suggested-by: Arnaldo Carvalho de Melo <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/Documentation/perf-report.txt | 24 ++++++++++----
tools/perf/builtin-report.c | 30 +++++++++++++++--
tools/perf/ui/browsers/hists.c | 57 ++++++++++++++++++++++++++------
tools/perf/ui/gtk/hists.c | 27 ++++++++++-----
tools/perf/ui/hist.c | 12 +++++--
tools/perf/util/hist.c | 23 ++++---------
tools/perf/util/symbol.c | 1 +
tools/perf/util/symbol.h | 3 +-
8 files changed, 129 insertions(+), 48 deletions(-)

diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 8eab8a4bdeb8..09af66298564 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -25,10 +25,6 @@ OPTIONS
--verbose::
Be more verbose. (show symbol address, etc)

--d::
---dsos=::
- Only consider symbols in these dsos. CSV that understands
- file://filename entries.
-n::
--show-nr-samples::
Show the number of samples for each symbol
@@ -42,11 +38,18 @@ OPTIONS
-c::
--comms=::
Only consider symbols in these comms. CSV that understands
- file://filename entries.
+ file://filename entries. This option will affect the percentage of
+ the overhead column. See --percentage for more info.
+-d::
+--dsos=::
+ Only consider symbols in these dsos. CSV that understands
+ file://filename entries. This option will affect the percentage of
+ the overhead column. See --percentage for more info.
-S::
--symbols=::
Only consider these symbols. CSV that understands
- file://filename entries.
+ file://filename entries. This option will affect the percentage of
+ the overhead column. See --percentage for more info.

--symbol-filter=::
Only show symbols that match (partially) with this filter.
@@ -237,6 +240,15 @@ OPTIONS
Do not show entries which have an overhead under that percent.
(Default: 0).

+--percentage::
+ Determine how to display the overhead percentage of filtered entries.
+ Filters can be applied by --comms, --dsos and/or --symbols options and
+ Zoom operations on the TUI (thread, dso, etc).
+
+ "relative" means it's relative to filtered entries only so that the
+ sum of shown entries will be always 100%. "absolute" means it retains
+ the original value before and after the filter is applied.
+
--header::
Show header information in the perf.data file. This includes
various information like hostname, OS and perf version, cpu/mem
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 5f7f1a332186..3c4f731e155a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -329,6 +329,11 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
char buf[512];
size_t size = sizeof(buf);

+ if (symbol_conf.filter_relative) {
+ nr_samples = hists->stats.nr_filtered_samples;
+ nr_events = hists->stats.total_filtered_period;
+ }
+
if (perf_evsel__is_group_event(evsel)) {
struct perf_evsel *pos;

@@ -336,8 +341,13 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
evname = buf;

for_each_group_member(pos, evsel) {
- nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
- nr_events += pos->hists.stats.total_period;
+ if (symbol_conf.filter_relative) {
+ nr_samples += pos->hists.stats.nr_filtered_samples;
+ nr_events += pos->hists.stats.total_filtered_period;
+ } else {
+ nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+ nr_events += pos->hists.stats.total_period;
+ }
}
}

@@ -693,6 +703,20 @@ parse_percent_limit(const struct option *opt, const char *str,
return 0;
}

+static int
+parse_percentage(const struct option *opt __maybe_unused, const char *str,
+ int unset __maybe_unused)
+{
+ if (!strcmp(str, "relative"))
+ symbol_conf.filter_relative = true;
+ else if (!strcmp(str, "absolute"))
+ symbol_conf.filter_relative = false;
+ else
+ return -1;
+
+ return 0;
+}
+
int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
{
struct perf_session *session;
@@ -815,6 +839,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_BOOLEAN(0, "mem-mode", &report.mem_mode, "mem access profile"),
OPT_CALLBACK(0, "percent-limit", &report, "percent",
"Don't show entries under that percent", parse_percent_limit),
+ OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
+ "how to display percentage of filtered entries", parse_percentage),
OPT_END()
};
struct perf_data_file file = {
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index b720b92eba6e..14ba6d524943 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -604,9 +604,13 @@ static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
double percent = 0.0;
struct hists *hists = he->hists;
struct hpp_arg *arg = hpp->ptr;
+ u64 total = hists->stats.total_period;

- if (hists->stats.total_period)
- percent = 100.0 * get_field(he) / hists->stats.total_period;
+ if (symbol_conf.filter_relative)
+ total = hists->stats.total_filtered_period;
+
+ if (total)
+ percent = 100.0 * get_field(he) / total;

ui_browser__set_percent_color(arg->b, percent, arg->current_entry);

@@ -629,7 +633,10 @@ static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,

list_for_each_entry(pair, &he->pairs.head, pairs.node) {
u64 period = get_field(pair);
- u64 total = pair->hists->stats.total_period;
+
+ total = pair->hists->stats.total_period;
+ if (symbol_conf.filter_relative)
+ total = pair->hists->stats.total_filtered_period;

if (!total)
continue;
@@ -811,12 +818,18 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)

for (nd = browser->top; nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
- float percent = h->stat.period * 100.0 /
- hb->hists->stats.total_period;
+ u64 total = h->hists->stats.total_period;
+ float percent = 0.0;

if (h->filtered)
continue;

+ if (symbol_conf.filter_relative)
+ total = h->hists->stats.total_filtered_period;
+
+ if (total)
+ percent = h->stat.period * 100.0 / total;
+
if (percent < hb->min_pcnt)
continue;

@@ -834,8 +847,14 @@ static struct rb_node *hists__filter_entries(struct rb_node *nd,
{
while (nd != NULL) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
- float percent = h->stat.period * 100.0 /
- hists->stats.total_period;
+ u64 total = hists->stats.total_period;
+ float percent = 0.0;
+
+ if (symbol_conf.filter_relative)
+ total = hists->stats.total_filtered_period;
+
+ if (total)
+ percent = h->stat.period * 100.0 / total;

if (percent < min_pcnt)
return NULL;
@@ -855,8 +874,14 @@ static struct rb_node *hists__filter_prev_entries(struct rb_node *nd,
{
while (nd != NULL) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
- float percent = h->stat.period * 100.0 /
- hists->stats.total_period;
+ u64 total = hists->stats.total_period;
+ float percent = 0.0;
+
+ if (symbol_conf.filter_relative)
+ total = hists->stats.total_filtered_period;
+
+ if (total)
+ percent = h->stat.period * 100.0 / total;

if (!h->filtered && percent >= min_pcnt)
return nd;
@@ -1231,6 +1256,11 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
char buf[512];
size_t buflen = sizeof(buf);

+ if (symbol_conf.filter_relative) {
+ nr_samples = hists->stats.nr_filtered_samples;
+ nr_events = hists->stats.total_filtered_period;
+ }
+
if (perf_evsel__is_group_event(evsel)) {
struct perf_evsel *pos;

@@ -1238,8 +1268,13 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size,
ev_name = buf;

for_each_group_member(pos, evsel) {
- nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
- nr_events += pos->hists.stats.total_period;
+ if (symbol_conf.filter_relative) {
+ nr_samples += pos->hists.stats.nr_filtered_samples;
+ nr_events += pos->hists.stats.total_filtered_period;
+ } else {
+ nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
+ nr_events += pos->hists.stats.total_period;
+ }
}
}

diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 5b95c44f3435..0e83125123e3 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -33,9 +33,13 @@ static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,
double percent = 0.0;
struct hists *hists = he->hists;
struct perf_evsel *evsel = hists_to_evsel(hists);
+ u64 total = hists->stats.total_period;

- if (hists->stats.total_period)
- percent = 100.0 * get_field(he) / hists->stats.total_period;
+ if (symbol_conf.filter_relative)
+ total = hists->stats.total_filtered_period;
+
+ if (total)
+ percent = 100.0 * get_field(he) / total;

ret = __percent_color_snprintf(hpp->buf, hpp->size, percent);

@@ -48,7 +52,10 @@ static int __hpp__color_fmt(struct perf_hpp *hpp, struct hist_entry *he,

list_for_each_entry(pair, &he->pairs.head, pairs.node) {
u64 period = get_field(pair);
- u64 total = pair->hists->stats.total_period;
+
+ total = pair->hists->stats.total_period;
+ if (symbol_conf.filter_relative)
+ total = pair->hists->stats.total_filtered_period;

evsel = hists_to_evsel(pair->hists);
idx_delta = perf_evsel__group_idx(evsel) - prev_idx - 1;
@@ -280,12 +287,18 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
GtkTreeIter iter;
- float percent = h->stat.period * 100.0 /
- hists->stats.total_period;
+ u64 total = h->hists->stats.total_period;
+ float percent = 0.0;

if (h->filtered)
continue;

+ if (symbol_conf.filter_relative)
+ total = h->hists->stats.total_filtered_period;
+
+ if (total)
+ percent = h->stat.period * 100.0 / total;
+
if (percent < min_pcnt)
continue;

@@ -313,12 +326,8 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
}

if (symbol_conf.use_callchain && sort__has_sym) {
- u64 total;
-
if (callchain_param.mode == CHAIN_GRAPH_REL)
total = h->stat.period;
- else
- total = hists->stats.total_period;

perf_gtk__add_callchain(&h->sorted_chain, store, &iter,
sym_col, total);
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 78f4c92e9b73..714f3f00ea55 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -21,10 +21,13 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,

if (fmt_percent) {
double percent = 0.0;
+ u64 total = hists->stats.total_period;

- if (hists->stats.total_period)
- percent = 100.0 * get_field(he) /
- hists->stats.total_period;
+ if (symbol_conf.filter_relative)
+ total = hists->stats.total_filtered_period;
+
+ if (total)
+ percent = 100.0 * get_field(he) / total;

ret = print_fn(hpp->buf, hpp->size, fmt, percent);
} else
@@ -41,6 +44,9 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
u64 period = get_field(pair);
u64 total = pair->hists->stats.total_period;

+ if (symbol_conf.filter_relative)
+ total = pair->hists->stats.total_filtered_period;
+
if (!total)
continue;

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 743947d891bd..3d9cdf97cfce 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -321,10 +321,11 @@ void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
{
if (!h->filtered) {
hists__calc_col_len(hists, h);
- ++hists->nr_entries;
- hists->stats.total_period += h->stat.period;
+ hists->nr_filtered_entries++;
hists->stats.total_filtered_period += h->stat.period;
}
+ hists->nr_entries++;
+ hists->stats.total_period += h->stat.period;
}

static u8 symbol__parent_filter(const struct symbol *parent)
@@ -675,8 +676,9 @@ void hists__output_resort(struct hists *hists)
next = rb_first(root);
hists->entries = RB_ROOT;

- hists->nr_entries = hists->nr_filtered_entries = 0;
- hists->stats.total_period = hists->stats.total_filtered_period = 0;
+ hists->nr_filtered_entries = 0;
+ hists->stats.total_period = 0;
+ hists->stats.total_filtered_period = 0;
hists__reset_col_len(hists);

while (next) {
@@ -695,16 +697,11 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
if (h->filtered)
return;

- hists->nr_entries++;
hists->nr_filtered_entries++;
- if (h->ms.unfolded) {
- hists->nr_entries += h->nr_rows;
+ if (h->ms.unfolded)
hists->nr_filtered_entries += h->nr_rows;
- }
h->row_offset = 0;
- hists->stats.total_period += h->stat.period;
hists->stats.total_filtered_period += h->stat.period;
- hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
hists->stats.nr_filtered_samples += h->stat.nr_events;

hists__calc_col_len(hists, h);
@@ -727,9 +724,7 @@ void hists__filter_by_dso(struct hists *hists)
{
struct rb_node *nd;

- hists->nr_entries = hists->stats.total_period = 0;
hists->nr_filtered_entries = hists->stats.total_filtered_period = 0;
- hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
hists->stats.nr_filtered_samples = 0;
hists__reset_col_len(hists);

@@ -762,9 +757,7 @@ void hists__filter_by_thread(struct hists *hists)
{
struct rb_node *nd;

- hists->nr_entries = hists->stats.total_period = 0;
hists->nr_filtered_entries = hists->stats.total_filtered_period = 0;
- hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
hists->stats.nr_filtered_samples = 0;
hists__reset_col_len(hists);

@@ -795,9 +788,7 @@ void hists__filter_by_symbol(struct hists *hists)
{
struct rb_node *nd;

- hists->nr_entries = hists->stats.total_period = 0;
hists->nr_filtered_entries = hists->stats.total_filtered_period = 0;
- hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
hists->stats.nr_filtered_samples = 0;
hists__reset_col_len(hists);

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a9d758a3b371..b888cb241164 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -33,6 +33,7 @@ struct symbol_conf symbol_conf = {
.try_vmlinux_path = true,
.annotate_src = true,
.demangle = true,
+ .filter_relative = true,
.symfs = "",
};

diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6300903de169..da779b23469b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -104,7 +104,8 @@ struct symbol_conf {
annotate_asm_raw,
annotate_src,
event_group,
- demangle;
+ demangle,
+ filter_relative;
const char *vmlinux_name,
*kallsyms_name,
*source_prefix,
--
1.7.11.7

2014-02-10 02:48:49

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 7/7] perf tools: Show absolute percentage by default

Now perf report will show absolute percentage on filter entries by
default.

Suggested-by: Jiri Olsa <[email protected]>
Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/symbol.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b888cb241164..a9d758a3b371 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -33,7 +33,6 @@ struct symbol_conf symbol_conf = {
.try_vmlinux_path = true,
.annotate_src = true,
.demangle = true,
- .filter_relative = true,
.symfs = "",
};

--
1.7.11.7

2014-02-10 02:49:06

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 6/8] perf tools: Add hist.percentage config option

Add hist.percentage option for setting default value of the
symbol_conf.filter_relative. It affects the output of various perf
commands (like perf report, top and diff) only if filter(s) applied.

An user can write .perfconfig file like below to show absolute
percentage of filtered entries by default:

$ cat ~/.perfconfig
[hist]
percentage = absolute

And it can be changed through command line:

$ perf report --percentage relative

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/builtin-diff.c | 2 ++
tools/perf/util/config.c | 4 ++++
tools/perf/util/hist.c | 14 ++++++++++++++
tools/perf/util/hist.h | 3 +++
4 files changed, 23 insertions(+)

diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 2c7406d9eb5d..839c8c0b1060 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -1153,6 +1153,8 @@ static int data_init(int argc, const char **argv)

int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused)
{
+ perf_config(perf_default_config, NULL);
+
sort_order = diff__default_sort_order;
argc = parse_options(argc, argv, options, diff_usage, 0);

diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 3e0fdd369ccb..24519e14ac56 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -11,6 +11,7 @@
#include "util.h"
#include "cache.h"
#include "exec_cmd.h"
+#include "util/hist.h" /* perf_hist_config */

#define MAXNAME (256)

@@ -355,6 +356,9 @@ int perf_default_config(const char *var, const char *value,
if (!prefixcmp(var, "core."))
return perf_default_core_config(var, value);

+ if (!prefixcmp(var, "hist."))
+ return perf_hist_config(var, value);
+
/* Add other config variables here. */
return 0;
}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 3d9cdf97cfce..84adde197c05 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -934,3 +934,17 @@ int hists__link(struct hists *leader, struct hists *other)

return 0;
}
+
+int perf_hist_config(const char *var, const char *value)
+{
+ if (!strcmp(var, "hist.percentage")) {
+ if (!strcmp(value, "relative"))
+ symbol_conf.filter_relative = true;
+ else if (!strcmp(value, "absolute"))
+ symbol_conf.filter_relative = false;
+ else
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 2f5686f4031b..cb8250d078b1 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -237,4 +237,7 @@ static inline int script_browse(const char *script_opt __maybe_unused)
#endif

unsigned int hists__sort_list_width(struct hists *hists);
+
+int perf_hist_config(const char *var, const char *value);
+
#endif /* __PERF_HIST_H */
--
1.7.11.7

2014-02-10 02:49:28

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 2/8] perf hists: Add support for showing relative percentage

When filtering by thread, dso or symbol on TUI it also update total
period so that the output shows different result than no filter - the
percentage changed to relative to filtered entries only. Sometimes
this is not desired since users might expect same results with filter.

So new filtered_* fields to hists->stats to count them separately.
They'll be controlled/used by user later.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/util/hist.c | 19 +++++++++++++++----
tools/perf/util/hist.h | 2 ++
2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index d0c40897c955..743947d891bd 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -675,8 +675,8 @@ void hists__output_resort(struct hists *hists)
next = rb_first(root);
hists->entries = RB_ROOT;

- hists->nr_entries = 0;
- hists->stats.total_period = 0;
+ hists->nr_entries = hists->nr_filtered_entries = 0;
+ hists->stats.total_period = hists->stats.total_filtered_period = 0;
hists__reset_col_len(hists);

while (next) {
@@ -695,12 +695,17 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
if (h->filtered)
return;

- ++hists->nr_entries;
- if (h->ms.unfolded)
+ hists->nr_entries++;
+ hists->nr_filtered_entries++;
+ if (h->ms.unfolded) {
hists->nr_entries += h->nr_rows;
+ hists->nr_filtered_entries += h->nr_rows;
+ }
h->row_offset = 0;
hists->stats.total_period += h->stat.period;
+ hists->stats.total_filtered_period += h->stat.period;
hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
+ hists->stats.nr_filtered_samples += h->stat.nr_events;

hists__calc_col_len(hists, h);
}
@@ -723,7 +728,9 @@ void hists__filter_by_dso(struct hists *hists)
struct rb_node *nd;

hists->nr_entries = hists->stats.total_period = 0;
+ hists->nr_filtered_entries = hists->stats.total_filtered_period = 0;
hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
+ hists->stats.nr_filtered_samples = 0;
hists__reset_col_len(hists);

for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@@ -756,7 +763,9 @@ void hists__filter_by_thread(struct hists *hists)
struct rb_node *nd;

hists->nr_entries = hists->stats.total_period = 0;
+ hists->nr_filtered_entries = hists->stats.total_filtered_period = 0;
hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
+ hists->stats.nr_filtered_samples = 0;
hists__reset_col_len(hists);

for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@@ -787,7 +796,9 @@ void hists__filter_by_symbol(struct hists *hists)
struct rb_node *nd;

hists->nr_entries = hists->stats.total_period = 0;
+ hists->nr_filtered_entries = hists->stats.total_filtered_period = 0;
hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
+ hists->stats.nr_filtered_samples = 0;
hists__reset_col_len(hists);

for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index bdfd821e2435..2f5686f4031b 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -41,6 +41,7 @@ struct events_stats {
u64 total_lost;
u64 total_invalid_chains;
u32 nr_events[PERF_RECORD_HEADER_MAX];
+ u32 nr_filtered_samples;
u32 nr_lost_warned;
u32 nr_unknown_events;
u32 nr_invalid_chains;
@@ -84,6 +85,7 @@ struct hists {
struct rb_root entries;
struct rb_root entries_collapsed;
u64 nr_entries;
+ u64 nr_filtered_entries;
const struct thread *thread_filter;
const struct dso *dso_filter;
const char *uid_filter_str;
--
1.7.11.7

2014-02-10 02:50:04

by Namhyung Kim

[permalink] [raw]
Subject: [PATCH 1/8] perf tools: Count periods of filtered entries separately

Currently if a sample was filtered by command line option, it just
dropped. But this affects final output in that the percentage can be
different since the filtered entries were not included to the total.

But user might want to see the original percentages when filter
applied so add new total_filtered_period filed to hists->stats in
order to be controlled by user later. It doesn't change the current
behavior yet.

Signed-off-by: Namhyung Kim <[email protected]>
---
tools/perf/builtin-report.c | 2 +-
tools/perf/util/event.c | 22 ++++++++++------------
tools/perf/util/hist.c | 10 ++--------
tools/perf/util/hist.h | 10 ++++++++++
tools/perf/util/symbol.h | 2 +-
5 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index d882b6f96411..5f7f1a332186 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -223,7 +223,7 @@ static int process_sample_event(struct perf_tool *tool,
return -1;
}

- if (al.filtered || (rep->hide_unresolved && al.sym == NULL))
+ if (rep->hide_unresolved && al.sym == NULL)
return 0;

if (rep->cpu_list && !test_bit(sample->cpu, rep->cpu_bitmap))
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index b0f3ca850e9e..21aa8c6248ee 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -3,6 +3,7 @@
#include "debug.h"
#include "machine.h"
#include "sort.h"
+#include "hist.h"
#include "string.h"
#include "strlist.h"
#include "thread.h"
@@ -661,7 +662,7 @@ void thread__find_addr_map(struct thread *thread,
al->thread = thread;
al->addr = addr;
al->cpumode = cpumode;
- al->filtered = false;
+ al->filtered = 0;

if (machine == NULL) {
al->map = NULL;
@@ -687,11 +688,11 @@ void thread__find_addr_map(struct thread *thread,
if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
!perf_guest)
- al->filtered = true;
+ al->filtered |= (1 << HIST_FILTER__GUEST);
if ((cpumode == PERF_RECORD_MISC_USER ||
cpumode == PERF_RECORD_MISC_KERNEL) &&
!perf_host)
- al->filtered = true;
+ al->filtered |= (1 << HIST_FILTER__HOST);

return;
}
@@ -748,9 +749,6 @@ int perf_event__preprocess_sample(const union perf_event *event,
if (thread == NULL)
return -1;

- if (thread__is_filtered(thread))
- goto out_filtered;
-
dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
/*
* Have we already created the kernel maps for this machine?
@@ -765,6 +763,10 @@ int perf_event__preprocess_sample(const union perf_event *event,

thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
sample->ip, al);
+
+ if (thread__is_filtered(thread))
+ al->filtered |= (1 << HIST_FILTER__THREAD);
+
dump_printf(" ...... dso: %s\n",
al->map ? al->map->dso->long_name :
al->level == 'H' ? "[hypervisor]" : "<not found>");
@@ -780,7 +782,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
(dso->short_name != dso->long_name &&
strlist__has_entry(symbol_conf.dso_list,
dso->long_name)))))
- goto out_filtered;
+ al->filtered |= (1 << HIST_FILTER__DSO);

al->sym = map__find_symbol(al->map, al->addr,
machine->symbol_filter);
@@ -789,11 +791,7 @@ int perf_event__preprocess_sample(const union perf_event *event,
if (symbol_conf.sym_list &&
(!al->sym || !strlist__has_entry(symbol_conf.sym_list,
al->sym->name)))
- goto out_filtered;
-
- return 0;
+ al->filtered |= (1 << HIST_FILTER__SYMBOL);

-out_filtered:
- al->filtered = true;
return 0;
}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 0466efa71140..d0c40897c955 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -13,13 +13,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
static bool hists__filter_entry_by_symbol(struct hists *hists,
struct hist_entry *he);

-enum hist_filter {
- HIST_FILTER__DSO,
- HIST_FILTER__THREAD,
- HIST_FILTER__PARENT,
- HIST_FILTER__SYMBOL,
-};
-
struct callchain_param callchain_param = {
.mode = CHAIN_GRAPH_REL,
.min_percent = 0.5,
@@ -330,6 +323,7 @@ void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h)
hists__calc_col_len(hists, h);
++hists->nr_entries;
hists->stats.total_period += h->stat.period;
+ hists->stats.total_filtered_period += h->stat.period;
}
}

@@ -429,7 +423,7 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
.weight = weight,
},
.parent = sym_parent,
- .filtered = symbol__parent_filter(sym_parent),
+ .filtered = symbol__parent_filter(sym_parent) | al->filtered,
.hists = hists,
.branch_info = bi,
.mem_info = mi,
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index a59743fa3ef7..bdfd821e2435 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -14,6 +14,15 @@ struct hist_entry;
struct addr_location;
struct symbol;

+enum hist_filter {
+ HIST_FILTER__DSO,
+ HIST_FILTER__THREAD,
+ HIST_FILTER__PARENT,
+ HIST_FILTER__SYMBOL,
+ HIST_FILTER__GUEST,
+ HIST_FILTER__HOST,
+};
+
/*
* The kernel collects the number of events it couldn't send in a stretch and
* when possible sends this number in a PERF_RECORD_LOST event. The number of
@@ -28,6 +37,7 @@ struct symbol;
*/
struct events_stats {
u64 total_period;
+ u64 total_filtered_period;
u64 total_lost;
u64 total_invalid_chains;
u32 nr_events[PERF_RECORD_HEADER_MAX];
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index fffe2888a1c7..6300903de169 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -175,7 +175,7 @@ struct addr_location {
struct symbol *sym;
u64 addr;
char level;
- bool filtered;
+ u8 filtered;
u8 cpumode;
s32 cpu;
};
--
1.7.11.7

2014-02-10 03:15:57

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 7/7] perf tools: Show absolute percentage by default

Oops, please ignore this. This was a leftover from last change.. sorry
:( (actually, it's same as patch 8/8).

Thanks,
Namhyung


2014-02-10 오전 11:47, Namhyung Kim 쓴 글:
> Now perf report will show absolute percentage on filter entries by
> default.
>
> Suggested-by: Jiri Olsa <[email protected]>
> Signed-off-by: Namhyung Kim <[email protected]>
> ---
> tools/perf/util/symbol.c | 1 -
> 1 file changed, 1 deletion(-)
>
> diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
> index b888cb241164..a9d758a3b371 100644
> --- a/tools/perf/util/symbol.c
> +++ b/tools/perf/util/symbol.c
> @@ -33,7 +33,6 @@ struct symbol_conf symbol_conf = {
> .try_vmlinux_path = true,
> .annotate_src = true,
> .demangle = true,
> - .filter_relative = true,
> .symfs = "",
> };
>
>

2014-02-20 01:00:22

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCHSET 0/8] perf tools: Update on filtered entries' percentage output (v4)

Ping!

On Mon, 10 Feb 2014 11:47:17 +0900, Namhyung Kim wrote:
> Hello,
>
> I added --percentage option to perf report to control display of
> percentage of filtered entries.
>
> usage: perf report [<options>]
>
> --percentage <relative|absolute>
> how to display percentage of filtered entries
>
> "relative" means it's relative to filtered entries only so that the
> sum of shown entries will be always 100%. "absolute" means it retains
> original value before and after the filter applied. In patch 5, I
> made the "absolute" as default since it makes more sense IMHO.
>
> $ perf report -s comm
> # Overhead Command
> # ........ ............
> #
> 74.19% cc1
> 7.61% gcc
> 6.11% as
> 4.35% sh
> 4.14% make
> 1.13% fixdep
> ...
>
> $ perf report -s comm -c cc1,gcc --percentage absolute
> # Overhead Command
> # ........ ............
> #
> 74.19% cc1
> 7.61% gcc
>
> $ perf report -s comm -c cc1,gcc --percentage relative
> # Overhead Command
> # ........ ............
> #
> 90.69% cc1
> 9.31% gcc
>
> Note that it has zero effect if no filter was applied.
>
> * changes in v4:
> - support perf top and perf diff also (Jiri)
> - add HIST_FILTER__HOST/GUEST (Jiri)
> - retain both of filtered and total stats (Arnaldo)
> - add 'F' hotkey on TUI (Jiri)
> - rename config variable to have "hist." prefix
>
>
> You can get this on the 'perf/percentage-v4' branch in my tree
>
> git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git
>
> Any comments are welcome, thanks
> Namhyung
>
>
> Namhyung Kim (8):
> perf tools: Count periods of filtered entries separately
> perf hists: Add support for showing relative percentage
> perf report: Add --percentage option
> perf top: Add --percentage option
> perf diff: Add --percentage option
> perf tools: Add hist.percentage config option
> perf ui/tui: Add 'F' hotkey to toggle percentage output
> perf tools: Show absolute percentage by default
>
> tools/perf/Documentation/perf-diff.txt | 21 +++++++++--
> tools/perf/Documentation/perf-report.txt | 24 +++++++++----
> tools/perf/Documentation/perf-top.txt | 18 ++++++++--
> tools/perf/builtin-diff.c | 48 +++++++++++++++++++++----
> tools/perf/builtin-report.c | 32 +++++++++++++++--
> tools/perf/builtin-top.c | 16 +++++++++
> tools/perf/ui/browsers/hists.c | 61 ++++++++++++++++++++++++++------
> tools/perf/ui/gtk/hists.c | 27 +++++++++-----
> tools/perf/ui/hist.c | 12 +++++--
> tools/perf/util/config.c | 4 +++
> tools/perf/util/event.c | 22 ++++++------
> tools/perf/util/hist.c | 52 ++++++++++++++++-----------
> tools/perf/util/hist.h | 15 ++++++++
> tools/perf/util/symbol.h | 5 +--
> 14 files changed, 278 insertions(+), 79 deletions(-)

2014-02-20 10:40:33

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 3/8] perf report: Add --percentage option

On Mon, Feb 10, 2014 at 11:47:20AM +0900, Namhyung Kim wrote:
> The --percentage option is for controlling overhead percentage
> displayed. It can only receive either of "relative" or "absolute".
>
> "relative" means it's relative to filtered entries only so that the
> sum of shown entries will be always 100%. "absolute" means it retains
> the original value before and after the filter is applied.

SNIP

> diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
> index 78f4c92e9b73..714f3f00ea55 100644
> --- a/tools/perf/ui/hist.c
> +++ b/tools/perf/ui/hist.c
> @@ -21,10 +21,13 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
>
> if (fmt_percent) {
> double percent = 0.0;
> + u64 total = hists->stats.total_period;
>
> - if (hists->stats.total_period)
> - percent = 100.0 * get_field(he) /
> - hists->stats.total_period;
> + if (symbol_conf.filter_relative)
> + total = hists->stats.total_filtered_period;
> +
> + if (total)
> + percent = 100.0 * get_field(he) / total;
>
> ret = print_fn(hpp->buf, hpp->size, fmt, percent);
> } else
> @@ -41,6 +44,9 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
> u64 period = get_field(pair);
> u64 total = pair->hists->stats.total_period;
>
> + if (symbol_conf.filter_relative)
> + total = pair->hists->stats.total_filtered_period;
> +
> if (!total)
> continue;

looks like we could use something like:

perf_hists__total_period(hists)
{
u64 total = hists->stats.total_period;

if (symbol_conf.filter_relative)
total = hists->stats.total_filtered_period;

return total;
}

probably on other places as well

jirka

2014-02-20 10:45:25

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 4/8] perf top: Add --percentage option

On Mon, Feb 10, 2014 at 11:47:21AM +0900, Namhyung Kim wrote:
> The --percentage option is for controlling overhead percentage
> displayed. It can only receive either of "relative" or "absolute".
>
> For more information, please see previous commit same thing done to
> "perf report".
>
> Signed-off-by: Namhyung Kim <[email protected]>
> ---

SNIP

>
> diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
> index ed99ec4a309f..a516e0389c5e 100644
> --- a/tools/perf/builtin-top.c
> +++ b/tools/perf/builtin-top.c
> @@ -1011,6 +1011,20 @@ parse_percent_limit(const struct option *opt, const char *arg,
> return 0;
> }
>
> +static int
> +parse_percentage(const struct option *opt __maybe_unused, const char *arg,
> + int unset __maybe_unused)
> +{
> + if (!strcmp(arg, "relative"))
> + symbol_conf.filter_relative = true;
> + else if (!strcmp(arg, "absolute"))
> + symbol_conf.filter_relative = false;
> + else
> + return -1;
> +
> + return 0;
> +}

please make one of parse_percentage functions public and
share it among report/top/diff commands

jirka

2014-02-20 10:48:05

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 5/8] perf diff: Add --percentage option

On Mon, Feb 10, 2014 at 11:47:22AM +0900, Namhyung Kim wrote:
> The --percentage option is for controlling overhead percentage
> displayed. It can only receive either of "relative" or "absolute" and
> affects -c delta output only.
>
> For more information, please see previous commit same thing done to
> "perf report".
>
> Cc: Jiri Olsa <[email protected]>
> Signed-off-by: Namhyung Kim <[email protected]>
> ---

SNIP

> ~~~~~
> If specified the 'Ratio' column is displayed with value 'r' computed as:
> diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
> index a77e31246c00..2c7406d9eb5d 100644
> --- a/tools/perf/builtin-diff.c
> +++ b/tools/perf/builtin-diff.c
> @@ -221,6 +221,10 @@ static int setup_compute(const struct option *opt, const char *str,
> static double period_percent(struct hist_entry *he, u64 period)
> {
> u64 total = he->hists->stats.total_period;
> +
> + if (symbol_conf.filter_relative)
> + total = he->hists->stats.total_filtered_period;
> +
> return (period * 100.0) / total;

yet another perf_hists__total_period user

> }
>
> @@ -259,11 +263,18 @@ static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
> static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
> char *buf, size_t size)
> {
> + u64 he_total = he->hists->stats.total_period;
> + u64 pair_total = pair->hists->stats.total_period;

SNIP

>
> static double baseline_percent(struct hist_entry *he)
> {
> struct hists *hists = he->hists;
> - return 100.0 * he->stat.period / hists->stats.total_period;
> + u64 total = hists->stats.total_period;
> +
> + if (symbol_conf.filter_relative)
> + total = hists->stats.total_filtered_period;
> +
> + return 100.0 * he->stat.period / total;
> }

and another ;-)

jirka

2014-02-20 10:49:32

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 5/8] perf diff: Add --percentage option

On Mon, Feb 10, 2014 at 11:47:22AM +0900, Namhyung Kim wrote:
> The --percentage option is for controlling overhead percentage
> displayed. It can only receive either of "relative" or "absolute" and
> affects -c delta output only.
>
> For more information, please see previous commit same thing done to
> "perf report".
>
> Cc: Jiri Olsa <[email protected]>
> Signed-off-by: Namhyung Kim <[email protected]>
> ---
> tools/perf/Documentation/perf-diff.txt | 21 +++++++++++++---
> tools/perf/builtin-diff.c | 46 +++++++++++++++++++++++++++++-----
> 2 files changed, 58 insertions(+), 9 deletions(-)

SNIP

> @@ -259,11 +263,18 @@ static s64 compute_wdiff(struct hist_entry *he, struct hist_entry *pair)
> static int formula_delta(struct hist_entry *he, struct hist_entry *pair,
> char *buf, size_t size)
> {
> + u64 he_total = he->hists->stats.total_period;
> + u64 pair_total = pair->hists->stats.total_period;
> +
> + if (symbol_conf.filter_relative) {
> + he_total = he->hists->stats.total_filtered_period;
> + pair_total = pair->hists->stats.total_filtered_period;
> + }

and another ;-)

jirka

2014-02-20 10:54:54

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 7/8] perf ui/tui: Add 'F' hotkey to toggle percentage output

On Mon, Feb 10, 2014 at 11:47:25AM +0900, Namhyung Kim wrote:
> Add 'F' hotkey to toggle relative and absolute percentage of filtered
> entries.
>
> Suggested-by: Jiri Olsa <[email protected]>
> Signed-off-by: Namhyung Kim <[email protected]>
> ---
> tools/perf/ui/browsers/hists.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
> index 14ba6d524943..681c484c5c8e 100644
> --- a/tools/perf/ui/browsers/hists.c
> +++ b/tools/perf/ui/browsers/hists.c
> @@ -1447,6 +1447,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
> "C Collapse all callchains\n" \
> "d Zoom into current DSO\n" \
> "E Expand all callchains\n" \
> + "F Toggle percentage of filtered entries\n" \
>
> /* help messages are sorted by lexical order of the hotkey */
> const char report_help[] = HIST_BROWSER_HELP_COMMON
> @@ -1552,6 +1553,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
> if (env->arch)
> tui__header_window(env);
> continue;
> + case 'F':
> + symbol_conf.filter_relative ^= 1;
> + continue;
> case K_F1:
> case 'h':
> case '?':
> --
> 1.7.11.7
>

when in relative mode i get 0 samples count
also in --stdio:

[jolsa@krava perf]$ ./perf report -s symbol --symbols=system_call,vfs_write --stdio --percentage=relative
Failed to open /tmp/perf-1063.map, continuing without symbols
# To display the perf.data header info, please use --header/--header-only options.
#
# Samples: 0 of event 'cycles'
# Event count (approx.): 6046797
#
# Overhead Symbol
# ........ ...............
#
57.05% [k] system_call
42.95% [k] vfs_write


jirka

2014-02-20 11:01:45

by Jiri Olsa

[permalink] [raw]
Subject: Re: [PATCH 6/8] perf tools: Add hist.percentage config option

On Mon, Feb 10, 2014 at 11:47:23AM +0900, Namhyung Kim wrote:
> Add hist.percentage option for setting default value of the
> symbol_conf.filter_relative. It affects the output of various perf
> commands (like perf report, top and diff) only if filter(s) applied.
>
> An user can write .perfconfig file like below to show absolute
> percentage of filtered entries by default:

SNIP

> +++ b/tools/perf/util/hist.c
> @@ -934,3 +934,17 @@ int hists__link(struct hists *leader, struct hists *other)
>
> return 0;
> }
> +
> +int perf_hist_config(const char *var, const char *value)
> +{
> + if (!strcmp(var, "hist.percentage")) {
> + if (!strcmp(value, "relative"))
> + symbol_conf.filter_relative = true;
> + else if (!strcmp(value, "absolute"))
> + symbol_conf.filter_relative = false;
> + else
> + return -1;
> + }
> +
> + return 0;
> +}

the inner stuff could be done in parse_percentage function
not to duplicate the symbol_conf.filter_relative assignment

jirka

2014-02-24 06:37:19

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 3/8] perf report: Add --percentage option

Hi Jiri,

On Thu, 20 Feb 2014 11:39:50 +0100, Jiri Olsa wrote:
> On Mon, Feb 10, 2014 at 11:47:20AM +0900, Namhyung Kim wrote:
>> The --percentage option is for controlling overhead percentage
>> displayed. It can only receive either of "relative" or "absolute".
>>
>> "relative" means it's relative to filtered entries only so that the
>> sum of shown entries will be always 100%. "absolute" means it retains
>> the original value before and after the filter is applied.
>
> SNIP
>
>> diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
>> index 78f4c92e9b73..714f3f00ea55 100644
>> --- a/tools/perf/ui/hist.c
>> +++ b/tools/perf/ui/hist.c
>> @@ -21,10 +21,13 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
>>
>> if (fmt_percent) {
>> double percent = 0.0;
>> + u64 total = hists->stats.total_period;
>>
>> - if (hists->stats.total_period)
>> - percent = 100.0 * get_field(he) /
>> - hists->stats.total_period;
>> + if (symbol_conf.filter_relative)
>> + total = hists->stats.total_filtered_period;
>> +
>> + if (total)
>> + percent = 100.0 * get_field(he) / total;
>>
>> ret = print_fn(hpp->buf, hpp->size, fmt, percent);
>> } else
>> @@ -41,6 +44,9 @@ static int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
>> u64 period = get_field(pair);
>> u64 total = pair->hists->stats.total_period;
>>
>> + if (symbol_conf.filter_relative)
>> + total = pair->hists->stats.total_filtered_period;
>> +
>> if (!total)
>> continue;
>
> looks like we could use something like:
>
> perf_hists__total_period(hists)
> {
> u64 total = hists->stats.total_period;
>
> if (symbol_conf.filter_relative)
> total = hists->stats.total_filtered_period;
>
> return total;
> }
>
> probably on other places as well

Right! Will change.

Thanks,
Namhyung

2014-02-24 06:37:53

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 4/8] perf top: Add --percentage option

On Thu, 20 Feb 2014 11:44:40 +0100, Jiri Olsa wrote:
> On Mon, Feb 10, 2014 at 11:47:21AM +0900, Namhyung Kim wrote:
>> The --percentage option is for controlling overhead percentage
>> displayed. It can only receive either of "relative" or "absolute".
>>
>> For more information, please see previous commit same thing done to
>> "perf report".
>>
>> Signed-off-by: Namhyung Kim <[email protected]>
>> ---
>
> SNIP
>
>>
>> diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
>> index ed99ec4a309f..a516e0389c5e 100644
>> --- a/tools/perf/builtin-top.c
>> +++ b/tools/perf/builtin-top.c
>> @@ -1011,6 +1011,20 @@ parse_percent_limit(const struct option *opt, const char *arg,
>> return 0;
>> }
>>
>> +static int
>> +parse_percentage(const struct option *opt __maybe_unused, const char *arg,
>> + int unset __maybe_unused)
>> +{
>> + if (!strcmp(arg, "relative"))
>> + symbol_conf.filter_relative = true;
>> + else if (!strcmp(arg, "absolute"))
>> + symbol_conf.filter_relative = false;
>> + else
>> + return -1;
>> +
>> + return 0;
>> +}
>
> please make one of parse_percentage functions public and
> share it among report/top/diff commands

Okay.

Thanks,
Namhyung

2014-02-24 06:41:29

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 6/8] perf tools: Add hist.percentage config option

On Thu, 20 Feb 2014 12:01:12 +0100, Jiri Olsa wrote:
> On Mon, Feb 10, 2014 at 11:47:23AM +0900, Namhyung Kim wrote:
>> Add hist.percentage option for setting default value of the
>> symbol_conf.filter_relative. It affects the output of various perf
>> commands (like perf report, top and diff) only if filter(s) applied.
>>
>> An user can write .perfconfig file like below to show absolute
>> percentage of filtered entries by default:
>
> SNIP
>
>> +++ b/tools/perf/util/hist.c
>> @@ -934,3 +934,17 @@ int hists__link(struct hists *leader, struct hists *other)
>>
>> return 0;
>> }
>> +
>> +int perf_hist_config(const char *var, const char *value)
>> +{
>> + if (!strcmp(var, "hist.percentage")) {
>> + if (!strcmp(value, "relative"))
>> + symbol_conf.filter_relative = true;
>> + else if (!strcmp(value, "absolute"))
>> + symbol_conf.filter_relative = false;
>> + else
>> + return -1;
>> + }
>> +
>> + return 0;
>> +}
>
> the inner stuff could be done in parse_percentage function
> not to duplicate the symbol_conf.filter_relative assignment

Will do!

Thanks,
Namhyung

2014-02-24 07:49:37

by Namhyung Kim

[permalink] [raw]
Subject: Re: [PATCH 7/8] perf ui/tui: Add 'F' hotkey to toggle percentage output

On Thu, 20 Feb 2014 11:54:02 +0100, Jiri Olsa wrote:
> On Mon, Feb 10, 2014 at 11:47:25AM +0900, Namhyung Kim wrote:
>> Add 'F' hotkey to toggle relative and absolute percentage of filtered
>> entries.
>>
>> Suggested-by: Jiri Olsa <[email protected]>
>> Signed-off-by: Namhyung Kim <[email protected]>
>> ---
>> tools/perf/ui/browsers/hists.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
>> index 14ba6d524943..681c484c5c8e 100644
>> --- a/tools/perf/ui/browsers/hists.c
>> +++ b/tools/perf/ui/browsers/hists.c
>> @@ -1447,6 +1447,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
>> "C Collapse all callchains\n" \
>> "d Zoom into current DSO\n" \
>> "E Expand all callchains\n" \
>> + "F Toggle percentage of filtered entries\n" \
>>
>> /* help messages are sorted by lexical order of the hotkey */
>> const char report_help[] = HIST_BROWSER_HELP_COMMON
>> @@ -1552,6 +1553,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
>> if (env->arch)
>> tui__header_window(env);
>> continue;
>> + case 'F':
>> + symbol_conf.filter_relative ^= 1;
>> + continue;
>> case K_F1:
>> case 'h':
>> case '?':
>> --
>> 1.7.11.7
>>
>
> when in relative mode i get 0 samples count
> also in --stdio:
>
> [jolsa@krava perf]$ ./perf report -s symbol --symbols=system_call,vfs_write --stdio --percentage=relative
> Failed to open /tmp/perf-1063.map, continuing without symbols
> # To display the perf.data header info, please use --header/--header-only options.
> #
> # Samples: 0 of event 'cycles'
> # Event count (approx.): 6046797
> #
> # Overhead Symbol
> # ........ ...............
> #
> 57.05% [k] system_call
> 42.95% [k] vfs_write

Oops, I found that I missed to increase it when adding hist
entries.. will fix.

Thanks,
Namhyung