diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-01-14 17:25:12 +0100 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-01-14 17:25:12 +0100 |
commit | 197749981e539c1eb5863f417de6dd4e2c02b76c (patch) | |
tree | d7c81373a9ea1b833163e9c36d727b1b6ddab067 /tools | |
parent | 1341f3e4c0276aae3de6d902c9202265d89fe438 (diff) | |
parent | 26f7f9877234e6b9ed87eff4ca450631bafe0182 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf tooling updates from Arnaldo Carvalho de Melo:
New features:
* perf record: Add --initial-delay option (Andi Kleen)
* Column colouring improvements in 'diff' (Ramkumar Ramachandra)
Fixes:
* Don't show counter information when workload fails (Arnaldo Carvalho de Melo)
* Fixup leak on error path in parse events test. (Arnaldo Carvalho de Melo)
* Fix --delay option in 'stat' man page (Andi Kleen)
* Use the DWARF unwind info only if loaded (Jean Pihet):
Developer stuff:
* Improve forked workload error reporting by sending the errno in the signal
data queueing integer field, using sigqueue and by doing the signal setup in
the evlist methods, removing open coded equivalents in various tools. (Arnaldo Carvalho de Melo)
* Do more auto exit cleanup shores in the 'evlist' destructor, so that the tools
don't have to all do that sequence. (Arnaldo Carvalho de Melo)
* Pack 'struct perf_session_env' and 'struct trace' (Arnaldo Carvalho de Melo)
* Include tools/lib/api/ in MANIFEST, fixing detached tarballs (Arnaldo Carvalho de Melo)
* Add test for building detached source tarballs (Arnaldo Carvalho de Melo)
* Shut up libtracevent plugins make message (Jiri Olsa)
* Fix installation tests path setup (Jiri Olsa)
* Fix id_hdr_size initialization (Jiri Olsa)
* Move some header files from tools/perf/ to tools/include/ to make them available to
other tools/ dwelling codebases (Namhyung Kim)
* Fix 'probe' build when DWARF support libraries not present (Arnaldo Carvalho de Melo)
Refactorings:
* Move logic to warn about kptr_restrict'ed kernels to separate
function in 'report' (Arnaldo Carvalho de Melo)
* Move hist browser selection code to separate function (Arnaldo Carvalho de Melo)
* Move histogram entries collapsing to separate function (Arnaldo Carvalho de Melo)
* Introduce evlist__for_each() & friends (Arnaldo Carvalho de Melo)
* Automate setup of FEATURE_CHECK_(C|LD)FLAGS-all variables (Jiri Olsa)
* Move arch setup into seprate Makefile (Jiri Olsa)
Trivial stuff:
* Remove misplaced __maybe_unused in 'stat' (Arnaldo Carvalho de Melo)
* Remove old evsel_list usage in 'record' (Arnaldo Carvalho de Melo)
* Comment typo fix (Cody P Schafer)
* Remove unused test-volatile-register-var.c (Yann Droneaud)
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
55 files changed, 724 insertions, 436 deletions
diff --git a/tools/perf/util/include/asm/bug.h b/tools/include/asm/bug.h index 7fcc6810adc..9e5f4846967 100644 --- a/tools/perf/util/include/asm/bug.h +++ b/tools/include/asm/bug.h @@ -1,5 +1,7 @@ -#ifndef _PERF_ASM_GENERIC_BUG_H -#define _PERF_ASM_GENERIC_BUG_H +#ifndef _TOOLS_ASM_BUG_H +#define _TOOLS_ASM_BUG_H + +#include <linux/compiler.h> #define __WARN_printf(arg...) do { fprintf(stderr, arg); } while (0) @@ -19,4 +21,5 @@ __warned = 1; \ unlikely(__ret_warn_once); \ }) -#endif + +#endif /* _TOOLS_ASM_BUG_H */ diff --git a/tools/perf/util/include/linux/compiler.h b/tools/include/linux/compiler.h index b003ad7200b..fbc6665c6d5 100644 --- a/tools/perf/util/include/linux/compiler.h +++ b/tools/include/linux/compiler.h @@ -1,5 +1,5 @@ -#ifndef _PERF_LINUX_COMPILER_H_ -#define _PERF_LINUX_COMPILER_H_ +#ifndef _TOOLS_LINUX_COMPILER_H_ +#define _TOOLS_LINUX_COMPILER_H_ #ifndef __always_inline # define __always_inline inline __attribute__((always_inline)) @@ -27,4 +27,12 @@ # define __weak __attribute__((weak)) #endif +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) #endif + +#ifndef unlikely +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif + +#endif /* _TOOLS_LINUX_COMPILER_H */ diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile index ca4ab78425d..f778d48ac60 100644 --- a/tools/lib/traceevent/Makefile +++ b/tools/lib/traceevent/Makefile @@ -86,8 +86,8 @@ ifeq ($(BUILD_SRC),) ifneq ($(OUTPUT),) define build_output - $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \ - BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1 + $(if $(VERBOSE:1=),@)+$(MAKE) -C $(OUTPUT) \ + BUILD_SRC=$(CURDIR)/ -f $(CURDIR)/Makefile $1 endef all: sub-make @@ -221,23 +221,23 @@ $(PLUGINS): %.so: %.o $(QUIET_LINK)$(CC) $(CFLAGS) -shared -nostartfiles -o $@ $< define make_version.h - (echo '/* This file is automatically generated. Do not modify. */'; \ - echo \#define VERSION_CODE $(shell \ - expr $(VERSION) \* 256 + $(PATCHLEVEL)); \ - echo '#define EXTRAVERSION ' $(EXTRAVERSION); \ - echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \ - echo '#define FILE_VERSION '$(FILE_VERSION); \ - ) > $1 + (echo '/* This file is automatically generated. Do not modify. */'; \ + echo \#define VERSION_CODE $(shell \ + expr $(VERSION) \* 256 + $(PATCHLEVEL)); \ + echo '#define EXTRAVERSION ' $(EXTRAVERSION); \ + echo '#define VERSION_STRING "'$(VERSION).$(PATCHLEVEL).$(EXTRAVERSION)'"'; \ + echo '#define FILE_VERSION '$(FILE_VERSION); \ + ) > $1 endef define update_version.h - ($(call make_version.h, $@.tmp); \ - if [ -r $@ ] && cmp -s $@ $@.tmp; then \ - rm -f $@.tmp; \ - else \ - echo ' UPDATE $@'; \ - mv -f $@.tmp $@; \ - fi); + ($(call make_version.h, $@.tmp); \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + echo ' UPDATE $@'; \ + mv -f $@.tmp $@; \ + fi); endef ep_version.h: force @@ -246,13 +246,13 @@ ep_version.h: force VERSION_FILES = ep_version.h define update_dir - (echo $1 > $@.tmp; \ - if [ -r $@ ] && cmp -s $@ $@.tmp; then \ - rm -f $@.tmp; \ - else \ - echo ' UPDATE $@'; \ - mv -f $@.tmp $@; \ - fi); + (echo $1 > $@.tmp; \ + if [ -r $@ ] && cmp -s $@ $@.tmp; then \ + rm -f $@.tmp; \ + else \ + echo ' UPDATE $@'; \ + mv -f $@.tmp $@; \ + fi); endef ## make deps @@ -262,10 +262,10 @@ all_deps := $(all_objs:%.o=.%.d) # let .d file also depends on the source and header files define check_deps - @set -e; $(RM) $@; \ - $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ - sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ - $(RM) $@.$$$$ + @set -e; $(RM) $@; \ + $(CC) -MM $(CFLAGS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + $(RM) $@.$$$$ endef $(all_deps): .%.d: $(src)/%.c @@ -329,9 +329,12 @@ clean: endif # skip-makefile -PHONY += force +PHONY += force plugins force: +plugins: + @echo > /dev/null + # Declare the contents of the .PHONY variable as phony. We keep that # information in a variable so we can use it in if_changed and friends. .PHONY: $(PHONY) diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index c407897f043..82bffac036e 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt @@ -209,6 +209,10 @@ overrides that and uses per-thread mmaps. A side-effect of that is that inheritance is automatically disabled. --per-thread is ignored with a warning if combined with -a or -C options. +--initial-delay msecs:: +After starting the program, wait msecs before measuring. This is useful to +filter out the startup phase of the program, which is often very different. + SEE ALSO -------- linkperf:perf-stat[1], linkperf:perf-list[1] diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt index 80c7da6732f..29ee857c09c 100644 --- a/tools/perf/Documentation/perf-stat.txt +++ b/tools/perf/Documentation/perf-stat.txt @@ -133,7 +133,7 @@ use --per-core in addition to -a. (system-wide). The output includes the core number and the number of online logical processors on that physical processor. -D msecs:: ---initial-delay msecs:: +--delay msecs:: After starting the program, wait msecs before measuring. This is useful to filter out the startup phase of the program, which is often very different. diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST index 3170a7ff578..f41572d0dd7 100644 --- a/tools/perf/MANIFEST +++ b/tools/perf/MANIFEST @@ -1,9 +1,11 @@ tools/perf tools/scripts tools/lib/traceevent -tools/lib/lk +tools/lib/api tools/lib/symbol/kallsyms.c tools/lib/symbol/kallsyms.h +tools/include/asm/bug.h +tools/include/linux/compiler.h include/linux/const.h include/linux/perf_event.h include/linux/rbtree.h diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf index 3638b0bd20d..87d7726cee2 100644 --- a/tools/perf/Makefile.perf +++ b/tools/perf/Makefile.perf @@ -211,7 +211,7 @@ LIB_H += ../../include/linux/hash.h LIB_H += ../../include/linux/stringify.h LIB_H += util/include/linux/bitmap.h LIB_H += util/include/linux/bitops.h -LIB_H += util/include/linux/compiler.h +LIB_H += ../include/linux/compiler.h LIB_H += util/include/linux/const.h LIB_H += util/include/linux/ctype.h LIB_H += util/include/linux/kernel.h @@ -226,7 +226,7 @@ LIB_H += util/include/linux/string.h LIB_H += util/include/linux/types.h LIB_H += util/include/linux/linkage.h LIB_H += util/include/asm/asm-offsets.h -LIB_H += util/include/asm/bug.h +LIB_H += ../include/asm/bug.h LIB_H += util/include/asm/byteorder.h LIB_H += util/include/asm/hweight.h LIB_H += util/include/asm/swab.h diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ab65057a031..0da603b79b6 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -232,7 +232,7 @@ static int __cmd_annotate(struct perf_annotate *ann) perf_session__fprintf_dsos(session, stdout); total_nr_samples = 0; - list_for_each_entry(pos, &session->evlist->entries, node) { + evlist__for_each(session->evlist, pos) { struct hists *hists = &pos->hists; u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index e6a0844bc2f..a77e31246c0 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -356,9 +356,10 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel, { struct perf_evsel *e; - list_for_each_entry(e, &evlist->entries, node) + evlist__for_each(evlist, e) { if (perf_evsel__match2(evsel, e)) return e; + } return NULL; } @@ -367,7 +368,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist) { struct perf_evsel *evsel; - list_for_each_entry(evsel, &evlist->entries, node) { + evlist__for_each(evlist, evsel) { struct hists *hists = &evsel->hists; hists__collapse_resort(hists, NULL); @@ -614,7 +615,7 @@ static void data_process(void) struct perf_evsel *evsel_base; bool first = true; - list_for_each_entry(evsel_base, &evlist_base->entries, node) { + evlist__for_each(evlist_base, evsel_base) { struct data__file *d; int i; @@ -769,6 +770,81 @@ static int hpp__entry_baseline(struct hist_entry *he, char *buf, size_t size) return ret; } +static int __hpp__color_compare(struct perf_hpp_fmt *fmt, + struct perf_hpp *hpp, struct hist_entry *he, + int comparison_method) +{ + struct diff_hpp_fmt *dfmt = + container_of(fmt, struct diff_hpp_fmt, fmt); + struct hist_entry *pair = get_pair_fmt(he, dfmt); + double diff; + s64 wdiff; + char pfmt[20] = " "; + + if (!pair) + goto dummy_print; + + switch (comparison_method) { + case COMPUTE_DELTA: + if (pair->diff.computed) + diff = pair->diff.period_ratio_delta; + else + diff = compute_delta(he, pair); + + if (fabs(diff) < 0.01) + goto dummy_print; + scnprintf(pfmt, 20, "%%%+d.2f%%%%", dfmt->header_width - 1); + return percent_color_snprintf(hpp->buf, hpp->size, + pfmt, diff); + case COMPUTE_RATIO: + if (he->dummy) + goto dummy_print; + if (pair->diff.computed) + diff = pair->diff.period_ratio; + else + diff = compute_ratio(he, pair); + + scnprintf(pfmt, 20, "%%%d.6f", dfmt->header_width); + return value_color_snprintf(hpp->buf, hpp->size, + pfmt, diff); + case COMPUTE_WEIGHTED_DIFF: + if (he->dummy) + goto dummy_print; + if (pair->diff.computed) + wdiff = pair->diff.wdiff; + else + wdiff = compute_wdiff(he, pair); + + scnprintf(pfmt, 20, "%%14ld", dfmt->header_width); + return color_snprintf(hpp->buf, hpp->size, + get_percent_color(wdiff), + pfmt, wdiff); + default: + BUG_ON(1); + } +dummy_print: + return scnprintf(hpp->buf, hpp->size, "%*s", + dfmt->header_width, pfmt); +} + +static int hpp__color_delta(struct perf_hpp_fmt *fmt, + struct perf_hpp *hpp, struct hist_entry *he) +{ + return __hpp__color_compare(fmt, hpp, he, COMPUTE_DELTA); +} + +static int hpp__color_ratio(struct perf_hpp_fmt *fmt, + struct perf_hpp *hpp, struct hist_entry *he) +{ + return __hpp__color_compare(fmt, hpp, he, COMPUTE_RATIO); +} + +static int hpp__color_wdiff(struct perf_hpp_fmt *fmt, + struct perf_hpp *hpp, struct hist_entry *he) +{ + return __hpp__color_compare(fmt, hpp, he, COMPUTE_WEIGHTED_DIFF); +} + static void hpp__entry_unpair(struct hist_entry *he, int idx, char *buf, size_t size) { @@ -940,8 +1016,22 @@ static void data__hpp_register(struct data__file *d, int idx) fmt->entry = hpp__entry_global; /* TODO more colors */ - if (idx == PERF_HPP_DIFF__BASELINE) + switch (idx) { + case PERF_HPP_DIFF__BASELINE: fmt->color = hpp__color_baseline; + break; + case PERF_HPP_DIFF__DELTA: + fmt->color = hpp__color_delta; + break; + case PERF_HPP_DIFF__RATIO: + fmt->color = hpp__color_ratio; + break; + case PERF_HPP_DIFF__WEIGHTED_DIFF: + fmt->color = hpp__color_wdiff; + break; + default: + break; + } init_header(d, dfmt); perf_hpp__column_register(fmt); diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c index 20b0f12763b..c99e0de7e54 100644 --- a/tools/perf/builtin-evlist.c +++ b/tools/perf/builtin-evlist.c @@ -29,7 +29,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details if (session == NULL) return -ENOMEM; - list_for_each_entry(pos, &session->evlist->entries, node) + evlist__for_each(session->evlist, pos) perf_evsel__fprintf(pos, details, stdout); perf_session__delete(session); diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index c9f6d74e1fd..b3466018bbd 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -369,7 +369,7 @@ static int __cmd_inject(struct perf_inject *inject) inject->tool.ordered_samples = true; - list_for_each_entry(evsel, &session->evlist->entries, node) { + evlist__for_each(session->evlist, evsel) { const char *name = perf_evsel__name(evsel); if (!strcmp(name, "sched:sched_switch")) { diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index a6ec1052c29..a7350519c63 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -1174,7 +1174,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) * Note: exclude_{guest,host} do not apply here. * This command processes KVM tracepoints from host only */ - list_for_each_entry(pos, &evlist->entries, node) { + evlist__for_each(evlist, pos) { struct perf_event_attr *attr = &pos->attr; /* make sure these *are* set */ @@ -1556,10 +1556,8 @@ out: if (kvm->session) perf_session__delete(kvm->session); kvm->session = NULL; - if (kvm->evlist) { - perf_evlist__delete_maps(kvm->evlist); + if (kvm->evlist) perf_evlist__delete(kvm->evlist); - } return err; } diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 6ec0cbc2a5d..07d4cf8d3fd 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -183,7 +183,7 @@ static int record__open(struct record *rec) perf_evlist__config(evlist, opts); - list_for_each_entry(pos, &evlist->entries, node) { + evlist__for_each(evlist, pos) { try_again: if (perf_evsel__open(pos, evlist->cpus, evlist->threads) < 0) { if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { @@ -324,7 +324,6 @@ out: static void record__init_features(struct record *rec) { - struct perf_evlist *evsel_list = rec->evlist; struct perf_session *session = rec->session; int feat; @@ -334,13 +333,29 @@ static void record__init_features(struct record *rec) if (rec->no_buildid) perf_header__clear_feat(&session->header, HEADER_BUILD_ID); - if (!have_tracepoints(&evsel_list->entries)) + if (!have_tracepoints(&rec->evlist->entries)) perf_header__clear_feat(&session->header, HEADER_TRACING_DATA); if (!rec->opts.branch_stack) perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK); } +static volatile int workload_exec_errno; + +/* + * perf_evlist__prepare_workload will send a SIGUSR1 + * if the fork fails, since we asked by setting its + * want_signal to true. + */ +static void workload_exec_failed_signal(int signo, siginfo_t *info, + void *ucontext __maybe_unused) +{ + workload_exec_errno = info->si_value.sival_int; + done = 1; + signr = signo; + child_finished = 1; +} + static int __cmd_record(struct record *rec, int argc, const char **argv) { int err; @@ -349,7 +364,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) struct machine *machine; struct perf_tool *tool = &rec->tool; struct record_opts *opts = &rec->opts; - struct perf_evlist *evsel_list = rec->evlist; struct perf_data_file *file = &rec->file; struct perf_session *session; bool disabled = false; @@ -359,7 +373,6 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) on_exit(record__sig_exit, rec); signal(SIGCHLD, sig_handler); signal(SIGINT, sig_handler); - signal(SIGUSR1, sig_handler); signal(SIGTERM, sig_handler); session = perf_session__new(file, false, NULL); @@ -373,9 +386,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) record__init_features(rec); if (forks) { - err = perf_evlist__prepare_workload(evsel_list, &opts->target, + err = perf_evlist__prepare_workload(rec->evlist, &opts->target, argv, file->is_pipe, - true); + workload_exec_failed_signal); if (err < 0) { pr_err("Couldn't run the workload!\n"); goto out_delete_session; @@ -387,7 +400,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_delete_session; } - if (!evsel_list->nr_groups) + if (!rec->evlist->nr_groups) perf_header__clear_feat(&session->header, HEADER_GROUP_DESC); /* @@ -400,7 +413,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) if (err < 0) goto out_delete_session; } else { - err = perf_session__write_header(session, evsel_list, + err = perf_session__write_header(session, rec->evlist, file->fd, false); if (err < 0) goto out_delete_session; @@ -424,7 +437,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) goto out_delete_session; } - if (have_tracepoints(&evsel_list->entries)) { + if (have_tracepoints(&rec->evlist->entries)) { /* * FIXME err <= 0 here actually means that * there were no tracepoints so its not really @@ -433,7 +446,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * return this more properly and also * propagate errors that now are calling die() */ - err = perf_event__synthesize_tracing_data(tool, file->fd, evsel_list, + err = perf_event__synthesize_tracing_data(tool, file->fd, rec->evlist, process_synthesized_event); if (err <= 0) { pr_err("Couldn't record tracing data.\n"); @@ -465,7 +478,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) perf_event__synthesize_guest_os, tool); } - err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads, + err = __machine__synthesize_threads(machine, tool, &opts->target, rec->evlist->threads, process_synthesized_event, opts->sample_address); if (err != 0) goto out_delete_session; @@ -486,14 +499,19 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) * (apart from group members) have enable_on_exec=1 set, * so don't spoil it by prematurely enabling them. */ - if (!target__none(&opts->target)) - perf_evlist__enable(evsel_list); + if (!target__none(&opts->target) && !opts->initial_delay) + perf_evlist__enable(rec->evlist); /* * Let the child rip */ if (forks) < |