perf/core improvements and fixes:

User visible:
 
 . Add --percentage option to control absolute/relative percentage output (Namhyung Kim)
 
 Developer stuff:
 
 . Add --list-cmds to 'kmem', 'mem', 'lock' and 'sched', for use by completion scripts (Ramkumar Ramachandra)
 
 Signed-off-by: Jiri Olsa <jolsa@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJTTsj7AAoJEPZqUSBWB3s98OEP/AzBJviyJSRqf/DNxMZpnuyT
 E1Pd9R8IUT50sWGklEYZcjeCG8JPF46sHcuf5v/tXCwni4u0muJ2imcOJzBKf4it
 XVpXA+E7bNt/oAr+8RVcZ0mhusX2DqafCZOVRTnuUv5y5JG7cWd9fC8qW2Hu6oYe
 SOfjNRpwi9tV6aCkJUMbJT6SaW+rMGSxHLxv77KK/uP50Ekd/H06TyVspsJRfFeB
 rckEIm8p3svQWX7EAHs09p7BxAarTbrK0TWzgfL3YEnCee/y0y9xxN32Pdc8fGj5
 bKx6uRe5HWDcZZZvDIIDQeZLECwBu4xJvQPeRE9AeDs8NgXyvnNvljED+RSXcQ/F
 zxnxYmviZSz/15B8fQ3TWIv+fd1rsc7hnbnmY1U+vPWdRgsc0spTFKZiKtDkLIBq
 jZI+vwhgznDCjajBdKTAVQj6lErupP9ML6HIRcQPWu1YHoDbPiM+ZZ0xskIcsOuE
 AfMAu5reYXW4bPGIA80AEEKLRjTjxcYlNadyQOHYZO/fE+SPs7iW+c/sm/+boN+r
 dWX8NeK6Nfz45wunBIxvXaCM/MnBvTuH657fZQlKuf43radnrduZRjf/Q+yDUEfQ
 VovatgZlK7PRJiIfBUfYfG+ov1cr0F9qJKBYyC8fIrNtWNsvfIwFd3ubkOQBW/qG
 Q0PYdJPNL0furiI0VWO0
 =cjaT
 -----END PGP SIGNATURE-----

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core

Pull perf/core improvements and fixes from Jiri Olsa:

User visible changes:

  * Add --percentage option to control absolute/relative percentage output (Namhyung Kim)

Plumbing changes:

  * Add --list-cmds to 'kmem', 'mem', 'lock' and 'sched', for use by completion scripts (Ramkumar Ramachandra)

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2014-04-17 10:06:47 +02:00
commit b3d5fc3c29
18 changed files with 230 additions and 76 deletions

View file

@ -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:

View file

@ -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

View file

@ -123,13 +123,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.
@ -165,6 +168,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
--------------------------

View file

@ -220,7 +220,8 @@ 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;
u64 total = hists__total_period(he->hists);
return (period * 100.0) / total;
}
@ -259,11 +260,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_non_filtered_period;
pair_total = pair->hists->stats.total_non_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 +335,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_non_filtered_period += sample->period;
evsel->hists.nr_non_filtered_entries++;
}
evsel->hists.stats.total_period += sample->period;
return 0;
}
@ -565,7 +574,9 @@ static void hists__compute_resort(struct hists *hists)
next = rb_first(root);
hists->nr_entries = 0;
hists->nr_non_filtered_entries = 0;
hists->stats.total_period = 0;
hists->stats.total_non_filtered_period = 0;
hists__reset_col_len(hists);
while (next != NULL) {
@ -732,13 +743,16 @@ 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_filter_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__total_period(he->hists);
return 100.0 * he->stat.period / total;
}
static int hpp__color_baseline(struct perf_hpp_fmt *fmt,
@ -1120,6 +1134,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);

View file

@ -756,11 +756,13 @@ int cmd_kmem(int argc, const char **argv, const char *prefix __maybe_unused)
OPT_BOOLEAN(0, "raw-ip", &raw_ip, "show raw ip instead of symbol"),
OPT_END()
};
const char * const kmem_usage[] = {
"perf kmem [<options>] {record|stat}",
const char *const kmem_subcommands[] = { "record", "stat", NULL };
const char *kmem_usage[] = {
NULL,
NULL
};
argc = parse_options(argc, argv, kmem_options, kmem_usage, 0);
argc = parse_options_subcommand(argc, argv, kmem_options,
kmem_subcommands, kmem_usage, 0);
if (!argc)
usage_with_options(kmem_usage, kmem_options);

View file

@ -961,8 +961,10 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
"perf lock info [<options>]",
NULL
};
const char * const lock_usage[] = {
"perf lock [<options>] {record|report|script|info}",
const char *const lock_subcommands[] = { "record", "report", "script",
"info", NULL };
const char *lock_usage[] = {
NULL,
NULL
};
const char * const report_usage[] = {
@ -976,8 +978,8 @@ int cmd_lock(int argc, const char **argv, const char *prefix __maybe_unused)
for (i = 0; i < LOCKHASH_SIZE; i++)
INIT_LIST_HEAD(lockhash_table + i);
argc = parse_options(argc, argv, lock_options, lock_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
argc = parse_options_subcommand(argc, argv, lock_options, lock_subcommands,
lock_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc)
usage_with_options(lock_usage, lock_options);

View file

@ -21,11 +21,6 @@ struct perf_mem {
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
};
static const char * const mem_usage[] = {
"perf mem [<options>] {record <command> |report}",
NULL
};
static int __cmd_record(int argc, const char **argv)
{
int rec_argc, i = 0, j;
@ -220,9 +215,15 @@ int cmd_mem(int argc, const char **argv, const char *prefix __maybe_unused)
" between columns '.' is reserved."),
OPT_END()
};
const char *const mem_subcommands[] = { "record", "report", NULL };
const char *mem_usage[] = {
NULL,
NULL
};
argc = parse_options(argc, argv, mem_options, mem_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
argc = parse_options_subcommand(argc, argv, mem_options, mem_subcommands,
mem_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc || !(strncmp(argv[0], "rec", 3) || mem_operation))
usage_with_options(mem_usage, mem_options);

View file

@ -123,6 +123,8 @@ static int report__add_mem_hist_entry(struct report *rep, struct addr_location *
evsel->hists.stats.total_period += cost;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
if (!he->filtered)
evsel->hists.stats.nr_non_filtered_samples++;
err = hist_entry__append_callchain(he, sample);
out:
return err;
@ -176,6 +178,8 @@ static int report__add_branch_hist_entry(struct report *rep, struct addr_locatio
evsel->hists.stats.total_period += 1;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
if (!he->filtered)
evsel->hists.stats.nr_non_filtered_samples++;
} else
goto out;
}
@ -209,6 +213,8 @@ static int report__add_hist_entry(struct report *rep, struct perf_evsel *evsel,
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
evsel->hists.stats.total_period += sample->period;
if (!he->filtered)
evsel->hists.stats.nr_non_filtered_samples++;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
out:
return err;
@ -337,6 +343,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_non_filtered_samples;
nr_events = hists->stats.total_non_filtered_period;
}
if (perf_evsel__is_group_event(evsel)) {
struct perf_evsel *pos;
@ -344,8 +355,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_non_filtered_samples;
nr_events += pos->hists.stats.total_non_filtered_period;
} else {
nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
nr_events += pos->hists.stats.total_period;
}
}
}
@ -823,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_filter_percentage),
OPT_END()
};
struct perf_data_file file = {

View file

@ -1713,8 +1713,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
"perf sched replay [<options>]",
NULL
};
const char * const sched_usage[] = {
"perf sched [<options>] {record|latency|map|replay|script}",
const char *const sched_subcommands[] = { "record", "latency", "map",
"replay", "script", NULL };
const char *sched_usage[] = {
NULL,
NULL
};
struct trace_sched_handler lat_ops = {
@ -1736,8 +1738,8 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
for (i = 0; i < ARRAY_SIZE(sched.curr_pid); i++)
sched.curr_pid[i] = -1;
argc = parse_options(argc, argv, sched_options, sched_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
argc = parse_options_subcommand(argc, argv, sched_options, sched_subcommands,
sched_usage, PARSE_OPT_STOP_AT_NON_OPTION);
if (!argc)
usage_with_options(sched_usage, sched_options);

View file

@ -253,6 +253,9 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
return NULL;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
if (!he->filtered)
evsel->hists.stats.nr_non_filtered_samples++;
return he;
}
@ -694,8 +697,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
if (event->header.misc & PERF_RECORD_MISC_EXACT_IP)
top->exact_samples++;
if (perf_event__preprocess_sample(event, machine, &al, sample) < 0 ||
al.filtered)
if (perf_event__preprocess_sample(event, machine, &al, sample) < 0)
return;
if (!top->kptr_restrict_warned &&
@ -1116,6 +1118,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_filter_percentage),
OPT_END()
};
const char * const top_usage[] = {

View file

@ -121,8 +121,8 @@ __perf_main ()
elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
evts=$($cmd list --raw-dump)
__perfcomp_colon "$evts" "$cur"
# List subcommands for 'perf kvm'
elif [[ $prev == "kvm" ]]; then
# List subcommands for perf commands
elif [[ $prev == @(kvm|kmem|mem|lock|sched) ]]; then
subcmds=$($cmd $prev --list-cmds)
__perfcomp_colon "$subcmds" "$cur"
# List long option names

View file

@ -769,12 +769,15 @@ 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 = hists__total_period(h->hists);
float percent = 0.0;
if (h->filtered)
continue;
if (total)
percent = h->stat.period * 100.0 / total;
if (percent < hb->min_pcnt)
continue;
@ -792,8 +795,11 @@ 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__total_period(hists);
float percent = 0.0;
if (total)
percent = h->stat.period * 100.0 / total;
if (percent < min_pcnt)
return NULL;
@ -813,8 +819,11 @@ 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__total_period(hists);
float percent = 0.0;
if (total)
percent = h->stat.period * 100.0 / total;
if (!h->filtered && percent >= min_pcnt)
return nd;
@ -1189,6 +1198,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_non_filtered_samples;
nr_events = hists->stats.total_non_filtered_period;
}
if (perf_evsel__is_group_event(evsel)) {
struct perf_evsel *pos;
@ -1196,8 +1210,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_non_filtered_samples;
nr_events += pos->hists.stats.total_non_filtered_period;
} else {
nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE];
nr_events += pos->hists.stats.total_period;
}
}
}
@ -1370,6 +1389,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
@ -1475,6 +1495,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 '?':

View file

@ -228,12 +228,15 @@ 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 = hists__total_period(h->hists);
float percent = 0.0;
if (h->filtered)
continue;
if (total)
percent = h->stat.period * 100.0 / total;
if (percent < min_pcnt)
continue;
@ -261,12 +264,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);

View file

@ -32,10 +32,10 @@ int __hpp__fmt(struct perf_hpp *hpp, struct hist_entry *he,
if (fmt_percent) {
double percent = 0.0;
u64 total = hists__total_period(hists);
if (hists->stats.total_period)
percent = 100.0 * get_field(he) /
hists->stats.total_period;
if (total)
percent = 100.0 * get_field(he) / total;
ret += hpp__call_print_fn(hpp, print_fn, fmt, percent);
} else
@ -50,7 +50,7 @@ int __hpp__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;
u64 total = hists__total_period(pair->hists);
if (!total)
continue;

View file

@ -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;
}

View file

@ -321,9 +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_non_filtered_entries++;
hists->stats.total_non_filtered_period += h->stat.period;
}
hists->nr_entries++;
hists->stats.total_period += h->stat.period;
}
static u8 symbol__parent_filter(const struct symbol *parent)
@ -674,8 +676,9 @@ void hists__output_resort(struct hists *hists)
next = rb_first(root);
hists->entries = RB_ROOT;
hists->nr_entries = 0;
hists->nr_non_filtered_entries = 0;
hists->stats.total_period = 0;
hists->stats.total_non_filtered_period = 0;
hists__reset_col_len(hists);
while (next) {
@ -694,12 +697,12 @@ static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h
if (h->filtered)
return;
++hists->nr_entries;
++hists->nr_non_filtered_entries;
if (h->ms.unfolded)
hists->nr_entries += h->nr_rows;
hists->nr_non_filtered_entries += h->nr_rows;
h->row_offset = 0;
hists->stats.total_period += h->stat.period;
hists->stats.nr_events[PERF_RECORD_SAMPLE] += h->stat.nr_events;
hists->stats.total_non_filtered_period += h->stat.period;
hists->stats.nr_non_filtered_samples += h->stat.nr_events;
hists__calc_col_len(hists, h);
}
@ -721,8 +724,9 @@ void hists__filter_by_dso(struct hists *hists)
{
struct rb_node *nd;
hists->nr_entries = hists->stats.total_period = 0;
hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
hists->nr_non_filtered_entries = 0;
hists->stats.total_non_filtered_period = 0;
hists->stats.nr_non_filtered_samples = 0;
hists__reset_col_len(hists);
for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@ -754,8 +758,9 @@ void hists__filter_by_thread(struct hists *hists)
{
struct rb_node *nd;
hists->nr_entries = hists->stats.total_period = 0;
hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
hists->nr_non_filtered_entries = 0;
hists->stats.total_non_filtered_period = 0;
hists->stats.nr_non_filtered_samples = 0;
hists__reset_col_len(hists);
for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@ -785,8 +790,9 @@ void hists__filter_by_symbol(struct hists *hists)
{
struct rb_node *nd;
hists->nr_entries = hists->stats.total_period = 0;
hists->stats.nr_events[PERF_RECORD_SAMPLE] = 0;
hists->nr_non_filtered_entries = 0;
hists->stats.total_non_filtered_period = 0;
hists->stats.nr_non_filtered_samples = 0;
hists__reset_col_len(hists);
for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
@ -931,3 +937,30 @@ int hists__link(struct hists *leader, struct hists *other)
return 0;
}
u64 hists__total_period(struct hists *hists)
{
return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
hists->stats.total_period;
}
int parse_filter_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 perf_hist_config(const char *var, const char *value)
{
if (!strcmp(var, "hist.percentage"))
return parse_filter_percentage(NULL, value, 0);
return 0;
}

View file

@ -37,9 +37,11 @@ enum hist_filter {
*/
struct events_stats {
u64 total_period;
u64 total_non_filtered_period;
u64 total_lost;
u64 total_invalid_chains;
u32 nr_events[PERF_RECORD_HEADER_MAX];
u32 nr_non_filtered_samples;
u32 nr_lost_warned;
u32 nr_unknown_events;
u32 nr_invalid_chains;
@ -83,6 +85,7 @@ struct hists {
struct rb_root entries;
struct rb_root entries_collapsed;
u64 nr_entries;
u64 nr_non_filtered_entries;
const struct thread *thread_filter;
const struct dso *dso_filter;
const char *uid_filter_str;
@ -112,6 +115,7 @@ void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
void hists__output_recalc_col_len(struct hists *hists, int max_rows);
u64 hists__total_period(struct hists *hists);
void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
void hists__inc_nr_events(struct hists *hists, u32 type);
void events_stats__inc(struct events_stats *stats, u32 type);
@ -250,4 +254,10 @@ static inline int script_browse(const char *script_opt __maybe_unused)
#endif
unsigned int hists__sort_list_width(struct hists *hists);
struct option;
int parse_filter_percentage(const struct option *opt __maybe_unused,
const char *arg, int unset __maybe_unused);
int perf_hist_config(const char *var, const char *value);
#endif /* __PERF_HIST_H */

View file

@ -115,7 +115,8 @@ struct symbol_conf {
annotate_asm_raw,
annotate_src,
event_group,
demangle;
demangle,
filter_relative;
const char *vmlinux_name,
*kallsyms_name,
*source_prefix,