You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (121 commits)
perf symbols: Increase symbol KSYM_NAME_LEN size
perf hists browser: Refuse 'a' hotkey on non symbolic views
perf ui browser: Use libslang to read keys
perf tools: Fix tracing info recording
perf hists browser: Elide DSO column when it is set to just one DSO, ditto for threads
perf hists: Don't consider filtered entries when calculating column widths
perf hists: Don't decay total_period for filtered entries
perf hists browser: Honour symbol_conf.show_{nr_samples,total_period}
perf hists browser: Do not exit on tab key with single event
perf annotate browser: Don't change selection line when returning from callq
perf tools: handle endianness of feature bitmap
perf tools: Add prelink suggestion to dso update message
perf script: Fix unknown feature comment
perf hists browser: Apply the dso and thread filters when merging new batches
perf hists: Move the dso and thread filters from hist_browser
perf ui browser: Honour the xterm colors
perf top tui: Give color hints just on the percentage, like on --stdio
perf ui browser: Make the colors configurable and change the defaults
perf tui: Remove unneeded call to newtCls on startup
perf hists: Don't format the percentage on hist_entry__snprintf
...
Fix up conflicts in arch/x86/kernel/kprobes.c manually.
Ingo's tree did the insane "add volatile to const array", which just
doesn't make sense ("volatile const"?). But we could remove the const
*and* make the array volatile to make doubly sure that gcc doesn't
optimize it away..
Also fix up kernel/trace/ring_buffer.c non-data-conflicts manually: the
reader_lock has been turned into a raw lock by the core locking merge,
and there was a new user of it introduced in this perf core merge. Make
sure that new use also uses the raw accessor functions.
This commit is contained in:
@@ -72,6 +72,19 @@ OPTIONS
|
||||
CPUs are specified with -: 0-2. Default is to report samples on all
|
||||
CPUs.
|
||||
|
||||
--asm-raw::
|
||||
Show raw instruction encoding of assembly instructions.
|
||||
|
||||
--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.
|
||||
|
||||
-M::
|
||||
--disassembler-style=:: Set disassembler style for objdump.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-record[1], linkperf:perf-report[1]
|
||||
|
||||
@@ -16,6 +16,9 @@ This command displays the buildids found in a perf.data file, so that other
|
||||
tools can be used to fetch packages with matching symbol tables for use by
|
||||
perf report.
|
||||
|
||||
It can also be used to show the build id of the running kernel or in an ELF
|
||||
file using -i/--input.
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-H::
|
||||
@@ -27,6 +30,9 @@ OPTIONS
|
||||
-f::
|
||||
--force::
|
||||
Don't do ownership validation.
|
||||
-k::
|
||||
--kernel::
|
||||
Show running kernel build id.
|
||||
-v::
|
||||
--verbose::
|
||||
Be more verbose.
|
||||
|
||||
@@ -134,6 +134,24 @@ OPTIONS
|
||||
CPUs are specified with -: 0-2. Default is to report samples on all
|
||||
CPUs.
|
||||
|
||||
-M::
|
||||
--disassembler-style=:: Set disassembler style for objdump.
|
||||
|
||||
--source::
|
||||
Interleave source code with assembly code. Enabled by default,
|
||||
disable with --no-source.
|
||||
|
||||
--asm-raw::
|
||||
Show raw instruction encoding of assembly instructions.
|
||||
|
||||
--show-total-period:: Show a column with the sum of periods.
|
||||
|
||||
-I::
|
||||
--show-info::
|
||||
Display extended information about the perf.data file. This adds
|
||||
information which may be very large and thus may clutter the display.
|
||||
It currently includes: cpu and numa topology of the host system.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-stat[1]
|
||||
linkperf:perf-stat[1], linkperf:perf-annotate[1]
|
||||
|
||||
@@ -8,7 +8,7 @@ perf-sched - Tool to trace/measure scheduler properties (latencies)
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'perf sched' {record|latency|map|replay|trace}
|
||||
'perf sched' {record|latency|map|replay|script}
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@@ -20,8 +20,8 @@ There are five variants of perf sched:
|
||||
'perf sched latency' to report the per task scheduling latencies
|
||||
and other scheduling properties of the workload.
|
||||
|
||||
'perf sched trace' to see a detailed trace of the workload that
|
||||
was recorded.
|
||||
'perf sched script' to see a detailed trace of the workload that
|
||||
was recorded (aliased to 'perf script' for now).
|
||||
|
||||
'perf sched replay' to simulate the workload that was recorded
|
||||
via perf sched record. (this is done by starting up mockup threads
|
||||
|
||||
@@ -188,6 +188,13 @@ OPTIONS
|
||||
CPUs are specified with -: 0-2. Default is to report samples on all
|
||||
CPUs.
|
||||
|
||||
-I::
|
||||
--show-info::
|
||||
Display extended information about the perf.data file. This adds
|
||||
information which may be very large and thus may clutter the display.
|
||||
It currently includes: cpu and numa topology of the host system.
|
||||
It can only be used with the perf script report mode.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-record[1], linkperf:perf-script-perl[1],
|
||||
|
||||
@@ -94,6 +94,22 @@ 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
|
||||
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.
|
||||
|
||||
--log-fd::
|
||||
|
||||
Log output to fd, instead of stderr. Complementary to --output, and mutually exclusive
|
||||
with it. --append may be used here. Examples:
|
||||
3>results perf stat --log-fd 3 -- $cmd
|
||||
3>>results perf stat --log-fd 3 --append -- $cmd
|
||||
|
||||
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
|
||||
@@ -106,6 +106,51 @@ Default is to monitor all CPUS.
|
||||
--zero::
|
||||
Zero history across display updates.
|
||||
|
||||
-s::
|
||||
--sort::
|
||||
Sort by key(s): pid, comm, dso, symbol, parent
|
||||
|
||||
-n::
|
||||
--show-nr-samples::
|
||||
Show a column with the number of samples.
|
||||
|
||||
--show-total-period::
|
||||
Show a column with the sum of periods.
|
||||
|
||||
--dsos::
|
||||
Only consider symbols in these dsos.
|
||||
|
||||
--comms::
|
||||
Only consider symbols in these comms.
|
||||
|
||||
--symbols::
|
||||
Only consider these symbols.
|
||||
|
||||
-M::
|
||||
--disassembler-style=:: Set disassembler style for objdump.
|
||||
|
||||
--source::
|
||||
Interleave source code with assembly code. Enabled by default,
|
||||
disable with --no-source.
|
||||
|
||||
--asm-raw::
|
||||
Show raw instruction encoding of assembly instructions.
|
||||
|
||||
-G [type,min,order]::
|
||||
--call-graph::
|
||||
Display call chains using type, min percent threshold and order.
|
||||
type can be either:
|
||||
- flat: single column, linear exposure of call chains.
|
||||
- graph: use a graph tree, displaying absolute overhead rates.
|
||||
- fractal: like graph, but displays relative rates. Each branch of
|
||||
the tree is considered as a new profiled object.
|
||||
|
||||
order can be either:
|
||||
- callee: callee based call graph.
|
||||
- caller: inverted caller based call graph.
|
||||
|
||||
Default: fractal,0.5,callee.
|
||||
|
||||
INTERACTIVE PROMPTING KEYS
|
||||
--------------------------
|
||||
|
||||
@@ -130,9 +175,6 @@ INTERACTIVE PROMPTING KEYS
|
||||
[S]::
|
||||
Stop annotation, return to full profile display.
|
||||
|
||||
[w]::
|
||||
Toggle between weighted sum and individual count[E]r profile.
|
||||
|
||||
[z]::
|
||||
Toggle event count zeroing across display updates.
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[colors]
|
||||
|
||||
# These were the old defaults
|
||||
top = red, lightgray
|
||||
medium = green, lightgray
|
||||
normal = black, lightgray
|
||||
selected = lightgray, magenta
|
||||
code = blue, lightgray
|
||||
|
||||
[tui]
|
||||
|
||||
# Defaults if linked with libslang
|
||||
report = on
|
||||
annotate = on
|
||||
top = on
|
||||
|
||||
[buildid]
|
||||
|
||||
# Default, disable using /dev/null
|
||||
dir = /root/.debug
|
||||
+1
-4
@@ -466,13 +466,13 @@ else
|
||||
LIB_OBJS += $(OUTPUT)util/ui/browsers/annotate.o
|
||||
LIB_OBJS += $(OUTPUT)util/ui/browsers/hists.o
|
||||
LIB_OBJS += $(OUTPUT)util/ui/browsers/map.o
|
||||
LIB_OBJS += $(OUTPUT)util/ui/browsers/top.o
|
||||
LIB_OBJS += $(OUTPUT)util/ui/helpline.o
|
||||
LIB_OBJS += $(OUTPUT)util/ui/progress.o
|
||||
LIB_OBJS += $(OUTPUT)util/ui/util.o
|
||||
LIB_H += util/ui/browser.h
|
||||
LIB_H += util/ui/browsers/map.h
|
||||
LIB_H += util/ui/helpline.h
|
||||
LIB_H += util/ui/keysyms.h
|
||||
LIB_H += util/ui/libslang.h
|
||||
LIB_H += util/ui/progress.h
|
||||
LIB_H += util/ui/util.h
|
||||
@@ -729,9 +729,6 @@ $(OUTPUT)util/ui/browser.o: util/ui/browser.c $(OUTPUT)PERF-CFLAGS
|
||||
$(OUTPUT)util/ui/browsers/annotate.o: util/ui/browsers/annotate.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
|
||||
|
||||
$(OUTPUT)util/ui/browsers/top.o: util/ui/browsers/top.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
|
||||
|
||||
$(OUTPUT)util/ui/browsers/hists.o: util/ui/browsers/hists.c $(OUTPUT)PERF-CFLAGS
|
||||
$(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DENABLE_SLFUTURE_CONST $<
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@ ifndef NO_DWARF
|
||||
PERF_HAVE_DWARF_REGS := 1
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
|
||||
endif
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../util/header.h"
|
||||
|
||||
#define __stringify_1(x) #x
|
||||
#define __stringify(x) __stringify_1(x)
|
||||
|
||||
#define mfspr(rn) ({unsigned long rval; \
|
||||
asm volatile("mfspr %0," __stringify(rn) \
|
||||
: "=r" (rval)); rval; })
|
||||
|
||||
#define SPRN_PVR 0x11F /* Processor Version Register */
|
||||
#define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) /* Version field */
|
||||
#define PVR_REV(pvr) (((pvr) >> 0) & 0xFFFF) /* Revison field */
|
||||
|
||||
int
|
||||
get_cpuid(char *buffer, size_t sz)
|
||||
{
|
||||
unsigned long pvr;
|
||||
int nb;
|
||||
|
||||
pvr = mfspr(SPRN_PVR);
|
||||
|
||||
nb = snprintf(buffer, sz, "%lu,%lu$", PVR_VER(pvr), PVR_REV(pvr));
|
||||
|
||||
/* look for end marker to ensure the entire data fit */
|
||||
if (strchr(buffer, '$')) {
|
||||
buffer[nb-1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -2,3 +2,4 @@ ifndef NO_DWARF
|
||||
PERF_HAVE_DWARF_REGS := 1
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
|
||||
endif
|
||||
LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/header.o
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../util/header.h"
|
||||
|
||||
static inline void
|
||||
cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
|
||||
unsigned int *d)
|
||||
{
|
||||
__asm__ __volatile__ (".byte 0x53\n\tcpuid\n\t"
|
||||
"movl %%ebx, %%esi\n\t.byte 0x5b"
|
||||
: "=a" (*a),
|
||||
"=S" (*b),
|
||||
"=c" (*c),
|
||||
"=d" (*d)
|
||||
: "a" (op));
|
||||
}
|
||||
|
||||
int
|
||||
get_cpuid(char *buffer, size_t sz)
|
||||
{
|
||||
unsigned int a, b, c, d, lvl;
|
||||
int family = -1, model = -1, step = -1;
|
||||
int nb;
|
||||
char vendor[16];
|
||||
|
||||
cpuid(0, &lvl, &b, &c, &d);
|
||||
strncpy(&vendor[0], (char *)(&b), 4);
|
||||
strncpy(&vendor[4], (char *)(&d), 4);
|
||||
strncpy(&vendor[8], (char *)(&c), 4);
|
||||
vendor[12] = '\0';
|
||||
|
||||
if (lvl >= 1) {
|
||||
cpuid(1, &a, &b, &c, &d);
|
||||
|
||||
family = (a >> 8) & 0xf; /* bits 11 - 8 */
|
||||
model = (a >> 4) & 0xf; /* Bits 7 - 4 */
|
||||
step = a & 0xf;
|
||||
|
||||
/* extended family */
|
||||
if (family == 0xf)
|
||||
family += (a >> 20) & 0xff;
|
||||
|
||||
/* extended model */
|
||||
if (family >= 0x6)
|
||||
model += ((a >> 16) & 0xf) << 4;
|
||||
}
|
||||
nb = snprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step);
|
||||
|
||||
/* look for end marker to ensure the entire data fit */
|
||||
if (strchr(buffer, '$')) {
|
||||
buffer[nb-1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -114,10 +114,11 @@ static int hist_entry__tty_annotate(struct hist_entry *he, int evidx)
|
||||
print_line, full_paths, 0, 0);
|
||||
}
|
||||
|
||||
static void hists__find_annotations(struct hists *self, int evidx)
|
||||
static void hists__find_annotations(struct hists *self, int evidx,
|
||||
int nr_events)
|
||||
{
|
||||
struct rb_node *nd = rb_first(&self->entries), *next;
|
||||
int key = KEY_RIGHT;
|
||||
int key = K_RIGHT;
|
||||
|
||||
while (nd) {
|
||||
struct hist_entry *he = rb_entry(nd, struct hist_entry, rb_node);
|
||||
@@ -129,7 +130,7 @@ static void hists__find_annotations(struct hists *self, int evidx)
|
||||
notes = symbol__annotation(he->ms.sym);
|
||||
if (notes->src == NULL) {
|
||||
find_next:
|
||||
if (key == KEY_LEFT)
|
||||
if (key == K_LEFT)
|
||||
nd = rb_prev(nd);
|
||||
else
|
||||
nd = rb_next(nd);
|
||||
@@ -137,12 +138,13 @@ find_next:
|
||||
}
|
||||
|
||||
if (use_browser > 0) {
|
||||
key = hist_entry__tui_annotate(he, evidx);
|
||||
key = hist_entry__tui_annotate(he, evidx, nr_events,
|
||||
NULL, NULL, 0);
|
||||
switch (key) {
|
||||
case KEY_RIGHT:
|
||||
case K_RIGHT:
|
||||
next = rb_next(nd);
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
case K_LEFT:
|
||||
next = rb_prev(nd);
|
||||
break;
|
||||
default:
|
||||
@@ -215,7 +217,8 @@ static int __cmd_annotate(void)
|
||||
total_nr_samples += nr_samples;
|
||||
hists__collapse_resort(hists);
|
||||
hists__output_resort(hists);
|
||||
hists__find_annotations(hists, pos->idx);
|
||||
hists__find_annotations(hists, pos->idx,
|
||||
session->evlist->nr_entries);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,6 +270,14 @@ static const struct option options[] = {
|
||||
OPT_BOOLEAN('P', "full-paths", &full_paths,
|
||||
"Don't shorten the displayed pathnames"),
|
||||
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_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
|
||||
"Specify disassembler style (e.g. -M intel for intel syntax)"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* builtin-buildid-list.c
|
||||
*
|
||||
* Builtin buildid-list command: list buildids in perf.data
|
||||
* Builtin buildid-list command: list buildids in perf.data, in the running
|
||||
* kernel and in ELF files.
|
||||
*
|
||||
* Copyright (C) 2009, Red Hat Inc.
|
||||
* Copyright (C) 2009, Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||
@@ -15,8 +16,11 @@
|
||||
#include "util/session.h"
|
||||
#include "util/symbol.h"
|
||||
|
||||
#include <libelf.h>
|
||||
|
||||
static char const *input_name = "perf.data";
|
||||
static bool force;
|
||||
static bool show_kernel;
|
||||
static bool with_hits;
|
||||
|
||||
static const char * const buildid_list_usage[] = {
|
||||
@@ -29,12 +33,13 @@ static const struct option options[] = {
|
||||
OPT_STRING('i', "input", &input_name, "file",
|
||||
"input file name"),
|
||||
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
|
||||
OPT_BOOLEAN('k', "kernel", &show_kernel, "Show current kernel build id"),
|
||||
OPT_INCR('v', "verbose", &verbose,
|
||||
"be more verbose"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
static int __cmd_buildid_list(void)
|
||||
static int perf_session__list_build_ids(void)
|
||||
{
|
||||
struct perf_session *session;
|
||||
|
||||
@@ -52,6 +57,49 @@ static int __cmd_buildid_list(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sysfs__fprintf_build_id(FILE *fp)
|
||||
{
|
||||
u8 kallsyms_build_id[BUILD_ID_SIZE];
|
||||
char sbuild_id[BUILD_ID_SIZE * 2 + 1];
|
||||
|
||||
if (sysfs__read_build_id("/sys/kernel/notes", kallsyms_build_id,
|
||||
sizeof(kallsyms_build_id)) != 0)
|
||||
return -1;
|
||||
|
||||
build_id__sprintf(kallsyms_build_id, sizeof(kallsyms_build_id),
|
||||
sbuild_id);
|
||||
fprintf(fp, "%s\n", sbuild_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int filename__fprintf_build_id(const char *name, FILE *fp)
|
||||
{
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
char sbuild_id[BUILD_ID_SIZE * 2 + 1];
|
||||
|
||||
if (filename__read_build_id(name, build_id,
|
||||
sizeof(build_id)) != sizeof(build_id))
|
||||
return 0;
|
||||
|
||||
build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
|
||||
return fprintf(fp, "%s\n", sbuild_id);
|
||||
}
|
||||
|
||||
static int __cmd_buildid_list(void)
|
||||
{
|
||||
if (show_kernel)
|
||||
return sysfs__fprintf_build_id(stdout);
|
||||
|
||||
elf_version(EV_CURRENT);
|
||||
/*
|
||||
* See if this is an ELF file first:
|
||||
*/
|
||||
if (filename__fprintf_build_id(input_name, stdout))
|
||||
return 0;
|
||||
|
||||
return perf_session__list_build_ids();
|
||||
}
|
||||
|
||||
int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
argc = parse_options(argc, argv, options, buildid_list_usage, 0);
|
||||
|
||||
@@ -162,7 +162,7 @@ static int __cmd_diff(void)
|
||||
|
||||
hists__match(&session[0]->hists, &session[1]->hists);
|
||||
hists__fprintf(&session[1]->hists, &session[0]->hists,
|
||||
show_displacement, stdout);
|
||||
show_displacement, true, 0, 0, stdout);
|
||||
out_delete:
|
||||
for (i = 0; i < 2; ++i)
|
||||
perf_session__delete(session[i]);
|
||||
|
||||
@@ -73,6 +73,7 @@ static off_t post_processing_offset;
|
||||
|
||||
static struct perf_session *session;
|
||||
static const char *cpu_list;
|
||||
static const char *progname;
|
||||
|
||||
static void advance_output(size_t size)
|
||||
{
|
||||
@@ -137,17 +138,29 @@ static void mmap_read(struct perf_mmap *md)
|
||||
|
||||
static volatile int done = 0;
|
||||
static volatile int signr = -1;
|
||||
static volatile int child_finished = 0;
|
||||
|
||||
static void sig_handler(int sig)
|
||||
{
|
||||
if (sig == SIGCHLD)
|
||||
child_finished = 1;
|
||||
|
||||
done = 1;
|
||||
signr = sig;
|
||||
}
|
||||
|
||||
static void sig_atexit(void)
|
||||
{
|
||||
if (child_pid > 0)
|
||||
kill(child_pid, SIGTERM);
|
||||
int status;
|
||||
|
||||
if (child_pid > 0) {
|
||||
if (!child_finished)
|
||||
kill(child_pid, SIGTERM);
|
||||
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status))
|
||||
psignal(WTERMSIG(status), progname);
|
||||
}
|
||||
|
||||
if (signr == -1 || signr == SIGUSR1)
|
||||
return;
|
||||
@@ -446,6 +459,8 @@ static int __cmd_record(int argc, const char **argv)
|
||||
char buf;
|
||||
struct machine *machine;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
page_size = sysconf(_SC_PAGE_SIZE);
|
||||
|
||||
atexit(sig_atexit);
|
||||
@@ -514,6 +529,19 @@ static int __cmd_record(int argc, const char **argv)
|
||||
if (have_tracepoints(&evsel_list->entries))
|
||||
perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
|
||||
|
||||
perf_header__set_feat(&session->header, HEADER_HOSTNAME);
|
||||
perf_header__set_feat(&session->header, HEADER_OSRELEASE);
|
||||
perf_header__set_feat(&session->header, HEADER_ARCH);
|
||||
perf_header__set_feat(&session->header, HEADER_CPUDESC);
|
||||
perf_header__set_feat(&session->header, HEADER_NRCPUS);
|
||||
perf_header__set_feat(&session->header, HEADER_EVENT_DESC);
|
||||
perf_header__set_feat(&session->header, HEADER_CMDLINE);
|
||||
perf_header__set_feat(&session->header, HEADER_VERSION);
|
||||
perf_header__set_feat(&session->header, HEADER_CPU_TOPOLOGY);
|
||||
perf_header__set_feat(&session->header, HEADER_TOTAL_MEM);
|
||||
perf_header__set_feat(&session->header, HEADER_NUMA_TOPOLOGY);
|
||||
perf_header__set_feat(&session->header, HEADER_CPUID);
|
||||
|
||||
/* 512 kiB: default amount of unprivileged mlocked memory */
|
||||
if (mmap_pages == UINT_MAX)
|
||||
mmap_pages = (512 * 1024) / page_size;
|
||||
@@ -785,6 +813,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
||||
int err = -ENOMEM;
|
||||
struct perf_evsel *pos;
|
||||
|
||||
perf_header__set_cmdline(argc, argv);
|
||||
|
||||
evsel_list = perf_evlist__new(NULL, NULL);
|
||||
if (evsel_list == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -40,6 +40,7 @@ static char const *input_name = "perf.data";
|
||||
static bool force, use_tui, use_stdio;
|
||||
static bool hide_unresolved;
|
||||
static bool dont_use_callchains;
|
||||
static bool show_full_info;
|
||||
|
||||
static bool show_threads;
|
||||
static struct perf_read_values show_threads_values;
|
||||
@@ -229,13 +230,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
|
||||
|
||||
list_for_each_entry(pos, &evlist->entries, node) {
|
||||
struct hists *hists = &pos->hists;
|
||||
const char *evname = NULL;
|
||||
|
||||
if (rb_first(&hists->entries) != rb_last(&hists->entries))
|
||||
evname = event_name(pos);
|
||||
const char *evname = event_name(pos);
|
||||
|
||||
hists__fprintf_nr_sample_events(hists, evname, stdout);
|
||||
hists__fprintf(hists, NULL, false, stdout);
|
||||
hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
|
||||
fprintf(stdout, "\n\n");
|
||||
}
|
||||
|
||||
@@ -276,6 +274,9 @@ static int __cmd_report(void)
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
if (use_browser <= 0)
|
||||
perf_session__fprintf_info(session, stdout, show_full_info);
|
||||
|
||||
if (show_threads)
|
||||
perf_read_values_init(&show_threads_values);
|
||||
|
||||
@@ -330,9 +331,10 @@ static int __cmd_report(void)
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
if (use_browser > 0)
|
||||
perf_evlist__tui_browse_hists(session->evlist, help);
|
||||
else
|
||||
if (use_browser > 0) {
|
||||
perf_evlist__tui_browse_hists(session->evlist, help,
|
||||
NULL, NULL, 0);
|
||||
} else
|
||||
perf_evlist__tty_browse_hists(session->evlist, help);
|
||||
|
||||
out_delete:
|
||||
@@ -487,6 +489,16 @@ static const struct option options[] = {
|
||||
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
|
||||
"Look for files with symbols relative to this directory"),
|
||||
OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
|
||||
OPT_BOOLEAN('I', "show-info", &show_full_info,
|
||||
"Display extended information about perf.data file"),
|
||||
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_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
|
||||
"Specify disassembler style (e.g. -M intel for intel syntax)"),
|
||||
OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
|
||||
"Show a column with the sum of periods"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ static u64 last_timestamp;
|
||||
static u64 nr_unordered;
|
||||
extern const struct option record_options[];
|
||||
static bool no_callchain;
|
||||
static bool show_full_info;
|
||||
static const char *cpu_list;
|
||||
static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
|
||||
|
||||
@@ -1083,7 +1084,8 @@ static const struct option options[] = {
|
||||
"comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
|
||||
parse_output_fields),
|
||||
OPT_STRING('c', "cpu", &cpu_list, "cpu", "list of cpus to profile"),
|
||||
|
||||
OPT_BOOLEAN('I', "show-info", &show_full_info,
|
||||
"display extended information from perf.data file"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
@@ -1268,6 +1270,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
|
||||
return -1;
|
||||
}
|
||||
|
||||
perf_session__fprintf_info(session, stdout, show_full_info);
|
||||
|
||||
if (!no_callchain)
|
||||
symbol_conf.use_callchain = true;
|
||||
else
|
||||
|
||||
+121
-69
@@ -194,6 +194,9 @@ static const char *cpu_list;
|
||||
static const char *csv_sep = NULL;
|
||||
static bool csv_output = false;
|
||||
static bool group = false;
|
||||
static const char *output_name = NULL;
|
||||
static FILE *output = NULL;
|
||||
static int output_fd;
|
||||
|
||||
static volatile int done = 0;
|
||||
|
||||
@@ -251,8 +254,13 @@ static double avg_stats(struct stats *stats)
|
||||
*/
|
||||
static double stddev_stats(struct stats *stats)
|
||||
{
|
||||
double variance = stats->M2 / (stats->n - 1);
|
||||
double variance_mean = variance / stats->n;
|
||||
double variance, variance_mean;
|
||||
|
||||
if (!stats->n)
|
||||
return 0.0;
|
||||
|
||||
variance = stats->M2 / (stats->n - 1);
|
||||
variance_mean = variance / stats->n;
|
||||
|
||||
return sqrt(variance_mean);
|
||||
}
|
||||
@@ -352,7 +360,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
|
||||
update_stats(&ps->res_stats[i], count[i]);
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
@@ -487,6 +495,8 @@ static int run_perf_stat(int argc __used, const char **argv)
|
||||
if (forks) {
|
||||
close(go_pipe[1]);
|
||||
wait(&status);
|
||||
if (WIFSIGNALED(status))
|
||||
psignal(WTERMSIG(status), argv[0]);
|
||||
} else {
|
||||
while(!done) sleep(1);
|
||||
}
|
||||
@@ -519,9 +529,9 @@ static void print_noise_pct(double total, double avg)
|
||||
pct = 100.0*total/avg;
|
||||
|
||||
if (csv_output)
|
||||
fprintf(stderr, "%s%.2f%%", csv_sep, pct);
|
||||
else
|
||||
fprintf(stderr, " ( +-%6.2f%% )", pct);
|
||||
fprintf(output, "%s%.2f%%", csv_sep, pct);
|
||||
else if (pct)
|
||||
fprintf(output, " ( +-%6.2f%% )", pct);
|
||||
}
|
||||
|
||||
static void print_noise(struct perf_evsel *evsel, double avg)
|
||||
@@ -546,16 +556,17 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
|
||||
csv_output ? 0 : -4,
|
||||
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)
|
||||
fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
|
||||
fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
|
||||
|
||||
if (csv_output)
|
||||
return;
|
||||
|
||||
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)
|
||||
@@ -576,9 +587,9 @@ static void print_stalled_cycles_frontend(int cpu, struct perf_evsel *evsel __us
|
||||
else if (ratio > 10.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " frontend cycles idle ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " frontend cycles idle ");
|
||||
}
|
||||
|
||||
static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __used, double avg)
|
||||
@@ -599,9 +610,9 @@ static void print_stalled_cycles_backend(int cpu, struct perf_evsel *evsel __use
|
||||
else if (ratio > 20.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " backend cycles idle ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " backend cycles idle ");
|
||||
}
|
||||
|
||||
static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double avg)
|
||||
@@ -622,9 +633,9 @@ static void print_branch_misses(int cpu, struct perf_evsel *evsel __used, double
|
||||
else if (ratio > 5.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " of all branches ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " of all branches ");
|
||||
}
|
||||
|
||||
static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
|
||||
@@ -645,9 +656,9 @@ static void print_l1_dcache_misses(int cpu, struct perf_evsel *evsel __used, dou
|
||||
else if (ratio > 5.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " of all L1-dcache hits ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " of all L1-dcache hits ");
|
||||
}
|
||||
|
||||
static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
|
||||
@@ -668,9 +679,9 @@ static void print_l1_icache_misses(int cpu, struct perf_evsel *evsel __used, dou
|
||||
else if (ratio > 5.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " of all L1-icache hits ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " of all L1-icache hits ");
|
||||
}
|
||||
|
||||
static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
|
||||
@@ -691,9 +702,9 @@ static void print_dtlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
|
||||
else if (ratio > 5.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " of all dTLB cache hits ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " of all dTLB cache hits ");
|
||||
}
|
||||
|
||||
static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
|
||||
@@ -714,9 +725,9 @@ static void print_itlb_cache_misses(int cpu, struct perf_evsel *evsel __used, do
|
||||
else if (ratio > 5.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " of all iTLB cache hits ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " of all iTLB cache hits ");
|
||||
}
|
||||
|
||||
static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, double avg)
|
||||
@@ -737,9 +748,9 @@ static void print_ll_cache_misses(int cpu, struct perf_evsel *evsel __used, doub
|
||||
else if (ratio > 5.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
fprintf(stderr, " # ");
|
||||
color_fprintf(stderr, color, "%6.2f%%", ratio);
|
||||
fprintf(stderr, " of all LL-cache hits ");
|
||||
fprintf(output, " # ");
|
||||
color_fprintf(output, color, "%6.2f%%", ratio);
|
||||
fprintf(output, " of all LL-cache hits ");
|
||||
}
|
||||
|
||||
static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
|
||||
@@ -762,10 +773,10 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
|
||||
else
|
||||
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)
|
||||
fprintf(stderr, "%s%s", csv_sep, evsel->cgrp->name);
|
||||
fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
|
||||
|
||||
if (csv_output)
|
||||
return;
|
||||
@@ -776,14 +787,14 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
|
||||
if (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 = max(total, avg_stats(&runtime_stalled_cycles_back_stats[cpu]));
|
||||
|
||||
if (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) &&
|
||||
@@ -831,7 +842,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
|
||||
if (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)) {
|
||||
print_stalled_cycles_frontend(cpu, evsel, avg);
|
||||
@@ -843,16 +854,16 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
|
||||
if (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) {
|
||||
total = avg_stats(&runtime_nsecs_stats[cpu]);
|
||||
|
||||
if (total)
|
||||
ratio = 1000.0 * avg / total;
|
||||
|
||||
fprintf(stderr, " # %8.3f M/sec ", ratio);
|
||||
fprintf(output, " # %8.3f M/sec ", ratio);
|
||||
} else {
|
||||
fprintf(stderr, " ");
|
||||
fprintf(output, " ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -867,7 +878,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
|
||||
int scaled = counter->counts->scaled;
|
||||
|
||||
if (scaled == -1) {
|
||||
fprintf(stderr, "%*s%s%*s",
|
||||
fprintf(output, "%*s%s%*s",
|
||||
csv_output ? 0 : 18,
|
||||
counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
|
||||
csv_sep,
|
||||
@@ -875,9 +886,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
|
||||
event_name(counter));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -889,7 +900,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
|
||||
print_noise(counter, avg);
|
||||
|
||||
if (csv_output) {
|
||||
fputc('\n', stderr);
|
||||
fputc('\n', output);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -899,9 +910,9 @@ static void print_counter_aggr(struct perf_evsel *counter)
|
||||
avg_enabled = avg_stats(&ps->res_stats[1]);
|
||||
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 +929,7 @@ static void print_counter(struct perf_evsel *counter)
|
||||
ena = counter->counts->cpu[cpu].ena;
|
||||
run = counter->counts->cpu[cpu].run;
|
||||
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,
|
||||
evsel_list->cpus->map[cpu], csv_sep,
|
||||
csv_output ? 0 : 18,
|
||||
@@ -928,9 +939,10 @@ static void print_counter(struct perf_evsel *counter)
|
||||
event_name(counter));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -943,9 +955,10 @@ static void print_counter(struct perf_evsel *counter)
|
||||
print_noise(counter, 1.0);
|
||||
|
||||
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 +970,21 @@ static void print_stat(int argc, const char **argv)
|
||||
fflush(stdout);
|
||||
|
||||
if (!csv_output) {
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " Performance counter stats for ");
|
||||
fprintf(output, "\n");
|
||||
fprintf(output, " Performance counter stats for ");
|
||||
if(target_pid == -1 && target_tid == -1) {
|
||||
fprintf(stderr, "\'%s", argv[0]);
|
||||
fprintf(output, "\'%s", argv[0]);
|
||||
for (i = 1; i < argc; i++)
|
||||
fprintf(stderr, " %s", argv[i]);
|
||||
fprintf(output, " %s", argv[i]);
|
||||
} else if (target_pid != -1)
|
||||
fprintf(stderr, "process id \'%d", target_pid);
|
||||
fprintf(output, "process id \'%d", target_pid);
|
||||
else
|
||||
fprintf(stderr, "thread id \'%d", target_tid);
|
||||
fprintf(output, "thread id \'%d", target_tid);
|
||||
|
||||
fprintf(stderr, "\'");
|
||||
fprintf(output, "\'");
|
||||
if (run_count > 1)
|
||||
fprintf(stderr, " (%d runs)", run_count);
|
||||
fprintf(stderr, ":\n\n");
|
||||
fprintf(output, " (%d runs)", run_count);
|
||||
fprintf(output, ":\n\n");
|
||||
}
|
||||
|
||||
if (no_aggr) {
|
||||
@@ -984,15 +997,15 @@ static void print_stat(int argc, const char **argv)
|
||||
|
||||
if (!csv_output) {
|
||||
if (!null_run)
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, " %17.9f seconds time elapsed",
|
||||
fprintf(output, "\n");
|
||||
fprintf(output, " %17.9f seconds time elapsed",
|
||||
avg_stats(&walltime_nsecs_stats)/1e9);
|
||||
if (run_count > 1) {
|
||||
fprintf(stderr, " ");
|
||||
fprintf(output, " ");
|
||||
print_noise_pct(stddev_stats(&walltime_nsecs_stats),
|
||||
avg_stats(&walltime_nsecs_stats));
|
||||
}
|
||||
fprintf(stderr, "\n\n");
|
||||
fprintf(output, "\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1030,6 +1043,8 @@ static int stat__set_big_num(const struct option *opt __used,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool append_file;
|
||||
|
||||
static const struct option options[] = {
|
||||
OPT_CALLBACK('e', "event", &evsel_list, "event",
|
||||
"event selector. use 'perf list' to list available events",
|
||||
@@ -1070,6 +1085,11 @@ static const struct option options[] = {
|
||||
OPT_CALLBACK('G', "cgroup", &evsel_list, "name",
|
||||
"monitor event in cgroup name only",
|
||||
parse_cgroups),
|
||||
OPT_STRING('o', "output", &output_name, "file",
|
||||
"output file name"),
|
||||
OPT_BOOLEAN(0, "append", &append_file, "append to the output file"),
|
||||
OPT_INTEGER(0, "log-fd", &output_fd,
|
||||
"log output to fd, instead of stderr"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
@@ -1141,6 +1161,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||
{
|
||||
struct perf_evsel *pos;
|
||||
int status = -ENOMEM;
|
||||
const char *mode;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
@@ -1151,16 +1172,46 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||
argc = parse_options(argc, argv, options, stat_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
if (csv_sep)
|
||||
output = stderr;
|
||||
if (output_name && strcmp(output_name, "-"))
|
||||
output = NULL;
|
||||
|
||||
if (output_name && output_fd) {
|
||||
fprintf(stderr, "cannot use both --output and --log-fd\n");
|
||||
usage_with_options(stat_usage, options);
|
||||
}
|
||||
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));
|
||||
} else if (output_fd != 2) {
|
||||
mode = append_file ? "a" : "w";
|
||||
output = fdopen(output_fd, mode);
|
||||
if (!output) {
|
||||
perror("Failed opening logfd");
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
if (csv_sep) {
|
||||
csv_output = true;
|
||||
else
|
||||
if (!strcmp(csv_sep, "\\t"))
|
||||
csv_sep = "\t";
|
||||
} else
|
||||
csv_sep = DEFAULT_SEPARATOR;
|
||||
|
||||
/*
|
||||
* let the spreadsheet do the pretty-printing
|
||||
*/
|
||||
if (csv_output) {
|
||||
/* User explicitely passed -B? */
|
||||
/* User explicitly passed -B? */
|
||||
if (big_num_opt == 1) {
|
||||
fprintf(stderr, "-B option not supported with -x\n");
|
||||
usage_with_options(stat_usage, options);
|
||||
@@ -1226,7 +1277,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||
status = 0;
|
||||
for (run_idx = 0; run_idx < run_count; run_idx++) {
|
||||
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)
|
||||
sync();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user