Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Conflicts:
	tools/perf/builtin-stat.c
This commit is contained in:
Ingo Molnar 2011-08-18 21:58:46 +02:00
commit 51887c8230
8 changed files with 126 additions and 66 deletions

View file

@ -72,6 +72,17 @@ OPTIONS
CPUs are specified with -: 0-2. Default is to report samples on all CPUs are specified with -: 0-2. Default is to report samples on all
CPUs. CPUs.
--asm-raw::
Show raw instruction encoding of assembly instructions. They
are displayed by default, disable with --no-asm-raw.
--source::
Interleave source code with assembly code. Enabled by default,
disable with --no-source.
--symfs=<directory>::
Look for files with symbols relative to this directory.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-report[1] linkperf:perf-record[1], linkperf:perf-report[1]

View file

@ -94,6 +94,13 @@ an empty cgroup (monitor all the time) using, e.g., -G foo,,bar. Cgroups must ha
corresponding events, i.e., they always refer to events defined earlier on the command corresponding events, i.e., they always refer to events defined earlier on the command
line. line.
-o file::
-output file::
Print the output into the designated file.
--append::
Append to the output file designated with the -o option. Ignored if -o is not specified.
EXAMPLES EXAMPLES
-------- --------

View file

@ -267,6 +267,12 @@ static const struct option options[] = {
OPT_BOOLEAN('P', "full-paths", &full_paths, OPT_BOOLEAN('P', "full-paths", &full_paths,
"Don't shorten the displayed pathnames"), "Don't shorten the displayed pathnames"),
OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"), OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_BOOLEAN('0', "source", &symbol_conf.annotate_src,
"Interleave source code with assembly code (default)"),
OPT_BOOLEAN('0', "asm-raw", &symbol_conf.annotate_asm_raw,
"Display raw encoding of assembly instructions (default)"),
OPT_END() OPT_END()
}; };

View file

@ -194,6 +194,8 @@ static const char *cpu_list;
static const char *csv_sep = NULL; static const char *csv_sep = NULL;
static bool csv_output = false; static bool csv_output = false;
static bool group = false; static bool group = false;
static const char *output_name = NULL;
static FILE *output = NULL;
static volatile int done = 0; static volatile int done = 0;
@ -352,7 +354,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
update_stats(&ps->res_stats[i], count[i]); update_stats(&ps->res_stats[i], count[i]);
if (verbose) { if (verbose) {
fprintf(stderr, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
event_name(counter), count[0], count[1], count[2]); event_name(counter), count[0], count[1], count[2]);
} }
@ -519,9 +521,9 @@ static void print_noise_pct(double total, double avg)
pct = 100.0*total/avg; pct = 100.0*total/avg;
if (csv_output) if (csv_output)
fprintf(stderr, "%s%.2f%%", csv_sep, pct); fprintf(output, "%s%.2f%%", csv_sep, pct);
else else
fprintf(stderr, " ( +-%6.2f%% )", pct); fprintf(output, " ( +-%6.2f%% )", pct);
} }
static void print_noise(struct perf_evsel *evsel, double avg) static void print_noise(struct perf_evsel *evsel, double avg)
@ -546,16 +548,17 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
csv_output ? 0 : -4, csv_output ? 0 : -4,
evsel_list->cpus->map[cpu], csv_sep); evsel_list->cpus->map[cpu], csv_sep);
fprintf(stderr, fmt, cpustr, msecs, csv_sep, event_name(evsel)); fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel));
if (evsel->cgrp) if (evsel->cgrp)
fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
if (csv_output) if (csv_output)
return; return;
if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK))
fprintf(stderr, " # %8.3f CPUs utilized ", avg / avg_stats(&walltime_nsecs_stats)); fprintf(output, " # %8.3f CPUs utilized ",
avg / avg_stats(&walltime_nsecs_stats));
} }
static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg) static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __used, double avg)
@ -576,9 +579,9 @@ static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __us
else if (ratio > 10.0) else if (ratio > 10.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " frontend cycles idle "); fprintf(output, " frontend cycles idle ");
} }
static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg) static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg)
@ -599,9 +602,9 @@ static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __use
else if (ratio > 20.0) else if (ratio > 20.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " backend cycles idle "); fprintf(output, " backend cycles idle ");
} }
static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg) static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@ -622,9 +625,9 @@ static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double
else if (ratio > 5.0) else if (ratio > 5.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " of all branches "); fprintf(output, " of all branches ");
} }
static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg) static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@ -645,9 +648,9 @@ static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, dou
else if (ratio > 5.0) else if (ratio > 5.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " of all L1-dcache hits "); fprintf(output, " of all L1-dcache hits ");
} }
static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg) static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@ -668,9 +671,9 @@ static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, dou
else if (ratio > 5.0) else if (ratio > 5.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " of all L1-icache hits "); fprintf(output, " of all L1-icache hits ");
} }
static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@ -691,9 +694,9 @@ static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
else if (ratio > 5.0) else if (ratio > 5.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " of all dTLB cache hits "); fprintf(output, " of all dTLB cache hits ");
} }
static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@ -714,9 +717,9 @@ static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
else if (ratio > 5.0) else if (ratio > 5.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " of all iTLB cache hits "); fprintf(output, " of all iTLB cache hits ");
} }
static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg) static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
@ -737,9 +740,9 @@ static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, doub
else if (ratio > 5.0) else if (ratio > 5.0)
color = PERF_COLOR_YELLOW; color = PERF_COLOR_YELLOW;
fprintf(stderr, " # "); fprintf(output, " # ");
color_fprintf(stderr, color, "%6.2f%%", ratio); color_fprintf(output, color, "%6.2f%%", ratio);
fprintf(stderr, " of all LL-cache hits "); fprintf(output, " of all LL-cache hits ");
} }
static void abs_printout(int cpu, struct perf_evsel *evsel, double avg) static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
@ -762,10 +765,10 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
else else
cpu = 0; cpu = 0;
fprintf(stderr, fmt, cpustr, avg, csv_sep, event_name(evsel)); fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel));
if (evsel->cgrp) if (evsel->cgrp)
fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name); fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
if (csv_output) if (csv_output)
return; return;
@ -776,14 +779,14 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
if (total) if (total)
ratio = avg / total; ratio = avg / total;
fprintf(stderr, " # %5.2f insns per cycle ", ratio); fprintf(output, " # %5.2f insns per cycle ", ratio);
total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]); total = avg_stats(&runtime_stalled_cycles_front_stats[cpu]);
total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu])); total = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
if (total && avg) { if (total && avg) {
ratio = total / avg; ratio = total / avg;
fprintf(stderr, "\n # %5.2f stalled cycles per insn", ratio); fprintf(output, "\n # %5.2f stalled cycles per insn", ratio);
} }
} else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) && } else if (perf_evsel__match(evsel, HARDWARE, HW_BRANCH_MISSES) &&
@ -831,7 +834,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
if (total) if (total)
ratio = avg * 100 / total; ratio = avg * 100 / total;
fprintf(stderr, " # %8.3f %% of all cache refs ", ratio); fprintf(output, " # %8.3f %% of all cache refs ", ratio);
} else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) { } else if (perf_evsel__match(evsel, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) {
print_stalled_cycles_frontend(cpu, evsel, avg); print_stalled_cycles_frontend(cpu, evsel, avg);
@ -843,16 +846,16 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
if (total) if (total)
ratio = 1.0 * avg / total; ratio = 1.0 * avg / total;
fprintf(stderr, " # %8.3f GHz ", ratio); fprintf(output, " # %8.3f GHz ", ratio);
} else if (runtime_nsecs_stats[cpu].n != 0) { } else if (runtime_nsecs_stats[cpu].n != 0) {
total = avg_stats(&runtime_nsecs_stats[cpu]); total = avg_stats(&runtime_nsecs_stats[cpu]);
if (total) if (total)
ratio = 1000.0 * avg / total; ratio = 1000.0 * avg / total;
fprintf(stderr, " # %8.3f M/sec ", ratio); fprintf(output, " # %8.3f M/sec ", ratio);
} else { } else {
fprintf(stderr, " "); fprintf(output, " ");
} }
} }
@ -867,7 +870,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
int scaled = counter->counts->scaled; int scaled = counter->counts->scaled;
if (scaled == -1) { if (scaled == -1) {
fprintf(stderr, "%*s%s%*s", fprintf(output, "%*s%s%*s",
csv_output ? 0 : 18, csv_output ? 0 : 18,
counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED, counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
csv_sep, csv_sep,
@ -875,9 +878,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
event_name(counter)); event_name(counter));
if (counter->cgrp) if (counter->cgrp)
fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
fputc('\n', stderr); fputc('\n', output);
return; return;
} }
@ -889,7 +892,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
print_noise(counter, avg); print_noise(counter, avg);
if (csv_output) { if (csv_output) {
fputc('\n', stderr); fputc('\n', output);
return; return;
} }
@ -899,9 +902,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
avg_enabled = avg_stats(&ps->res_stats[1]); avg_enabled = avg_stats(&ps->res_stats[1]);
avg_running = avg_stats(&ps->res_stats[2]); avg_running = avg_stats(&ps->res_stats[2]);
fprintf(stderr, " [%5.2f%%]", 100 * avg_running / avg_enabled); fprintf(output, " [%5.2f%%]", 100 * avg_running / avg_enabled);
} }
fprintf(stderr, "\n"); fprintf(output, "\n");
} }
/* /*
@ -918,7 +921,7 @@ static void print_counter(struct perf_evsel *counter)
ena = counter->counts->cpu[cpu].ena; ena = counter->counts->cpu[cpu].ena;
run = counter->counts->cpu[cpu].run; run = counter->counts->cpu[cpu].run;
if (run == 0 || ena == 0) { if (run == 0 || ena == 0) {
fprintf(stderr, "CPU%*d%s%*s%s%*s", fprintf(output, "CPU%*d%s%*s%s%*s",
csv_output ? 0 : -4, csv_output ? 0 : -4,
evsel_list->cpus->map[cpu], csv_sep, evsel_list->cpus->map[cpu], csv_sep,
csv_output ? 0 : 18, csv_output ? 0 : 18,
@ -928,9 +931,10 @@ static void print_counter(struct perf_evsel *counter)
event_name(counter)); event_name(counter));
if (counter->cgrp) if (counter->cgrp)
fprintf(stderr, "%s%s", csv_sep, counter->cgrp->name); fprintf(output, "%s%s",
csv_sep, counter->cgrp->name);
fputc('\n', stderr); fputc('\n', output);
continue; continue;
} }
@ -943,9 +947,10 @@ static void print_counter(struct perf_evsel *counter)
print_noise(counter, 1.0); print_noise(counter, 1.0);
if (run != ena) if (run != ena)
fprintf(stderr, " (%.2f%%)", 100.0 * run / ena); fprintf(output, " (%.2f%%)",
100.0 * run / ena);
} }
fputc('\n', stderr); fputc('\n', output);
} }
} }
@ -957,21 +962,21 @@ static void print_stat(int argc, const char **argv)
fflush(stdout); fflush(stdout);
if (!csv_output) { if (!csv_output) {
fprintf(stderr, "\n"); fprintf(output, "\n");
fprintf(stderr, " Performance counter stats for "); fprintf(output, " Performance counter stats for ");
if(target_pid == -1 && target_tid == -1) { if(target_pid == -1 && target_tid == -1) {
fprintf(stderr, "\'%s", argv[0]); fprintf(output, "\'%s", argv[0]);
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
fprintf(stderr, " %s", argv[i]); fprintf(output, " %s", argv[i]);
} else if (target_pid != -1) } else if (target_pid != -1)
fprintf(stderr, "process id \'%d", target_pid); fprintf(output, "process id \'%d", target_pid);
else else
fprintf(stderr, "thread id \'%d", target_tid); fprintf(output, "thread id \'%d", target_tid);
fprintf(stderr, "\'"); fprintf(output, "\'");
if (run_count > 1) if (run_count > 1)
fprintf(stderr, " (%d runs)", run_count); fprintf(output, " (%d runs)", run_count);
fprintf(stderr, ":\n\n"); fprintf(output, ":\n\n");
} }
if (no_aggr) { if (no_aggr) {
@ -984,15 +989,15 @@ static void print_stat(int argc, const char **argv)
if (!csv_output) { if (!csv_output) {
if (!null_run) if (!null_run)
fprintf(stderr, "\n"); fprintf(output, "\n");
fprintf(stderr, " %17.9f seconds time elapsed", fprintf(output, " %17.9f seconds time elapsed",
avg_stats(&walltime_nsecs_stats)/1e9); avg_stats(&walltime_nsecs_stats)/1e9);
if (run_count > 1) { if (run_count > 1) {
fprintf(stderr, " "); fprintf(output, " ");
print_noise_pct(stddev_stats(&walltime_nsecs_stats), print_noise_pct(stddev_stats(&walltime_nsecs_stats),
avg_stats(&walltime_nsecs_stats)); avg_stats(&walltime_nsecs_stats));
} }
fprintf(stderr, "\n\n"); fprintf(output, "\n\n");
} }
} }
@ -1030,6 +1035,8 @@ static int stat__set_big_num(const struct option *opt __used,
return 0; return 0;
} }
static bool append_file;
static const struct option options[] = { static const struct option options[] = {
OPT_CALLBACK('e', "event", &evsel_list, "event", OPT_CALLBACK('e', "event", &evsel_list, "event",
"event selector. use 'perf list' to list available events", "event selector. use 'perf list' to list available events",
@ -1070,6 +1077,9 @@ static const struct option options[] = {
OPT_CALLBACK('G', "cgroup", &evsel_list, "name", OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
"monitor event in cgroup name only", "monitor event in cgroup name only",
parse_cgroups), parse_cgroups),
OPT_STRING('o', "output", &output_name, "file",
"output file name"),
OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
OPT_END() OPT_END()
}; };
@ -1141,6 +1151,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
int status = -ENOMEM; int status = -ENOMEM;
const char *mode;
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
@ -1151,6 +1162,23 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
argc = parse_options(argc, argv, options, stat_usage, argc = parse_options(argc, argv, options, stat_usage,
PARSE_OPT_STOP_AT_NON_OPTION); PARSE_OPT_STOP_AT_NON_OPTION);
output = stderr;
if (output_name && strcmp(output_name, "-"))
output = NULL;
if (!output) {
struct timespec tm;
mode = append_file ? "a" : "w";
output = fopen(output_name, mode);
if (!output) {
perror("failed to create output file");
exit(-1);
}
clock_gettime(CLOCK_REALTIME, &tm);
fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
}
if (csv_sep) if (csv_sep)
csv_output = true; csv_output = true;
else else
@ -1226,7 +1254,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
status = 0; status = 0;
for (run_idx = 0; run_idx < run_count; run_idx++) { for (run_idx = 0; run_idx < run_count; run_idx++) {
if (run_count != 1 && verbose) if (run_count != 1 && verbose)
fprintf(stderr, "[ perf stat: executing run #%d ... ]\n", run_idx + 1); fprintf(output, "[ perf stat: executing run #%d ... ]\n",
run_idx + 1);
if (sync_run) if (sync_run)
sync(); sync();

View file

@ -324,9 +324,12 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
snprintf(command, sizeof(command), snprintf(command, sizeof(command),
"objdump --start-address=0x%016" PRIx64 "objdump --start-address=0x%016" PRIx64
" --stop-address=0x%016" PRIx64 " -dS -C %s|grep -v %s|expand", " --stop-address=0x%016" PRIx64
" -d %s %s -C %s|grep -v %s|expand",
map__rip_2objdump(map, sym->start), map__rip_2objdump(map, sym->start),
map__rip_2objdump(map, sym->end), map__rip_2objdump(map, sym->end),
symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
symbol_conf.annotate_src ? "-S" : "",
symfs_filename, filename); symfs_filename, filename);
pr_debug("Executing: %s\n", command); pr_debug("Executing: %s\n", command);

View file

@ -200,7 +200,7 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
* Auto-detect: * Auto-detect:
*/ */
if (perf_use_color_default < 0) { if (perf_use_color_default < 0) {
if (isatty(1) || pager_in_use()) if (isatty(fileno(fp)) || pager_in_use())
perf_use_color_default = 1; perf_use_color_default = 1;
else else
perf_use_color_default = 0; perf_use_color_default = 0;

View file

@ -46,6 +46,8 @@ struct symbol_conf symbol_conf = {
.exclude_other = true, .exclude_other = true,
.use_modules = true, .use_modules = true,
.try_vmlinux_path = true, .try_vmlinux_path = true,
.annotate_asm_raw = true,
.annotate_src = true,
.symfs = "", .symfs = "",
}; };

View file

@ -76,7 +76,9 @@ struct symbol_conf {
exclude_other, exclude_other,
show_cpu_utilization, show_cpu_utilization,
initialized, initialized,
kptr_restrict; kptr_restrict,
annotate_asm_raw,
annotate_src;
const char *vmlinux_name, const char *vmlinux_name,
*kallsyms_name, *kallsyms_name,
*source_prefix, *source_prefix,