perf report: Introduce --socket-filter option
Introduce --socket-filter option for 'perf report' to only show entries for a processor socket that match this filter. $ perf report --socket-filter 1 --stdio # To display the perf.data header info, please use --header/--header-only options. # # Total Lost Samples: 0 # # Samples: 752 of event 'cycles' # Event count (approx.): 350995599 # Processor Socket: 1 # # Overhead Command Shared Object Symbol # ........ ......... ................ ................................. # 97.02% test test [.] plusB_c 0.97% test test [.] plusA_c 0.23% swapper [kernel.vmlinux] [k] acpi_idle_do_entry 0.09% rcu_sched [kernel.vmlinux] [k] dyntick_save_progress_counter 0.01% swapper [kernel.vmlinux] [k] task_waking_fair 0.00% swapper [kernel.vmlinux] [k] run_timer_softirq Signed-off-by: Kan Liang <kan.liang@intel.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1441377946-44429-3-git-send-email-kan.liang@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Родитель
2e7ea3ab82
Коммит
21394d948a
|
@ -350,6 +350,9 @@ include::itrace.txt[]
|
||||||
This option extends the perf report to show reference callgraphs,
|
This option extends the perf report to show reference callgraphs,
|
||||||
which collected by reference event, in no callgraph event.
|
which collected by reference event, in no callgraph event.
|
||||||
|
|
||||||
|
--socket-filter::
|
||||||
|
Only report the samples on the processor socket that match with this filter
|
||||||
|
|
||||||
include::callchain-overhead-calculation.txt[]
|
include::callchain-overhead-calculation.txt[]
|
||||||
|
|
||||||
SEE ALSO
|
SEE ALSO
|
||||||
|
|
|
@ -62,6 +62,7 @@ struct report {
|
||||||
float min_percent;
|
float min_percent;
|
||||||
u64 nr_entries;
|
u64 nr_entries;
|
||||||
u64 queue_size;
|
u64 queue_size;
|
||||||
|
int socket_filter;
|
||||||
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
|
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -286,6 +287,7 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
|
||||||
struct perf_evsel *evsel = hists_to_evsel(hists);
|
struct perf_evsel *evsel = hists_to_evsel(hists);
|
||||||
char buf[512];
|
char buf[512];
|
||||||
size_t size = sizeof(buf);
|
size_t size = sizeof(buf);
|
||||||
|
int socket = hists->socket_filter;
|
||||||
|
|
||||||
if (symbol_conf.filter_relative) {
|
if (symbol_conf.filter_relative) {
|
||||||
nr_samples = hists->stats.nr_non_filtered_samples;
|
nr_samples = hists->stats.nr_non_filtered_samples;
|
||||||
|
@ -326,6 +328,10 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report
|
||||||
ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order);
|
ret += fprintf(fp, "\n# Sort order : %s", sort_order ? : default_mem_sort_order);
|
||||||
} else
|
} else
|
||||||
ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
|
ret += fprintf(fp, "\n# Event count (approx.): %" PRIu64, nr_events);
|
||||||
|
|
||||||
|
if (socket > -1)
|
||||||
|
ret += fprintf(fp, "\n# Processor Socket: %d", socket);
|
||||||
|
|
||||||
return ret + fprintf(fp, "\n#\n");
|
return ret + fprintf(fp, "\n#\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,6 +456,8 @@ static void report__collapse_hists(struct report *rep)
|
||||||
if (pos->idx == 0)
|
if (pos->idx == 0)
|
||||||
hists->symbol_filter_str = rep->symbol_filter_str;
|
hists->symbol_filter_str = rep->symbol_filter_str;
|
||||||
|
|
||||||
|
hists->socket_filter = rep->socket_filter;
|
||||||
|
|
||||||
hists__collapse_resort(hists, &prog);
|
hists__collapse_resort(hists, &prog);
|
||||||
|
|
||||||
/* Non-group events are considered as leader */
|
/* Non-group events are considered as leader */
|
||||||
|
@ -635,6 +643,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
},
|
},
|
||||||
.max_stack = PERF_MAX_STACK_DEPTH,
|
.max_stack = PERF_MAX_STACK_DEPTH,
|
||||||
.pretty_printing_style = "normal",
|
.pretty_printing_style = "normal",
|
||||||
|
.socket_filter = -1,
|
||||||
};
|
};
|
||||||
const struct option options[] = {
|
const struct option options[] = {
|
||||||
OPT_STRING('i', "input", &input_name, "file",
|
OPT_STRING('i', "input", &input_name, "file",
|
||||||
|
@ -747,6 +756,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||||
"Show full source file name path for source lines"),
|
"Show full source file name path for source lines"),
|
||||||
OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph,
|
OPT_BOOLEAN(0, "show-ref-call-graph", &symbol_conf.show_ref_callgraph,
|
||||||
"Show callgraph from reference event"),
|
"Show callgraph from reference event"),
|
||||||
|
OPT_INTEGER(0, "socket-filter", &report.socket_filter,
|
||||||
|
"only show processor socket that match with this filter"),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
struct perf_data_file file = {
|
struct perf_data_file file = {
|
||||||
|
|
|
@ -1261,6 +1261,7 @@ static int hists__browser_title(struct hists *hists,
|
||||||
int printed;
|
int printed;
|
||||||
const struct dso *dso = hists->dso_filter;
|
const struct dso *dso = hists->dso_filter;
|
||||||
const struct thread *thread = hists->thread_filter;
|
const struct thread *thread = hists->thread_filter;
|
||||||
|
int socket = hists->socket_filter;
|
||||||
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
|
||||||
u64 nr_events = hists->stats.total_period;
|
u64 nr_events = hists->stats.total_period;
|
||||||
struct perf_evsel *evsel = hists_to_evsel(hists);
|
struct perf_evsel *evsel = hists_to_evsel(hists);
|
||||||
|
@ -1314,6 +1315,9 @@ static int hists__browser_title(struct hists *hists,
|
||||||
if (dso)
|
if (dso)
|
||||||
printed += scnprintf(bf + printed, size - printed,
|
printed += scnprintf(bf + printed, size - printed,
|
||||||
", DSO: %s", dso->short_name);
|
", DSO: %s", dso->short_name);
|
||||||
|
if (socket > -1)
|
||||||
|
printed += scnprintf(bf + printed, size - printed,
|
||||||
|
", Processor Socket: %d", socket);
|
||||||
if (!is_report_browser(hbt)) {
|
if (!is_report_browser(hbt)) {
|
||||||
struct perf_top *top = hbt->arg;
|
struct perf_top *top = hbt->arg;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ static bool hists__filter_entry_by_thread(struct hists *hists,
|
||||||
struct hist_entry *he);
|
struct hist_entry *he);
|
||||||
static bool hists__filter_entry_by_symbol(struct hists *hists,
|
static bool hists__filter_entry_by_symbol(struct hists *hists,
|
||||||
struct hist_entry *he);
|
struct hist_entry *he);
|
||||||
|
static bool hists__filter_entry_by_socket(struct hists *hists,
|
||||||
|
struct hist_entry *he);
|
||||||
|
|
||||||
u16 hists__col_len(struct hists *hists, enum hist_column col)
|
u16 hists__col_len(struct hists *hists, enum hist_column col)
|
||||||
{
|
{
|
||||||
|
@ -1027,6 +1029,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
|
||||||
hists__filter_entry_by_dso(hists, he);
|
hists__filter_entry_by_dso(hists, he);
|
||||||
hists__filter_entry_by_thread(hists, he);
|
hists__filter_entry_by_thread(hists, he);
|
||||||
hists__filter_entry_by_symbol(hists, he);
|
hists__filter_entry_by_symbol(hists, he);
|
||||||
|
hists__filter_entry_by_socket(hists, he);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
|
void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
|
||||||
|
@ -1295,6 +1298,18 @@ void hists__filter_by_symbol(struct hists *hists)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool hists__filter_entry_by_socket(struct hists *hists,
|
||||||
|
struct hist_entry *he)
|
||||||
|
{
|
||||||
|
if ((hists->socket_filter > -1) &&
|
||||||
|
(he->socket != hists->socket_filter)) {
|
||||||
|
he->filtered |= (1 << HIST_FILTER__SOCKET);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void events_stats__inc(struct events_stats *stats, u32 type)
|
void events_stats__inc(struct events_stats *stats, u32 type)
|
||||||
{
|
{
|
||||||
++stats->nr_events[0];
|
++stats->nr_events[0];
|
||||||
|
@ -1520,6 +1535,7 @@ static int hists_evsel__init(struct perf_evsel *evsel)
|
||||||
hists->entries_collapsed = RB_ROOT;
|
hists->entries_collapsed = RB_ROOT;
|
||||||
hists->entries = RB_ROOT;
|
hists->entries = RB_ROOT;
|
||||||
pthread_mutex_init(&hists->lock, NULL);
|
pthread_mutex_init(&hists->lock, NULL);
|
||||||
|
hists->socket_filter = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ enum hist_filter {
|
||||||
HIST_FILTER__SYMBOL,
|
HIST_FILTER__SYMBOL,
|
||||||
HIST_FILTER__GUEST,
|
HIST_FILTER__GUEST,
|
||||||
HIST_FILTER__HOST,
|
HIST_FILTER__HOST,
|
||||||
|
HIST_FILTER__SOCKET,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum hist_column {
|
enum hist_column {
|
||||||
|
@ -71,6 +72,7 @@ struct hists {
|
||||||
struct events_stats stats;
|
struct events_stats stats;
|
||||||
u64 event_stream;
|
u64 event_stream;
|
||||||
u16 col_len[HISTC_NR_COLS];
|
u16 col_len[HISTC_NR_COLS];
|
||||||
|
int socket_filter;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hist_entry_iter;
|
struct hist_entry_iter;
|
||||||
|
@ -149,7 +151,7 @@ void hists__filter_by_symbol(struct hists *hists);
|
||||||
static inline bool hists__has_filter(struct hists *hists)
|
static inline bool hists__has_filter(struct hists *hists)
|
||||||
{
|
{
|
||||||
return hists->thread_filter || hists->dso_filter ||
|
return hists->thread_filter || hists->dso_filter ||
|
||||||
hists->symbol_filter_str;
|
hists->symbol_filter_str || (hists->socket_filter > -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 hists__col_len(struct hists *hists, enum hist_column col);
|
u16 hists__col_len(struct hists *hists, enum hist_column col);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче