Re: [RFC/PATCHSET 00/15] perf report: Add support to accumulate hist periods
Hi Arun and Peter, On Mon, 29 Oct 2012 14:36:01 -0700, Arun Sharma wrote: On 10/29/12 12:08 PM, Peter Zijlstra wrote: Right, so I tried this and I would expect the callchains to be inverted too, so that when I expand say 'c' I would see that 'c' calls 'b' for 100% which calls 'a' for 100%. Instead I get the regular callchains, expanding 'c' gives me main calls it for 100%. Adding -G (invert callchains) doesn't make it better, in that case, when I expand 'c' we start at '__libc_start_main' instead of 'c'. Is there anything I'm missing? Sounds like a reasonable expectation. I tested mainly: perf report --cumulate -g graph,100,callee to find the functions with a large amount of CPU time underneath. Then examined the callgraph without --cumulate. But yeah - it'd be nice to be able to do both in a single invocation. Yes, the callchain part needs to be improved. Peter's idea indeed looks good to me too. But before doing that, I'd like to get an agreement on how to design/implement this feature. Sorry to Frederic (and Stephane), I'm bothering you multiple times with this but I didn't get what you want exactly. IIUC you don't want to have --cumulate option but to share branch sampling code to implement it, right? But the branch sampling output looks not fit to --cumulate usage IMHO. Could you give me an advice? Also, when callgraphs are displayed, the percentages are off ( 100%). Namhyung probably needs to use he-stat_acc-period in a few places as the denominator instead of he-period. I will look into it later. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/9] perf python: add ui stubs file
Hi David, On Mon, 29 Oct 2012 10:31:41 -0600, David Ahern wrote: stdio based implementations of ui_ based functions for the python library. Needed for patch 3 - consolidating open counters method. How about adding ui/util.c to the python-ext-sources? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 2/9] perf top: make use of perf_record_opts
On Mon, 29 Oct 2012 10:31:42 -0600, David Ahern wrote: Changes top code to use the perf_record_opts struct. Stepping stone to consolidating the open counters code. Maybe time to rename perf_record_opts to perf_open_opts or just perf_opts? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [BUG] perf report: different reports when run on terminal as opposed to script
Hi Dhaval, On Mon, 29 Oct 2012 12:45:53 -0400, Dhaval Giani wrote: On Mon, Oct 29, 2012 at 12:01 PM, Dhaval Giani dhaval.gi...@gmail.com wrote: Hi, As part of a class assignment I have to collect some performance statistics. In order to do so I run perf record -g the program I have to profile And in another window, I start 200 threads of the load generator (which is not recorded by perf) This generates me statistics that I expect to see, and I am happy. As this is academia and a class assignment, I need to collect information and analyze it across different setups. Which of course meant I script this whole thing, which basically is for i in all possibilities do perf record -g the program I have to profile WAITPID=$! for j in NR_THREADS do start load generator KILLPID=$! done wait $PID You meant $WAITPID, right? kill $KILLPID Doesn't it kill the last load generator only? mv perf.data results/perf.data.$i done (This is basic pseudo script of what I am doing), which results me having my profile being topped by _vscanf() and the function which I was seeing dominating in the older report dropping down to something like 5% (as opposed to 16-17%) Have I misunderstood how perf works? Something deeper? I am currently on 3.6.3. I can update to the latest upstream and report back. Any debug code is very welcome. I can also make my toy program and the scripts available for you to try out. I just updated to 6b0cb4eef7bdaa27b8021ea81813fba330a2d94d and I still see this happen. Thanks! Dhaval -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [Patch v1 04/10] perf/x86: add memory profiling via PEBS Load Latency
Hi Stephane, On Mon, 29 Oct 2012 16:15:46 +0100, Stephane Eranian wrote: + /* + * use the mapping table for bit 0-15 + */ + val = pebs_data_source[dse.ld_dse]; I guess you meant bit 0-3, right? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [Patch v1 06/10] perf/x86: add support for PEBS Precise Store
On Mon, 29 Oct 2012 16:15:48 +0100, Stephane Eranian wrote: This patch adds support for PEBS Precise Store which is available on Intel Sandy Bridge and Ivy Bridge processors. To use Precise store, the proper PEBS event must be used: mem_trans_retired:precise_stores. For the perf tool, the generic mem-stores event exported via sysfs can be used directly. Just trivial nitpicks.. Signed-off-by: Stephane Eranian eran...@google.com --- [snip] @@ -486,6 +524,7 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0xc4, 0xf),/* BR_INST_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xc5, 0xf),/* BR_MISP_RETIRED.* */ INTEL_PLD_CONSTRAINT(0x01cd, 0x8),/* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ + INTEL_PST_CONSTRAINT(0x02cd, 0x8),/* MEM_TRANS_RETIRED.PRECISE_STORES */ INTEL_EVENT_CONSTRAINT(0xd0, 0xf),/* MEM_UOP_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd1, 0xf),/* MEM_LOAD_UOPS_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd2, 0xf),/* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ @@ -500,6 +539,7 @@ struct event_constraint intel_ivb_pebs_event_constraints[] = { INTEL_EVENT_CONSTRAINT(0xc4, 0xf),/* BR_INST_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xc5, 0xf),/* BR_MISP_RETIRED.* */ INTEL_PLD_CONSTRAINT(0x01cd, 0x8),/* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ + INTEL_PST_CONSTRAINT(0x02cd, 0x8),/* MEM_TRANS_RETIRED.PRECISE_STORES */ White-space damaged? Oh, it seems already broken with spaces. INTEL_EVENT_CONSTRAINT(0xd0, 0xf),/* MEM_UOP_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd1, 0xf),/* MEM_LOAD_UOPS_RETIRED.* */ INTEL_EVENT_CONSTRAINT(0xd2, 0xf),/* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ [snip] @@ -672,7 +715,7 @@ static void __intel_pmu_pebs_event(struct perf_event *event, /* * if PEBS-LL or PreciseStore */ - if (fll) { + if (fll || fst) { if (sample_type PERF_SAMPLE_ADDR) data.addr = pebs-dla; @@ -688,6 +731,8 @@ static void __intel_pmu_pebs_event(struct perf_event *event, if (sample_type PERF_SAMPLE_DSRC) { if (fll) data.dsrc.val = load_latency_data(pebs-dse); + else if (fst) Looks like it can be converted to a plain 'else'. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [Patch v1 07/10] perf tools: add mem access sampling core support
On Mon, 29 Oct 2012 16:15:49 +0100, Stephane Eranian wrote: This patch adds the sorting and histogram support functions to enable profiling of memory accesses. The following sorting orders are added: - symbol_daddr: data address symbol (or raw address) - dso_daddr: data address shared object - cost: access cost - locked: access uses locked transaction - tlb : TLB access - mem : memory level of the access (L1, L2, L3, RAM, ...) - snoop: access snoop mode Signed-off-by: Stephane Eranian eran...@google.com --- [snip] +/* --sort daddr_sym */ +static int64_t +sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right) +{ + struct addr_map_symbol *l = left-mem_info-daddr; + struct addr_map_symbol *r = right-mem_info-daddr; + + return (int64_t)(r-addr - l-addr); +} Doesn't it need to compare symbol (start address) if any, before doing it with raw addresses? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [Patch v1 08/10] perf report: add support for mem access profiling
On Mon, 29 Oct 2012 16:15:50 +0100, Stephane Eranian wrote: This patch adds the --mem-mode option to perf report. This mode requires a perf.data file created with memory access samples. Signed-off-by: Stephane Eranian eran...@google.com --- [snip] + cost = mi-cost; + if (!cost) + cost = 1; + + /* + * The report shows the percentage of total branches captured + * and not events sampled. Thus we use a pseudo period of 1. But cost won't be 1 anymore if PERF_SAMPLE_COST set, right? + * Only in the newt browser we are doing integrated annotation, + * so we don't allocated the extra space needed because the stdio + * code will not use it. Yes, and gtk too. + */ + he = __hists__add_mem_entry(evsel-hists, al, parent, mi, + cost); + if (!he) + return -ENOMEM; + + if (sort__has_sym he-ms.sym use_browser 0) { So I'd rather write 'use_browser == 1' instead of ' 0'. + struct annotation *notes = symbol__annotation(he-ms.sym); + + assert(evsel != NULL); + + if (notes-src == NULL symbol__alloc_hist(he-ms.sym) 0) + goto out; + + err = hist_entry__inc_addr_samples(he, evsel-idx, al-addr); + if (err) + goto out; + } + + if (sort__has_sym he-mem_info-daddr.sym use_browser 0) { Ditto. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [Patch v1 10/10] perf tools: add new mem command for memory access profiling
On Mon, 29 Oct 2012 16:15:52 +0100, Stephane Eranian wrote: This new command is a wrapper on top of perf record and perf report to make it easier to configure for memory access profiling. So this new command will be run only on speicific (PEBS 2?) Intel machines, right? Is there anything we can do for others? Or at least it might emit a warning message.. To record loads: $ perf mem -t load rec . To record stores: $ perf mem -t store rec . To get the report: $ perf mem -t load rep Signed-off-by: Stephane Eranian eran...@google.com --- [snip] +perf-mem(1) +=== + +NAME + +perf-mem - Profile memory accesses + +SYNOPSIS + +[verse] +'perf mem' -t load record command +'perf mem' -t store record command +'perf mem' -t load report +'perf mem' -t store report Is '-t' option mandatory? AFAISC it seems optional and defaults to load. And is command for record also mandatory? Doesn't 'perf record' make it optional? If so, the above can be written like you did in 'mem_usage': 'perf mem' [options] (record [command] | report) + +DESCRIPTION +--- +perf mem -t TYPE record runs a command and gathers memory operation data +from it, into perf.data. Perf record options are accepted and are passed through. + +perf mem -t TYPE report displays the result. It invokes perf report with the +right set of options to display a memory access profile. + +OPTIONS +--- +command...:: + Any command you can specify in a shell. + +-t:: +--type=:: + Select the memory operation type: load or store It'd better saying it defaults to load. + +-R:: +--dump-raw-samples=:: + Dump the raw decoded samples on the screen in a format that is easy to parse with + one sample per line. Didn't we usually use -D switch for this? + +-x:: +--field-separator:: + Specify the field separator used when dump raw samples (-R option). By default, + The separator is the space character. And using -t for this will make it consistent with perf report IMHO. + +-C:: +--cpu-list:: + Restrict dump of raw samples to those provided via this option. Note that the same + option can be passed in record mode. It will be interpreted the same way as perf + record. + +SEE ALSO + +linkperf:perf-record[1], linkperf:perf-report[1] [snip] +#define MEM_OPERATION_LOAD load +#define MEM_OPERATION_STORE store + +static char const*input_name = perf.data; We have a global 'input_name' as of commit 70cb4e963f77 (perf tools: Add a global variable 'const char *input_name'). +static const char*mem_operation = MEM_OPERATION_LOAD; +static const char*csv_sep= NULL; Why not use symbol_conf.field_sep? + +struct perf_mem { + struct perf_tooltool; + char const *input_name; + symbol_filter_t annotate_init; + boolhide_unresolved; + booldump_raw; + const char *cpu_list; + DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); +}; + +static const char * const mem_usage[] = { + perf mem [options] {record command |report}, + NULL +}; [snip] +static int report_raw_events(struct perf_mem *mem) +{ + int err = -EINVAL; + int ret; + struct perf_session *session = perf_session__new(input_name, O_RDONLY, + 0, false, mem-tool); + + if (mem-cpu_list) { + ret = perf_session__cpu_bitmap(session, mem-cpu_list, +mem-cpu_bitmap); + if (ret) + goto out_delete; + } + + if (symbol__init() 0) + return -1; + + if (session == NULL) + return -ENOMEM; This check should be moved before perf_session__cpu_bitmap() calls. Thanks, Namhyung + + printf(# PID, TID, IP, ADDR, COST, DSRC, SYMBOL\n); + + err = perf_session__process_events(session, mem-tool); + if (err) + return err; + + return 0; + +out_delete: + perf_session__delete(session); + return err; +} -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [BUG] perf report: different reports when run on terminal as opposed to script
On Tue, 30 Oct 2012 08:05:45 -0400, Dhaval Giani wrote: On Tue, Oct 30, 2012 at 3:42 AM, Namhyung Kim namhy...@kernel.org wrote: Hi Dhaval, On Mon, 29 Oct 2012 12:45:53 -0400, Dhaval Giani wrote: On Mon, Oct 29, 2012 at 12:01 PM, Dhaval Giani dhaval.gi...@gmail.com wrote: Hi, As part of a class assignment I have to collect some performance statistics. In order to do so I run perf record -g the program I have to profile And in another window, I start 200 threads of the load generator (which is not recorded by perf) This generates me statistics that I expect to see, and I am happy. As this is academia and a class assignment, I need to collect information and analyze it across different setups. Which of course meant I script this whole thing, which basically is for i in all possibilities do perf record -g the program I have to profile WAITPID=$! for j in NR_THREADS do start load generator KILLPID=$! done wait $PID You meant $WAITPID, right? yes. grrr. I changed the name here to WAITPID for it to be clear and that was a fail. (I blame the cold) kill $KILLPID Doesn't it kill the last load generator only? Well, this was a bug in me typing the pseudo code. the actual script does $KILLPID $! Okay, so I suspect that it might be affected by the autogroup scheduling feature since you said running load generators in another window - I guess it's a terminal. How about running them with setsid? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/9] perf python: add ui stubs file
On Tue, 30 Oct 2012 08:53:38 -0700, Arnaldo Carvalho de Melo wrote: Em Tue, Oct 30, 2012 at 08:45:28AM -0600, David Ahern escreveu: On 10/30/12 1:24 AM, Namhyung Kim wrote: On Mon, 29 Oct 2012 10:31:41 -0600, David Ahern wrote: stdio based implementations of ui_ based functions for the python library. Needed for patch 3 - consolidating open counters method. How about adding ui/util.c to the python-ext-sources? Handles some of the ui_ functions, but still missing some symbols -- verbose, eprintf, ui__error_paranoid. The point of the python_stubs.c was a short term solution for the ui handlers. Arnaldo had some ideas on what is really needed. Yes, and that is something like what Namhyung did for perf_target, i.e. don't call ui__ stuff from the evsel/evlist classes but use a perf_evlist__strerror, merge perf_evlist__open_counters() with perf_evlist__open(), use just perf_evlist__open() everywhere, so that all tools get the fallbacks for features not present in older kernels, etc. Yeah, it'd be better definitely. But the problem is we might emit warnings even in the internal fallback loop. Not sure how to handle it with this approach. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC/PATCHSET 00/15] perf report: Add support to accumulate hist periods
On Tue, 30 Oct 2012 10:01:10 +0100, Ingo Molnar wrote: * Peter Zijlstra a.p.zijls...@chello.nl wrote: On Tue, 2012-10-30 at 15:59 +0900, Namhyung Kim wrote: Yes, the callchain part needs to be improved. Peter's idea indeed looks good to me too. FWIW, I think this is exactly what sysprof does, except that tool isn't usable for other reasons.. You might want to look at it though. I always found the fundamental sysprof system-wide call graph profiling output/view superior - and so do many Xorg developers who are using SysProf that I talked to - so I'd strongly encourage to use that ordering and grouping for the default perf call-graph profiling output/view. Okay, I'll look at the sysprof. Anyway, do you have any other comments for the general --cumulate approach in this series (esp. with --branch-stack)? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: why is perf-report asking for objdump path?
Hi David, On Thu, 01 Nov 2012 15:09:46 -0600, David Ahern wrote: $ /tmp/pbuild/perf report -i perf.data --kallsyms kallsyms Error: Please install objdump for i686. You can add it to PATH, set CROSS_COMPILE or override the default using --objdump. And worse it refuses to run without it. If I was running the annotate command I could understand the request -- but this is the report path. Agreed. It should not affect when no annotation was used. Furthermore objdump exists: $ which objdump /usr/bin/objdump yes, the file was created on an i686 target, but I should be able to use the x86_64 host objdump if I were doing an annotate. Could you test the below patch? It'd great if you can do it in a reverse situation - using x86_64 target on i686 host. From f0a9d6303f83452c8b6f81081abae8fdf9c81778 Mon Sep 17 00:00:00 2001 From: Namhyung Kim namhyung@lge.com Date: Fri, 2 Nov 2012 09:48:17 +0900 Subject: [PATCH] perf tools: Use normalized arch name for searching objdump path David reported that perf report for i686 target data on x86_64 host failed to work because it tried to find out cross-compiled objdump. However objdump for x86_64 is compatible to i686 so that it doesn't need to do it at all. To prevent similar artifacts, normalize arch name when comparing host and file architectures. Reported-by: David Ahern dsah...@gmail.com Cc: Irina Tirdea irina.tir...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/arch/common.c | 40 +--- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index 2367b253f039..5683529135b1 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c @@ -93,16 +93,46 @@ static int lookup_triplets(const char *const *triplets, const char *name) return -1; } +/* + * Return architecture name in a normalized form. + * The conversion logic comes from the Makefile. + */ +static const char *normalize_arch(char *arch) +{ + if (!strcmp(arch, x86_64)) + return x86; + if (arch[0] == 'i' arch[2] == '8' arch[3] == '6') + return x86; + if (!strcmp(arch, sun4u) || !strncmp(arch, sparc, 5)) + return sparc; + if (!strncmp(arch, arm, 3) || !strcmp(arch, sa110)) + return arm; + if (!strncmp(arch, s390, 4)) + return s390; + if (!strncmp(arch, parisc, 6)) + return parisc; + if (!strncmp(arch, powerpc, 7) || !strncmp(arch, ppc, 3)) + return powerpc; + if (!strncmp(arch, mips, 4)) + return mips; + if (!strncmp(arch, sh, 2) isdigit(arch[2])) + return sh; + + return arch; +} + static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, const char *name, const char **path) { int idx; - char *arch, *cross_env; + const char *arch, *cross_env; struct utsname uts; const char *const *path_list; char *buf = NULL; + arch = normalize_arch(env-arch); + if (uname(uts) 0) goto out; @@ -110,7 +140,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, * We don't need to try to find objdump path for native system. * Just use default binutils path (e.g.: objdump). */ - if (!strcmp(uts.machine, env-arch)) + if (!strcmp(normalize_arch(uts.machine), arch)) goto out; cross_env = getenv(CROSS_COMPILE); @@ -127,8 +157,6 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, free(buf); } - arch = env-arch; - if (!strcmp(arch, arm)) path_list = arm_triplets; else if (!strcmp(arch, powerpc)) @@ -139,9 +167,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, path_list = s390_triplets; else if (!strcmp(arch, sparc)) path_list = sparc_triplets; - else if (!strcmp(arch, x86) || !strcmp(arch, i386) || -!strcmp(arch, i486) || !strcmp(arch, i586) || -!strcmp(arch, i686)) + else if (!strcmp(arch, x86)) path_list = x86_triplets; else if (!strcmp(arch, mips)) path_list = mips_triplets; -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 00/25] perf test: Add perf_event_attr tests
Hi, On Fri, 2 Nov 2012 00:20:56 +0100, Jiri Olsa wrote: On Thu, Nov 01, 2012 at 05:38:01PM -0300, Arnaldo Carvalho de Melo wrote: Ah, I just pushed perf/core with this patchset, thanks! thanks, jirka When using current acme/perf/core, I got this: namhyung@sejong:perf$ ./perf test -v perf_event_attr 13: struct perf_event_attr setup : --- start --- running './tests/attr/test-record-count' running './tests/attr/test-stat-group1' Traceback (most recent call last): File ./tests/attr.py, line 313, in module main() File ./tests/attr.py, line 304, in main run_tests(options) File ./tests/attr.py, line 247, in run_tests Test(f, options).run() File ./tests/attr.py, line 126, in __init__ self.load_events(path, self.expect) File ./tests/attr.py, line 147, in load_events base_items = parser_base.items('event') File /usr/lib64/python2.7/ConfigParser.py, line 642, in items raise NoSectionError(section) ConfigParser.NoSectionError: No section: 'event' end struct perf_event_attr setup: FAILED! namhyung@sejong:perf$ cat tests/attr/test-stat-group1 [config] command = stat args= -e '{cycles,instructions}' kill /dev/null 21 ret = 1 [event-1:base-stat] fd=1 group_fd=-1 [event-2:base-stat] fd=2 group_fd=1 config=1 # TODO both disabled and enable_on_exec are disabled for --group option, # enabled otherwise, check why.. disabled=1 enable_on_exec=1 Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 02/25] perf tests: Move test objects into 'tests' directory
Hi Jiri, Despite its way to acme's tree, I'd like to leave a few comments. :) On Tue, 30 Oct 2012 23:01:43 +0100, Jiri Olsa wrote: Separating test objects into 'tests' directory. Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com --- tools/perf/Makefile |9 +- tools/perf/builtin-test.c | 1559 --- tools/perf/tests/builtin-test.c | 1559 +++ tools/perf/tests/dso-data.c | 153 tools/perf/tests/parse-events.c | 1116 + tools/perf/util/dso-test-data.c | 153 tools/perf/util/parse-events-test.c | 1116 - Looks like it should be considered as renames. Isn't 'git format-patch -M' working? 7 files changed, 2833 insertions(+), 2832 deletions(-) delete mode 100644 tools/perf/builtin-test.c create mode 100644 tools/perf/tests/builtin-test.c create mode 100644 tools/perf/tests/dso-data.c create mode 100644 tools/perf/tests/parse-events.c delete mode 100644 tools/perf/util/dso-test-data.c delete mode 100644 tools/perf/util/parse-events-test.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3e807d7..2d3427f 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -169,7 +169,7 @@ endif ### --- END CONFIGURATION SECTION --- -BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE +BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -Iutil -I. -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE Hmm.. Do you really want this? AFAIK there're lots of places that include header files under the util directory and they used relative path. I don't know how it affects them but at least they can be changed to use simpler path with this change. BASIC_LDFLAGS = ifeq ($(call try-cc,$(SOURCE_BIONIC),$(CFLAGS),bionic),y) @@ -371,7 +371,6 @@ LIB_OBJS += $(OUTPUT)util/help.o LIB_OBJS += $(OUTPUT)util/levenshtein.o LIB_OBJS += $(OUTPUT)util/parse-options.o LIB_OBJS += $(OUTPUT)util/parse-events.o -LIB_OBJS += $(OUTPUT)util/parse-events-test.o LIB_OBJS += $(OUTPUT)util/path.o LIB_OBJS += $(OUTPUT)util/rbtree.o LIB_OBJS += $(OUTPUT)util/bitmap.o @@ -389,7 +388,6 @@ LIB_OBJS += $(OUTPUT)util/sigchain.o LIB_OBJS += $(OUTPUT)util/dso.o LIB_OBJS += $(OUTPUT)util/symbol.o LIB_OBJS += $(OUTPUT)util/symbol-elf.o -LIB_OBJS += $(OUTPUT)util/dso-test-data.o LIB_OBJS += $(OUTPUT)util/color.o LIB_OBJS += $(OUTPUT)util/pager.o LIB_OBJS += $(OUTPUT)util/header.o @@ -430,6 +428,9 @@ LIB_OBJS += $(OUTPUT)ui/stdio/hist.o LIB_OBJS += $(OUTPUT)arch/common.o +LIB_OBJS += $(OUTPUT)tests/parse-events.o +LIB_OBJS += $(OUTPUT)tests/dso-data.o + Maybe TEST_OBJS? I guess they don't need to be included in libperf? BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o # Benchmark modules @@ -459,8 +460,8 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o BUILTIN_OBJS += $(OUTPUT)builtin-lock.o BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o -BUILTIN_OBJS += $(OUTPUT)builtin-test.o BUILTIN_OBJS += $(OUTPUT)builtin-inject.o +BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o Placing builtin command in a different directory looks little bit odd. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCHv2 03/25] perf tests: Add framework for automated perf_event_attr tests
On Wed, 31 Oct 2012 15:52:47 +0100, Jiri Olsa wrote: Adding automated test to check event's perf_event_attr values. The idea is run perf session with kidnapping sys_perf_event_open function. For each sys_perf_event_open call we store the perf_event_attr data to the file to be checked later against what we expect. You can run this by: $ python ./tests/attr.py -d ./tests/attr/ -p ./perf -v v2 changes: - preserve errno value in the hook Signed-off-by: Jiri Olsa jo...@redhat.com Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com --- tools/perf/Makefile | 1 + tools/perf/perf.c| 2 + tools/perf/perf.h| 16 ++- tools/perf/tests/attr.c | 140 + tools/perf/tests/attr.py | 313 +++ 5 files changed, 470 insertions(+), 2 deletions(-) create mode 100644 tools/perf/tests/attr.c create mode 100644 tools/perf/tests/attr.py diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 2d3427f..1da87a3 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -430,6 +430,7 @@ LIB_OBJS += $(OUTPUT)arch/common.o LIB_OBJS += $(OUTPUT)tests/parse-events.o LIB_OBJS += $(OUTPUT)tests/dso-data.o +LIB_OBJS += $(OUTPUT)tests/attr.o It'd better if it has more specific name like 'event-attr' but it'd not a big deal so no strong objection. :) BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o [snip] +#define WRITE_ASS(str, fmt, data)\ +do { \ + char buf[BUFSIZE]; \ + size_t size;\ + \ + size = snprintf(buf, BUFSIZE, #str =%fmt \n, data); \ + if (1 != fwrite(buf, size, 1, file)) { \ + perror(test attr - failed to write event file); \ + fclose(file); \ + return -1; \ + } \ + \ +} while (0) What is ASS? + +static int store_event(struct perf_event_attr *attr, pid_t pid, int cpu, +int fd, int group_fd, unsigned long flags) +{ + FILE *file; + char path[PATH_MAX]; + + snprintf(path, PATH_MAX, %s/event-%d-%llu-%d, dir, + attr-type, attr-config, fd); + + file = fopen(path, w+); + if (!file) { + perror(test attr - failed to open event file); + return -1; + } + + if (fprintf(file, [event-%d-%llu-%d]\n, + attr-type, attr-config, fd) 0) { + perror(test attr - failed to write event file); + fclose(file); + return -1; + } + + /* syscall arguments */ + WRITE_ASS(fd, d, fd); + WRITE_ASS(group_fd, d, group_fd); + WRITE_ASS(cpu, d, cpu); + WRITE_ASS(pid, d, pid); + WRITE_ASS(flags, lu, flags); + + /* struct perf_event_attr */ + WRITE_ASS(type, PRIu32, attr-type); + WRITE_ASS(size, PRIu32, attr-size); + WRITE_ASS(config, llu, attr-config); + WRITE_ASS(sample_period, llu, attr-sample_period); + WRITE_ASS(sample_type, llu, attr-sample_type); + WRITE_ASS(read_format, llu, attr-read_format); + WRITE_ASS(disabled, d, attr-disabled); + WRITE_ASS(inherit,d, attr-inherit); + WRITE_ASS(pinned, d, attr-pinned); + WRITE_ASS(exclusive, d, attr-exclusive); + WRITE_ASS(exclude_user, d, attr-exclude_user); + WRITE_ASS(exclude_kernel, d, attr-exclude_kernel); + WRITE_ASS(exclude_hv, d, attr-exclude_hv); + WRITE_ASS(exclude_idle, d, attr-exclude_idle); + WRITE_ASS(mmap, d, attr-mmap); + WRITE_ASS(comm, d, attr-comm); + WRITE_ASS(freq, d, attr-freq); + WRITE_ASS(inherit_stat, d, attr-inherit_stat); + WRITE_ASS(enable_on_exec, d, attr-enable_on_exec); + WRITE_ASS(task, d, attr-task); + WRITE_ASS(watermask, d, attr-watermark); + WRITE_ASS(precise_ip, d, attr-precise_ip); + WRITE_ASS(mmap_data, d, attr-mmap_data); + WRITE_ASS(sample_id_all, d, attr-sample_id_all); + WRITE_ASS(exclude_host, d, attr-exclude_host); + WRITE_ASS(exclude_guest, d, attr-exclude_guest); + WRITE_ASS(exclude_callchain_kernel, d, + attr-exclude_callchain_kernel); +
Re: [PATCH 00/25] perf test: Add perf_event_attr tests
On Fri, 02 Nov 2012 10:25:18 +0900, Namhyung Kim wrote: namhyung@sejong:perf$ cat tests/attr/test-stat-group1 [config] command = stat args= -e '{cycles,instructions}' kill /dev/null 21 ret = 1 [event-1:base-stat] fd=1 group_fd=-1 [event-2:base-stat] fd=2 group_fd=1 config=1 # TODO both disabled and enable_on_exec are disabled for --group option, # enabled otherwise, check why.. disabled=1 enable_on_exec=1 Oh I realize that I don't have the base-stat file. namhyung@sejong:perf$ cat tests/attr/base-stat cat: tests/attr/base-stat: No such file or directory Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 3/3] perf report: Enable the runtime switching of perf data file
Hi Feng, On Thu, 1 Nov 2012 00:00:57 +0800, Feng Tang wrote: This is for tui browser only. This patch will check the returned key of tui hists browser, if it's K_SWITH_INPUT_DATA, then recreate a session for the new selected data file. You may want to add my previous patch [1] to your patch set as it can call perf_session__delete() multiple times. Thanks, Namhyung [1] https://lkml.org/lkml/2012/9/24/693 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH RESEND 1/3] perf tools: Use normalized arch name for searching objdump path
From: Namhyung Kim namhyung@lge.com David reported that perf report for i686 target data on x86_64 host failed to work because it tried to find out cross-compiled objdump. However objdump for x86_64 is compatible to i686 so that it doesn't need to do it at all. To prevent similar artifacts, normalize arch name when comparing host and file architectures. Reported-by: David Ahern dsah...@gmail.com Cc: David Ahern dsah...@gmail.com Cc: Irina Tirdea irina.tir...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/arch/common.c | 40 +--- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c index 2367b253f039..5683529135b1 100644 --- a/tools/perf/arch/common.c +++ b/tools/perf/arch/common.c @@ -93,16 +93,46 @@ static int lookup_triplets(const char *const *triplets, const char *name) return -1; } +/* + * Return architecture name in a normalized form. + * The conversion logic comes from the Makefile. + */ +static const char *normalize_arch(char *arch) +{ + if (!strcmp(arch, x86_64)) + return x86; + if (arch[0] == 'i' arch[2] == '8' arch[3] == '6') + return x86; + if (!strcmp(arch, sun4u) || !strncmp(arch, sparc, 5)) + return sparc; + if (!strncmp(arch, arm, 3) || !strcmp(arch, sa110)) + return arm; + if (!strncmp(arch, s390, 4)) + return s390; + if (!strncmp(arch, parisc, 6)) + return parisc; + if (!strncmp(arch, powerpc, 7) || !strncmp(arch, ppc, 3)) + return powerpc; + if (!strncmp(arch, mips, 4)) + return mips; + if (!strncmp(arch, sh, 2) isdigit(arch[2])) + return sh; + + return arch; +} + static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, const char *name, const char **path) { int idx; - char *arch, *cross_env; + const char *arch, *cross_env; struct utsname uts; const char *const *path_list; char *buf = NULL; + arch = normalize_arch(env-arch); + if (uname(uts) 0) goto out; @@ -110,7 +140,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, * We don't need to try to find objdump path for native system. * Just use default binutils path (e.g.: objdump). */ - if (!strcmp(uts.machine, env-arch)) + if (!strcmp(normalize_arch(uts.machine), arch)) goto out; cross_env = getenv(CROSS_COMPILE); @@ -127,8 +157,6 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, free(buf); } - arch = env-arch; - if (!strcmp(arch, arm)) path_list = arm_triplets; else if (!strcmp(arch, powerpc)) @@ -139,9 +167,7 @@ static int perf_session_env__lookup_binutils_path(struct perf_session_env *env, path_list = s390_triplets; else if (!strcmp(arch, sparc)) path_list = sparc_triplets; - else if (!strcmp(arch, x86) || !strcmp(arch, i386) || -!strcmp(arch, i486) || !strcmp(arch, i586) || -!strcmp(arch, i686)) + else if (!strcmp(arch, x86)) path_list = x86_triplets; else if (!strcmp(arch, mips)) path_list = mips_triplets; -- 1.7.11.7 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/3] perf report: Postpone objdump check until annotation requested
From: Namhyung Kim namhyung@lge.com David reported that current perf report refused to run on a data file captured from a different machine because of objdump. Since the objdump tools won't be used unless annotation was requested, checking its presence at init time doens't make sense. Reported-by: David Ahern dsah...@gmail.com Cc: Irina Tirdea irina.tir...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c| 9 ++--- tools/perf/builtin-top.c | 3 ++- tools/perf/ui/browsers/hists.c | 22 -- tools/perf/util/hist.h | 7 +-- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 234f34d466e3..fc251005dd3d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -428,7 +428,8 @@ static int __cmd_report(struct perf_report *rep) if (use_browser 0) { if (use_browser == 1) { perf_evlist__tui_browse_hists(session-evlist, help, - NULL); + NULL, + session-header.env); } else if (use_browser == 2) { perf_evlist__gtk_browse_hists(session-evlist, help, NULL); @@ -672,12 +673,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) has_br_stack = perf_header__has_feat(session-header, HEADER_BRANCH_STACK); - if (!objdump_path) { - ret = perf_session_env__lookup_objdump(session-header.env); - if (ret) - goto error; - } - if (sort__branch_mode == -1 has_br_stack) sort__branch_mode = 1; diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 102b43c9905d..c9ff3950cd4b 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -598,7 +598,8 @@ static void *display_thread_tui(void *arg) list_for_each_entry(pos, top-evlist-entries, node) pos-hists.uid_filter_str = top-target.uid_str; - perf_evlist__tui_browse_hists(top-evlist, help, hbt); + perf_evlist__tui_browse_hists(top-evlist, help, hbt, + top-session-header.env); exit_browser(0); exit(0); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index c7d32edb8057..ccc4bd161420 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -11,6 +11,7 @@ #include ../../util/pstack.h #include ../../util/sort.h #include ../../util/util.h +#include ../../arch/common.h #include ../browser.h #include ../helpline.h @@ -1137,7 +1138,8 @@ static inline bool is_report_browser(void *timer) static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, const char *helpline, const char *ev_name, bool left_exits, - struct hist_browser_timer *hbt) + struct hist_browser_timer *hbt, + struct perf_session_env *env) { struct hists *hists = evsel-hists; struct hist_browser *browser = hist_browser__new(hists); @@ -1367,6 +1369,9 @@ retry_popup_menu: struct hist_entry *he; int err; do_annotate: + if (!objdump_path perf_session_env__lookup_objdump(env)) + continue; + he = hist_browser__selected_entry(browser); if (he == NULL) continue; @@ -1470,6 +1475,7 @@ struct perf_evsel_menu { struct ui_browser b; struct perf_evsel *selection; bool lost_events, lost_events_warned; + struct perf_session_env *env; }; static void perf_evsel_menu__write(struct ui_browser *browser, @@ -1551,7 +1557,8 @@ browse_hists: hbt-timer(hbt-arg); ev_name = perf_evsel__name(pos); key = perf_evsel__hists_browse(pos, nr_events, help, - ev_name, true, hbt); + ev_name, true, hbt, + menu-env); ui_browser__show_title(menu-b, title); switch (key) { case K_TAB: @@ -1599,7 +1606,8 @@ out: static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, - struct hist_browser_timer *hbt
[PATCH 2/3] perf tools: Introduce struct hist_browser_timer
From: Namhyung Kim namhyung@lge.com Currently various hist browser functions receive 3 arguments for refreshing histogram but only used from a few places. Also it's only for perf top command so that it can be NULL for other (and probably most) cases. Pack them into a struct in order to reduce number of those unused arguments. This is a mechanical change and does not intend a functional change. Cc: David Ahern dsah...@gmail.com Cc: Irina Tirdea irina.tir...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-annotate.c | 2 +- tools/perf/builtin-report.c | 4 ++-- tools/perf/builtin-top.c | 9 +--- tools/perf/ui/browsers/annotate.c | 27 +++- tools/perf/ui/browsers/hists.c| 43 +-- tools/perf/ui/gtk/browser.c | 4 +--- tools/perf/util/annotate.h| 8 tools/perf/util/hist.h| 28 - 8 files changed, 58 insertions(+), 67 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index cb234765ce3d..dc870cf31b79 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -139,7 +139,7 @@ find_next: } if (use_browser 0) { - key = hist_entry__tui_annotate(he, evidx, NULL, NULL, 0); + key = hist_entry__tui_annotate(he, evidx, NULL); switch (key) { case K_RIGHT: next = rb_next(nd); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index f07eae73e692..234f34d466e3 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -428,10 +428,10 @@ static int __cmd_report(struct perf_report *rep) if (use_browser 0) { if (use_browser == 1) { perf_evlist__tui_browse_hists(session-evlist, help, - NULL, NULL, 0); + NULL); } else if (use_browser == 2) { perf_evlist__gtk_browse_hists(session-evlist, help, - NULL, NULL, 0); + NULL); } } else perf_evlist__tty_browse_hists(session-evlist, rep, help); diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index f2ecd498c72d..102b43c9905d 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -582,6 +582,11 @@ static void *display_thread_tui(void *arg) struct perf_evsel *pos; struct perf_top *top = arg; const char *help = For a higher level overview, try: perf top --sort comm,dso; + struct hist_browser_timer hbt = { + .timer = perf_top__sort_new_samples, + .arg= top, + .refresh= top-delay_secs, + }; perf_top__sort_new_samples(top); @@ -593,9 +598,7 @@ static void *display_thread_tui(void *arg) list_for_each_entry(pos, top-evlist-entries, node) pos-hists.uid_filter_str = top-target.uid_str; - perf_evlist__tui_browse_hists(top-evlist, help, - perf_top__sort_new_samples, - top, top-delay_secs); + perf_evlist__tui_browse_hists(top-evlist, help, hbt); exit_browser(0); exit(0); diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 28f8aab73aee..3eff17f703f3 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -386,9 +386,8 @@ static void annotate_browser__init_asm_mode(struct annotate_browser *browser) browser-b.nr_entries = browser-nr_asm_entries; } -static bool annotate_browser__callq(struct annotate_browser *browser, - int evidx, void (*timer)(void *arg), - void *arg, int delay_secs) +static bool annotate_browser__callq(struct annotate_browser *browser, int evidx, + struct hist_browser_timer *hbt) { struct map_symbol *ms = browser-b.priv; struct disasm_line *dl = browser-selection; @@ -418,7 +417,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser, } pthread_mutex_unlock(notes-lock); - symbol__tui_annotate(target, ms-map, evidx, timer, arg, delay_secs); + symbol__tui_annotate(target, ms-map, evidx, hbt); ui_browser__show_title(browser-b, sym-name); return true; } @@ -602,13 +601,13 @@ static void annotate_browser__update_addr_width(struct annotate_browser *browser } static int annotate_browser__run(struct annotate_browser *browser, int evidx, -void
[PATCH 0/6] perf header: Save and reuse feature information in header (v5)
Hi, Currently the perf header information is used only at initial setup time and discarded. If it's saved we could reuse the information for various purpose - for instance, perf kvm stat needs to know cpuid so it had to invent an accessor. Thanks, Namhyung v4 - v5: * Use saved cpuid info for perf kvm (David) v3 - v4: * rename perf_header_info to perf_session_env (Arnaldo) v2 - v3: * patch 1-3 in v2 merged into tip * rebased on current acme/perf/core v1 - v2: * not touch EVENT_DESC feature handling * split out struct perf_header_info * simplify multi-string handling * add some cleanup patches Namhyung Kim (6): perf header: Add struct perf_session_env perf header: Add -process callbacks to most of features perf header: Use pre-processed session env when printing perf header: Remove unused @feat arg from -process callback perf kvm: Use perf_session_env for reading cpuid perf header: Remove perf_header__read_feature tools/perf/builtin-kvm.c | 10 +- tools/perf/util/header.c | 598 ++- tools/perf/util/header.h | 25 +- 3 files changed, 406 insertions(+), 227 deletions(-) -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 3/6] perf header: Use pre-processed session env when printing
From now on each feature information is processed and saved in perf header so that it can be used for printing. The event desc and branch stack features are not touched since they're not saved. Cc: Stephane Eranian eran...@google.com Cc: Robert Richter robert.rich...@amd.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/header.c | 207 +++ 1 file changed, 66 insertions(+), 141 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index d74b58d4105d..b2929d7a3d4e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1103,118 +1103,80 @@ static int write_branch_stack(int fd __maybe_unused, return 0; } -static void print_hostname(struct perf_header *ph, int fd, FILE *fp) +static void print_hostname(struct perf_header *ph, int fd __maybe_unused, + FILE *fp) { - char *str = do_read_string(fd, ph); - fprintf(fp, # hostname : %s\n, str); - free(str); + fprintf(fp, # hostname : %s\n, ph-env.hostname); } -static void print_osrelease(struct perf_header *ph, int fd, FILE *fp) +static void print_osrelease(struct perf_header *ph, int fd __maybe_unused, + FILE *fp) { - char *str = do_read_string(fd, ph); - fprintf(fp, # os release : %s\n, str); - free(str); + fprintf(fp, # os release : %s\n, ph-env.os_release); } -static void print_arch(struct perf_header *ph, int fd, FILE *fp) +static void print_arch(struct perf_header *ph, int fd __maybe_unused, FILE *fp) { - char *str = do_read_string(fd, ph); - fprintf(fp, # arch : %s\n, str); - free(str); + fprintf(fp, # arch : %s\n, ph-env.arch); } -static void print_cpudesc(struct perf_header *ph, int fd, FILE *fp) +static void print_cpudesc(struct perf_header *ph, int fd __maybe_unused, + FILE *fp) { - char *str = do_read_string(fd, ph); - fprintf(fp, # cpudesc : %s\n, str); - free(str); + fprintf(fp, # cpudesc : %s\n, ph-env.cpu_desc); } -static void print_nrcpus(struct perf_header *ph, int fd, FILE *fp) +static void print_nrcpus(struct perf_header *ph, int fd __maybe_unused, +FILE *fp) { - ssize_t ret; - u32 nr; - - ret = read(fd, nr, sizeof(nr)); - if (ret != (ssize_t)sizeof(nr)) - nr = -1; /* interpreted as error */ - - if (ph-needs_swap) - nr = bswap_32(nr); - - fprintf(fp, # nrcpus online : %u\n, nr); - - ret = read(fd, nr, sizeof(nr)); - if (ret != (ssize_t)sizeof(nr)) - nr = -1; /* interpreted as error */ - - if (ph-needs_swap) - nr = bswap_32(nr); - - fprintf(fp, # nrcpus avail : %u\n, nr); + fprintf(fp, # nrcpus online : %u\n, ph-env.nr_cpus_online); + fprintf(fp, # nrcpus avail : %u\n, ph-env.nr_cpus_avail); } -static void print_version(struct perf_header *ph, int fd, FILE *fp) +static void print_version(struct perf_header *ph, int fd __maybe_unused, + FILE *fp) { - char *str = do_read_string(fd, ph); - fprintf(fp, # perf version : %s\n, str); - free(str); + fprintf(fp, # perf version : %s\n, ph-env.version); } -static void print_cmdline(struct perf_header *ph, int fd, FILE *fp) +static void print_cmdline(struct perf_header *ph, int fd __maybe_unused, + FILE *fp) { - ssize_t ret; + int nr, i; char *str; - u32 nr, i; - - ret = read(fd, nr, sizeof(nr)); - if (ret != (ssize_t)sizeof(nr)) - return; - if (ph-needs_swap) - nr = bswap_32(nr); + nr = ph-env.nr_cmdline; + str = ph-env.cmdline; fprintf(fp, # cmdline : ); for (i = 0; i nr; i++) { - str = do_read_string(fd, ph); fprintf(fp, %s , str); - free(str); + str += strlen(str) + 1; } fputc('\n', fp); } -static void print_cpu_topology(struct perf_header *ph, int fd, FILE *fp) +static void print_cpu_topology(struct perf_header *ph, int fd __maybe_unused, + FILE *fp) { - ssize_t ret; - u32 nr, i; + int nr, i; char *str; - ret = read(fd, nr, sizeof(nr)); - if (ret != (ssize_t)sizeof(nr)) - return; - - if (ph-needs_swap) - nr = bswap_32(nr); + nr = ph-env.nr_sibling_cores; + str = ph-env.sibling_cores; for (i = 0; i nr; i++) { - str = do_read_string(fd, ph); fprintf(fp, # sibling cores : %s\n, str); - free(str); + str += strlen(str) + 1; } - ret = read(fd, nr, sizeof(nr)); - if (ret != (ssize_t)sizeof(nr)) - return; - - if (ph-needs_swap) - nr = bswap_32(nr); + nr
[PATCH 1/6] perf header: Add struct perf_session_env
From: Namhyung Kim namhyung@lge.com The struct perf_session_env will preserve environment information at the time of perf record. It can be accessed anytime after parsing a perf.data file if needed. Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/header.h | 24 1 file changed, 24 insertions(+) diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 58de08b21bce..5867c7d74f97 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -58,6 +58,29 @@ struct perf_header; int perf_file_header__read(struct perf_file_header *header, struct perf_header *ph, int fd); +struct perf_session_env { + char*hostname; + char*os_release; + char*version; + char*arch; + int nr_cpus_online; + int nr_cpus_avail; + char*cpu_desc; + char*cpuid; + unsigned long long total_mem; + + int nr_cmdline; + char*cmdline; + int nr_sibling_cores; + char*sibling_cores; + int nr_sibling_threads; + char*sibling_threads; + int nr_numa_nodes; + char*numa_nodes; + int nr_pmu_mappings; + char*pmu_mappings; +}; + struct perf_header { int frozen; boolneeds_swap; @@ -67,6 +90,7 @@ struct perf_header { u64 event_offset; u64 event_size; DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS); + struct perf_session_env env; }; struct perf_evlist; -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 4/6] perf header: Remove unused @feat arg from -process callback
From: Namhyung Kim namhyung@lge.com As the @feat arg is not used anywhere, get rid of it from the signature. Cc: Stephane Eranian eran...@google.com Cc: Robert Richter robert.rich...@amd.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/header.c | 70 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index b2929d7a3d4e..4b028df83a40 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1580,18 +1580,16 @@ out: return err; } -static int process_tracing_data(struct perf_file_section *section - __maybe_unused, - struct perf_header *ph __maybe_unused, - int feat __maybe_unused, int fd, void *data) +static int process_tracing_data(struct perf_file_section *section __maybe_unused, + struct perf_header *ph __maybe_unused, + int fd, void *data) { trace_report(fd, data, false); return 0; } static int process_build_id(struct perf_file_section *section, - struct perf_header *ph, - int feat __maybe_unused, int fd, + struct perf_header *ph, int fd, void *data __maybe_unused) { if (perf_header__read_build_ids(ph, fd, section-offset, section-size)) @@ -1600,40 +1598,40 @@ static int process_build_id(struct perf_file_section *section, } static int process_hostname(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int feat __maybe_unused, - int fd, void *data __maybe_unused) + struct perf_header *ph, int fd, + void *data __maybe_unused) { ph-env.hostname = do_read_string(fd, ph); return ph-env.hostname ? 0 : -ENOMEM; } static int process_osrelease(struct perf_file_section *section __maybe_unused, -struct perf_header *ph, int feat __maybe_unused, -int fd, void *data __maybe_unused) +struct perf_header *ph, int fd, +void *data __maybe_unused) { ph-env.os_release = do_read_string(fd, ph); return ph-env.os_release ? 0 : -ENOMEM; } static int process_version(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int feat __maybe_unused, - int fd, void *data __maybe_unused) + struct perf_header *ph, int fd, + void *data __maybe_unused) { ph-env.version = do_read_string(fd, ph); return ph-env.version ? 0 : -ENOMEM; } static int process_arch(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int feat __maybe_unused, - int fd, void *data __maybe_unused) + struct perf_header *ph, int fd, + void *data __maybe_unused) { ph-env.arch = do_read_string(fd, ph); return ph-env.arch ? 0 : -ENOMEM; } static int process_nrcpus(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int feat __maybe_unused, - int fd, void *data __maybe_unused) + struct perf_header *ph, int fd, + void *data __maybe_unused) { size_t ret; u32 nr; @@ -1659,24 +1657,24 @@ static int process_nrcpus(struct perf_file_section *section __maybe_unused, } static int process_cpudesc(struct perf_file_section *section __maybe_unused, - struct perf_header *ph, int feat __maybe_unused, - int fd, void *data __maybe_unused) + struct perf_header *ph, int fd, + void *data __maybe_unused) { ph-env.cpu_desc = do_read_string(fd, ph); return ph-env.cpu_desc ? 0 : -ENOMEM; } static int process_cpuid(struct perf_file_section *section __maybe_unused, -struct perf_header *ph, int feat __maybe_unused, -int fd, void *data __maybe_unused) +struct perf_header *ph, int fd, +void *data __maybe_unused) { ph-env.cpuid = do_read_string(fd, ph); return ph-env.cpuid ? 0 : -ENOMEM; } static int process_total_mem(struct perf_file_section *section __maybe_unused, -struct perf_header *ph, int feat __maybe_unused, -int fd, void *data __maybe_unused) +struct perf_header *ph, int fd, +void *data __maybe_unused
[PATCH 2/6] perf header: Add -process callbacks to most of features
From now on each feature information is processed and saved in perf header so that it can be used wherever needed. The BRANCH_STACK feature is an exception since it needs nothing to be done. Cc: Stephane Eranian eran...@google.com Cc: Robert Richter robert.rich...@amd.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/header.c | 319 +-- 1 file changed, 308 insertions(+), 11 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index ad72b2814ba8..d74b58d4105d 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -22,6 +22,7 @@ #include cpumap.h #include pmu.h #include vdso.h +#include strbuf.h static bool no_buildid_cache = false; @@ -1673,6 +1674,99 @@ static int process_build_id(struct perf_file_section *section, return 0; } +static int process_hostname(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int feat __maybe_unused, + int fd, void *data __maybe_unused) +{ + ph-env.hostname = do_read_string(fd, ph); + return ph-env.hostname ? 0 : -ENOMEM; +} + +static int process_osrelease(struct perf_file_section *section __maybe_unused, +struct perf_header *ph, int feat __maybe_unused, +int fd, void *data __maybe_unused) +{ + ph-env.os_release = do_read_string(fd, ph); + return ph-env.os_release ? 0 : -ENOMEM; +} + +static int process_version(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int feat __maybe_unused, + int fd, void *data __maybe_unused) +{ + ph-env.version = do_read_string(fd, ph); + return ph-env.version ? 0 : -ENOMEM; +} + +static int process_arch(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int feat __maybe_unused, + int fd, void *data __maybe_unused) +{ + ph-env.arch = do_read_string(fd, ph); + return ph-env.arch ? 0 : -ENOMEM; +} + +static int process_nrcpus(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int feat __maybe_unused, + int fd, void *data __maybe_unused) +{ + size_t ret; + u32 nr; + + ret = read(fd, nr, sizeof(nr)); + if (ret != sizeof(nr)) + return -1; + + if (ph-needs_swap) + nr = bswap_32(nr); + + ph-env.nr_cpus_online = nr; + + ret = read(fd, nr, sizeof(nr)); + if (ret != sizeof(nr)) + return -1; + + if (ph-needs_swap) + nr = bswap_32(nr); + + ph-env.nr_cpus_avail = nr; + return 0; +} + +static int process_cpudesc(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int feat __maybe_unused, + int fd, void *data __maybe_unused) +{ + ph-env.cpu_desc = do_read_string(fd, ph); + return ph-env.cpu_desc ? 0 : -ENOMEM; +} + +static int process_cpuid(struct perf_file_section *section __maybe_unused, +struct perf_header *ph, int feat __maybe_unused, +int fd, void *data __maybe_unused) +{ + ph-env.cpuid = do_read_string(fd, ph); + return ph-env.cpuid ? 0 : -ENOMEM; +} + +static int process_total_mem(struct perf_file_section *section __maybe_unused, +struct perf_header *ph, int feat __maybe_unused, +int fd, void *data __maybe_unused) +{ + uint64_t mem; + size_t ret; + + ret = read(fd, mem, sizeof(mem)); + if (ret != sizeof(mem)) + return -1; + + if (ph-needs_swap) + mem = bswap_64(mem); + + ph-env.total_mem = mem; + return 0; +} + static char *read_cpuid(struct perf_header *ph, int fd) { return do_read_string(fd, ph); @@ -1728,6 +1822,208 @@ process_event_desc(struct perf_file_section *section __maybe_unused, return 0; } +static int process_cmdline(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int feat __maybe_unused, + int fd, void *data __maybe_unused) +{ + size_t ret; + char *str; + u32 nr, i; + struct strbuf sb; + + ret = read(fd, nr, sizeof(nr)); + if (ret != sizeof(nr)) + return -1; + + if (ph-needs_swap) + nr = bswap_32(nr); + + ph-env.nr_cmdline = nr; + strbuf_init(sb, 128); + + for (i = 0; i nr; i++) { + str = do_read_string(fd, ph); + if (!str) + goto error; + + /* include a NULL character at the end */ + strbuf_add(sb, str, strlen(str) + 1); + free(str); + } + ph
[PATCH 6/6] perf header: Remove perf_header__read_feature
From: Namhyung Kim namhyung@lge.com Because its only user builtin-kvm::get_cpu_isa() has gone, It can be removed safely. In general, we have the feature information in perf_session_env already, no need to read it again. Cc: David Ahern dsah...@gmail.com Cc: Xiao Guangrong xiaoguangr...@linux.vnet.ibm.com Cc: Dong Hao haod...@linux.vnet.ibm.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/header.c | 60 +--- tools/perf/util/header.h | 1 - 2 files changed, 1 insertion(+), 60 deletions(-) diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4b028df83a40..6aae3290358e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1690,11 +1690,6 @@ static int process_total_mem(struct perf_file_section *section __maybe_unused, return 0; } -static char *read_cpuid(struct perf_header *ph, int fd) -{ - return do_read_string(fd, ph); -} - static struct perf_evsel * perf_evlist__find_by_index(struct perf_evlist *evlist, int idx) { @@ -1952,7 +1947,6 @@ error: struct feature_ops { int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist); void (*print)(struct perf_header *h, int fd, FILE *fp); - char *(*read)(struct perf_header *h, int fd); int (*process)(struct perf_file_section *section, struct perf_header *h, int fd, void *data); const char *name; @@ -1967,10 +1961,6 @@ struct feature_ops { #define FEAT_OPF(n, func) \ [n] = { .name = #n, .write = write_##func, .print = print_##func, \ .process = process_##func, .full_only = true } -#define FEAT_OPA_R(n, func) \ - [n] = { .name = #n, .write = write_##func, .print = print_##func, \ - .read = read_##func, .process = process_##func, \ - .full_only = true } /* feature_ops not implemented: */ #define print_tracing_data NULL @@ -1985,7 +1975,7 @@ static const struct feature_ops feat_ops[HEADER_LAST_FEATURE] = { FEAT_OPP(HEADER_ARCH, arch), FEAT_OPP(HEADER_NRCPUS, nrcpus), FEAT_OPP(HEADER_CPUDESC,cpudesc), - FEAT_OPA_R(HEADER_CPUID,cpuid), + FEAT_OPP(HEADER_CPUID, cpuid), FEAT_OPP(HEADER_TOTAL_MEM, total_mem), FEAT_OPP(HEADER_EVENT_DESC, event_desc), FEAT_OPP(HEADER_CMDLINE,cmdline), @@ -2040,54 +2030,6 @@ int perf_header__fprintf_info(struct perf_session *session, FILE *fp, bool full) return 0; } -struct header_read_data { - int feat; - char *result; -}; - -static int perf_file_section__read_feature(struct perf_file_section *section, - struct perf_header *ph, - int feat, int fd, void *data) -{ - struct header_read_data *hd = data; - - if (feat != hd-feat) - return 0; - - if (lseek(fd, section-offset, SEEK_SET) == (off_t)-1) { - pr_debug(Failed to lseek to % PRIu64 offset for feature - %d, continuing...\n, section-offset, feat); - return 0; - } - - if (feat = HEADER_LAST_FEATURE) { - pr_warning(unknown feature %d\n, feat); - return 0; - } - - if (!feat_ops[feat].read) { - pr_warning(read is not supported for feature %d\n, feat); - return 0; - } - - hd-result = feat_ops[feat].read(ph, fd); - return 0; -} - -char *perf_header__read_feature(struct perf_session *session, int feat) -{ - struct perf_header *header = session-header; - struct header_read_data hd; - int fd = session-fd; - - hd.feat = feat; - hd.result = NULL; - - perf_header__process_sections(header, fd, hd, - perf_file_section__read_feature); - return hd.result; -} - static int do_write_feat(int fd, struct perf_header *h, int type, struct perf_file_section **p, struct perf_evlist *evlist) diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h index 5867c7d74f97..99bdd3abce59 100644 --- a/tools/perf/util/header.h +++ b/tools/perf/util/header.h @@ -118,7 +118,6 @@ int perf_header__process_sections(struct perf_header *header, int fd, int feat, int fd, void *data)); int perf_header__fprintf_info(struct perf_session *s, FILE *fp, bool full); -char *perf_header__read_feature(struct perf_session *session, int feat); int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, const char *name, bool is_kallsyms, bool is_vdso); -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http
[PATCH 5/6] perf kvm: Use perf_session_env for reading cpuid
From: Namhyung Kim namhyung@lge.com We have processed and saved cpuid information to perf_session_env so reuse it for get_cpu_isa(). Cc: David Ahern dsah...@gmail.com Cc: Xiao Guangrong xiaoguangr...@linux.vnet.ibm.com Cc: Dong Hao haod...@linux.vnet.ibm.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-kvm.c | 10 +- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c index 819af25a9a11..b76b3aa14ffd 100644 --- a/tools/perf/builtin-kvm.c +++ b/tools/perf/builtin-kvm.c @@ -664,16 +664,9 @@ static struct perf_tool eops = { static int get_cpu_isa(struct perf_session *session) { - char *cpuid; + char *cpuid = session-header.env.cpuid; int isa; - cpuid = perf_header__read_feature(session, HEADER_CPUID); - - if (!cpuid) { - pr_err(read HEADER_CPUID failed.\n); - return -ENOTSUP; - } - if (strstr(cpuid, Intel)) isa = 1; else if (strstr(cpuid, AMD)) @@ -683,7 +676,6 @@ static int get_cpu_isa(struct perf_session *session) isa = -ENOTSUP; } - free(cpuid); return isa; } -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] block: makes bio_split support bio without data
Hi, On Mon, 24 Sep 2012 14:56:39 +1000, NeilBrown wrote: Hi Jens, this patch has been sitting in my -next tree for a little while and I was hoping for it to go in for the next merge window. It simply allows bio_split() to be used on bios without a payload, such as 'discard'. Are you happy with it going in though my 'md' tree, or would you rather take it though your 'block' tree? Thanks, NeilBrown From: Shaohua Li s...@fusionio.com Date: Thu, 20 Sep 2012 09:36:03 +1000 Subject: [PATCH] block: makes bio_split support bio without data discard bio hasn't data attached. We hit a BUG_ON with such bio. This makes bio_split works for such bio. Signed-off-by: Shaohua Li s...@fusionio.com Signed-off-by: NeilBrown ne...@suse.de diff --git a/fs/bio.c b/fs/bio.c index 71072ab..dbb7a6c 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1501,7 +1501,7 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors) trace_block_split(bdev_get_queue(bi-bi_bdev), bi, bi-bi_sector + first_sectors); - BUG_ON(bi-bi_vcnt != 1); + BUG_ON(bi-bi_vcnt != 1 bi-bi_vcnt != 0); Why not BUG_ON(bi-bi_vcnt 1); ? Thanks, Namhyung BUG_ON(bi-bi_idx != 0); atomic_set(bp-cnt, 3); bp-error = 0; @@ -1511,17 +1511,19 @@ struct bio_pair *bio_split(struct bio *bi, int first_sectors) bp-bio2.bi_size -= first_sectors 9; bp-bio1.bi_size = first_sectors 9; - bp-bv1 = bi-bi_io_vec[0]; - bp-bv2 = bi-bi_io_vec[0]; - bp-bv2.bv_offset += first_sectors 9; - bp-bv2.bv_len -= first_sectors 9; - bp-bv1.bv_len = first_sectors 9; + if (bi-bi_vcnt != 0) { + bp-bv1 = bi-bi_io_vec[0]; + bp-bv2 = bi-bi_io_vec[0]; + bp-bv2.bv_offset += first_sectors 9; + bp-bv2.bv_len -= first_sectors 9; + bp-bv1.bv_len = first_sectors 9; - bp-bio1.bi_io_vec = bp-bv1; - bp-bio2.bi_io_vec = bp-bv2; + bp-bio1.bi_io_vec = bp-bv1; + bp-bio2.bi_io_vec = bp-bv2; - bp-bio1.bi_max_vecs = 1; - bp-bio2.bi_max_vecs = 1; + bp-bio1.bi_max_vecs = 1; + bp-bio2.bi_max_vecs = 1; + } bp-bio1.bi_end_io = bio_pair_end_1; bp-bio2.bi_end_io = bio_pair_end_2; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 1/9] perf hists: Move hists_init() from util/evsel.c to util/hist.c
On Mon, 24 Sep 2012 13:02:39 -0300, Arnaldo Carvalho de Melo wrote: Em Mon, Sep 24, 2012 at 11:24:03PM +0800, Feng Tang escreveu: Which looks more natural It is there to avoid dragging the hist code into the python binding :-\ Hmm... it's so hairy. Can't we do better? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 3/9] perf script: Add more filter to find_scripts()
Hi Feng, On Mon, 24 Sep 2012 23:24:05 +0800, Feng Tang wrote: As suggested by Arnaldo, many scripts have their own usages and need capture specific events or tracepoints, so only those scripts whose targe events match the events in current perf data file should be listed in the script browser menu. This patch will add the event match checking. Signed-off-by: Feng Tang feng.t...@intel.com --- tools/perf/builtin-script.c | 76 +-- 1 files changed, 73 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c index 4e2f10f..37a0df8 100644 --- a/tools/perf/builtin-script.c +++ b/tools/perf/builtin-script.c @@ -1031,6 +1031,63 @@ static int list_available_scripts(const struct option *opt __maybe_unused, } /* + * Some scripts specify the required events in their xxx-record file, + * this function will check if the events in perf.data match those + * mentioned in the xxx-record. + */ +static int check_ev_match(char *dir_name, char *scriptname, + struct perf_session *session) +{ + char filename[MAXPATHLEN], evname[128]; + char line[BUFSIZ], *p, *temp; + struct perf_evsel *pos; + int match; + FILE *fp; + + sprintf(filename, %s/bin/%s-record, dir_name, scriptname); + + fp = fopen(filename, r); + if (!fp) + return -1; + + while (fgets(line, sizeof(line), fp)) { + p = ltrim(line); + if (strlen(p) == 0 ||*p == '#') + continue; + + while (strlen(p)) { + temp = strstr(p, -e); + if (!temp) + break; + + p = temp + 3; + temp = strchr(p, ' '); + snprintf(evname, (temp - p) + 1, %s, p); It can't recognize extra spaces, multiple events connected by commas, event groups and probably more.. So I think it'd better if we can use parse_events() here - but w/o an evlist. Jiri, what do you think? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 7/9] perf header: Add check_perf_magic() func
On Mon, 24 Sep 2012 23:24:09 +0800, Feng Tang wrote: [snip] +/* Return 0 if matched */ +int check_perf_magic(u64 magic) +{ + if (!memcmp(magic, __perf_magic1, sizeof(magic)) + || magic == __perf_magic2 + || magic == __perf_magic2_sw) + return 0; + + return -1; +} Just an idea. How about returning version number instead of 0 so that it can be used elsewhere those check is needed and possibly wants to know the version number also? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 8/9] perf hists browser: Add option for runtime switching perf data file
On Mon, 24 Sep 2012 23:24:10 +0800, Feng Tang wrote: [snip] + if (!check_perf_magic(magic)) { + options[nr_options] = strdup(name); + abs_path[nr_options++] = strdup(path); Need to check return values. + } + fclose(file); + } + closedir(pwd_dir); + + if (nr_options) { + choice = ui__popup_menu(nr_options, options); + if (choice nr_options choice = 0) { + input_name = strdup(abs_path[choice]); Ditto. Plus it might leak previous input_name. Thanks, Namhyung + ret = 0; + } + } + + free_popup_options(options, nr_options); + free_popup_options(abs_path, nr_options); + return ret; +} + + -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf test: Fix build failure
From: Namhyung Kim namhyung@lge.com The commit 6a6cd11d4e57 (perf test: Add test for the sched tracepoint format fields) added following build error: CC builtin-test.o builtin-test.c: In function ‘perf_evsel__test_field’: builtin-test.c:1216:6: error: variable ‘ret’ set but not used [-Werror=unused-but-set-variable] builtin-test.c: In function ‘perf_evsel__tp_sched_test’: builtin-test.c:1242:6: error: variable ‘ret’ set but not used [-Werror=unused-but-set-variable] cc1: all warnings being treated as errors make: *** [builtin-test.o] Error 1 Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 32caf13cfe01..78b47a75a7c9 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -1233,7 +1233,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name, ret = -1; } - return 0; + return ret; } static int perf_evsel__tp_sched_test(void) @@ -1286,7 +1286,7 @@ static int perf_evsel__tp_sched_test(void) if (perf_evsel__test_field(evsel, target_cpu, 4, true)) ret = -1; - return 0; + return ret; } static struct test { -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf session: Add perf_session__delete_env
From: Namhyung Kim namhyung@lge.com The perf session environment information was saved (so allocated) during perf_session__open, but was not freed. As free(3) handles NULL pointer input properly it won't cause a issue for writing modes - e.g. perf record. Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/session.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 3049b0ae7003..568037750d12 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c @@ -204,11 +204,30 @@ static void perf_session__delete_threads(struct perf_session *session) machine__delete_threads(session-host_machine); } +static void perf_session__delete_env(struct perf_session *self) +{ + struct perf_session_env *env = self-header.env; + + free(env-hostname); + free(env-os_release); + free(env-version); + free(env-arch); + free(env-cpu_desc); + free(env-cpuid); + + free(env-cmdline); + free(env-sibling_cores); + free(env-sibling_threads); + free(env-numa_nodes); + free(env-pmu_mappings); +} + void perf_session__delete(struct perf_session *self) { perf_session__destroy_kernel_maps(self); perf_session__delete_dead_threads(self); perf_session__delete_threads(self); + perf_session__delete_env(self); machine__exit(self-host_machine); close(self-fd); free(self); -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 27/30] tools lib traceevent: Carve out events format parsing routine
On Mon, 24 Sep 2012 12:59:41 -0300, Arnaldo Carvalho de Melo wrote: From: Arnaldo Carvalho de Melo a...@redhat.com The pevent_parse_event() routine will parse a events/sys/tp/format file and add an event_format instance to the pevent struct. This patch introduces a pevent_parse_format() routine with just the bits needed to parse the event/sys/tp/format file and just return the event_format instance, useful for when all we want is to parse the format file, without requiring the pevent struct. [snip] +enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, + unsigned long size, const char *sys) +{ + struct event_format *event = NULL; + int ret = __pevent_parse_format(event, pevent, buf, size, sys); + + if (event == NULL) + return ret; + + /* Add pevent to event so that it can be referenced */ + event-pevent = pevent; + + if (add_event(pevent, event)) + goto event_add_failed; It seems we should set the 'ret' to a proper pevent_errno - PEVENT_ERRNO__MEM_ALLOC_FAILED. + +#define PRINT_ARGS 0 + if (PRINT_ARGS event-print_fmt.args) + print_args(event-print_fmt.args); + + return 0; + +event_add_failed: + free(event-system); + free(event-name); + free(event); At this point, the 'event' also has fields and format information and they all need to be freed. Looks like calling pevent_free_format() would be the right thing IMHO. Thanks, Namhyung return ret; } -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 28/30] perf evsel: Provide a new constructor for tracepoints
On Mon, 24 Sep 2012 12:59:42 -0300, Arnaldo Carvalho de Melo wrote: From: Arnaldo Carvalho de Melo a...@redhat.com The existing constructor receives a perf_event_attr filled with the event type and the config. To reduce the boilerplate for tracepoints, provide a new constructor, perf_evsel__newtp() that receives the tracepoint name and will open the debugfs file, call into libtraceevent new pevent_parse_format file to fill its -tp_format member, so that users can then just call perf_evsel__field() to access its fields. [snip] +static struct event_format *event_format__new(const char *sys, const char *name) +{ + int fd, n; + char *filename; + void *bf = NULL, *nbf; + size_t size = 0, alloc_size = 0; + struct event_format *format = NULL; + + if (asprintf(filename, %s/%s/%s/format, tracing_events_path, sys, name) 0) + goto out; + + fd = open(filename, O_RDONLY); + if (fd 0) + goto out_free_filename; + + do { + if (size == alloc_size) { + alloc_size += BUFSIZ; + nbf = realloc(bf, alloc_size); + if (nbf == NULL) + goto out_free_bf; + bf = nbf; + } + + n = read(fd, bf + size, BUFSIZ); Wouldn't it be better doing s/BUFSIZ/alloc_size - size/ ? Although there'll be no partial reading issue when working on debugfs I guess. Thanks, Namhyung + if (n 0) + goto out_free_bf; + size += n; + } while (n 0); + + pevent_parse_format(format, bf, size, sys); + +out_free_bf: + free(bf); + close(fd); +out_free_filename: + free(filename); +out: + return format; +} -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 29/30] perf test: Add test for the sched tracepoint format fields
On Mon, 24 Sep 2012 12:59:43 -0300, Arnaldo Carvalho de Melo wrote: From: Arnaldo Carvalho de Melo a...@redhat.com So that we make sure the routines that do event format parsing are working on at least two well know scheduler tracepoints. It caused a build error and I posted a fix, please see: https://lkml.org/lkml/2012/9/24/689 Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC/PATCHSET 00/15] perf report: Add support to accumulate hist periods
Ping. Any comments for this? Arun, thanks for testing! Namhyung On Thu, 13 Sep 2012 16:19:56 +0900, Namhyung Kim wrote: Hi, This is my first attempt to implement cumulative hist period report. This work begins from Arun's SORT_INCLUSIVE patch [1] but I completely rewrote it from scratch. It basically adds period in a sample to every node in the callchain. A hist_entry now has an additional fields to keep the cumulative period if --cumulate option is given on perf report. Let me show you an example: $ cat abc.c #define barrier() asm volatile( ::: memory) void a(void) { int i; for (i = 0; i 100; i++) barrier(); } void b(void) { a(); } void c(void) { b(); } int main(void) { c(); return 0; } With this simple program I ran perf record and report: $ perf record -g -e cycles:u ./abc $ perf report -g none --stdio [snip] # Overhead Command Shared Object Symbol # ... .. .. # 93.35% abc abc [.] a 5.17% abc ld-2.15.so [.] _dl_map_object_from_fd 1.13% abc ld-2.15.so [.] _dl_start 0.29% abc libpthread-2.15.so [.] __libc_close 0.07% abc [kernel.kallsyms] [k] page_fault 0.00% abc ld-2.15.so [.] _start When --cumulate option is given, it'll be shown like this: $ perf report --cumulate (...) + 93.63% abc libc-2.15.so[.] __libc_start_main + 93.35% abc abc [.] main + 93.35% abc abc [.] c + 93.35% abc abc [.] b + 93.35% abc abc [.] a + 5.17% abc ld-2.15.so [.] _dl_map_object + 5.17% abc ld-2.15.so [.] _dl_map_object_from_fd + 1.13% abc ld-2.15.so [.] _dl_start_user + 1.13% abc ld-2.15.so [.] _dl_start + 0.29% abc perf[.] main + 0.29% abc perf[.] run_builtin + 0.29% abc perf[.] cmd_record + 0.29% abc libpthread-2.15.so [.] __libc_close + 0.07% abc ld-2.15.so [.] _start + 0.07% abc [kernel.kallsyms] [k] page_fault (This output came from TUI since stdio bothered by callchains) As you can see __libc_start_main - main - c - b - a callchain show up in the output. It might have some rough edges or even bugs, but I really want to release it and get reviews. In fact I saw some very large percentage or 'inf' on some callchain nodes when expanding. It currently ignores samples don't have symbol info when accumulating periods along the callchain. Otherwise it resulted in very strangely large output since every node in the callchain would be added into a single entry which has NULL dso/sym. Simply ignoring them solved the problem and I couldn't come up with a better solution. This patchset is based on current acme/perf/core + my small fixes [2],[3]. You can also get this series on my tree at: git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git perf/cumulate-v1 Any comments are welcome, thanks. Namhyung [1] https://lkml.org/lkml/2012/3/31/6 [2] https://lkml.org/lkml/2012/9/11/546 [3] https://lkml.org/lkml/2012/9/12/51 Namhyung Kim (15): perf hists: Add missing period_* fields when collapsing a hist entry perf hists: Introduce struct he_stat perf hists: Move he-stat.nr_events initialization to a template perf hists: Convert hist entry functions to use struct he_stat perf hists: Add more helpers for hist entry stat perf hists: Add support for accumulated stat of hist entry perf hists: Check if accumulated when adding a hist entry perf callchain: Add a couple of callchain helpers perf hists: Let add_hist_entry to make a hist entry template perf hists: Accumulate hist entry stat based on the callchain perf hists: Sort hist entries by accumulated period perf ui/hist: Add support to accumulated hist stat perf ui/browser: Add support to accumulated hist stat perf ui/gtk: Add support to accumulated hist stat perf report: Add --cumulate option tools/perf/builtin-report.c| 8 ++ tools/perf/ui/browsers/hists.c | 12 +- tools/perf/ui/gtk/browser.c| 5 +- tools/perf/ui/hist.c | 74 ++--- tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/callchain.c| 15 +++ tools/perf/util/callchain.h| 17 +++ tools/perf/util/hist.c | 242 + tools/perf/util/sort.h | 17 ++- tools/perf/util/symbol.h | 1 + 10 files changed, 318 insertions(+), 75 deletions(-) -- To unsubscribe from this list: send the line
Re: [PATCH 3/3] perf ui/browser: Fix stale output of sorted result
Hi Arnaldo, It seems it's not merged into your tree as I still can see this issue. Would you consider applying? Thanks, Namhyung On Fri, 14 Sep 2012 17:35:29 +0900, Namhyung Kim wrote: From: Namhyung Kim namhyung@lge.com The hist_entry__sort_snprintf() can return 0 if all of the sort keys are elided. In this case a buffer which used for the function would contain old message or a garbage and printed like below: $ perf record -g -e cycles:u abc $ perf --report -s comm -c abc (...) + 100.00%100.00% Fix it by checking return value. Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/browsers/hists.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a21f40bebbac..75b3898ca651 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -664,8 +664,8 @@ static int hist_browser__show_entry(struct hist_browser *browser, if (!browser-b.navkeypressed) width += 1; - hist_entry__sort_snprintf(entry, s, sizeof(s), browser-hists); - slsmg_write_nstring(s, width); + if (hist_entry__sort_snprintf(entry, s, sizeof(s), browser-hists)) + slsmg_write_nstring(s, width); ++row; ++printed; } else @@ -981,7 +981,6 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.use_callchain) folded_sign = hist_entry__folded(he); - hist_entry__sort_snprintf(he, s, sizeof(s), browser-hists); percent = (he-period * 100.0) / browser-hists-stats.total_period; if (symbol_conf.use_callchain) @@ -995,7 +994,8 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, if (symbol_conf.show_total_period) printed += fprintf(fp, %12 PRIu64, he-period); - printed += fprintf(fp, %s\n, rtrim(s)); + if (hist_entry__sort_snprintf(he, s, sizeof(s), browser-hists)) + printed += fprintf(fp, %s\n, rtrim(s)); if (folded_sign == '-') printed += hist_browser__fprintf_callchain(browser, he-sorted_chain, 1, fp); -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] fix compilation error of perf/core
Hi Dong, On Tue, 25 Sep 2012 16:21:25 +0800, Dong Hao wrote: From: Dong Hao haod...@linux.vnet.ibm.com The newest branch of perf/core should have compilation error! Error log includes: builtin-test.c: In function ‘perf_evsel__test_field’: builtin-test.c:1216:6: error: variable ‘ret’ set but not used [-Werror=unused-but-set-variable] builtin-test.c: In function ‘perf_evsel__tp_sched_test’: builtin-test.c:1242:6: error: variable ‘ret’ set but not used [-Werror=unused-but-set-variable] cc1: all warnings being treated as errors make: *** [builtin-test.o] Error 1 - Fix it by replacing return value from 0 to ret. Then this branch can be compiled successfully. Signed-off-by: Dong Hao haod...@linux.vnet.ibm.com I already sent the same patch: https://lkml.org/lkml/2012/9/24/689 Thanks for fixing it anyway! Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] tools lib traceevent: Fix error path on pevent_parse_event
If __pevent_parse_format() succeeded but add_event() failed, 'ret' didn't have a proper error code. Set it to PEVENT_ERRNO__MEM_ALLOC_FAILED. In addition, at that point 'event' also has fields and format information and they all need to be freed. Call pevent_free_format() to handle it. Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/lib/traceevent/event-parse.c |8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 17c922145e88..47264b4652b9 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -5044,8 +5044,10 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, /* Add pevent to event so that it can be referenced */ event-pevent = pevent; - if (add_event(pevent, event)) + if (add_event(pevent, event)) { + ret = PEVENT_ERRNO__MEM_ALLOC_FAILED; goto event_add_failed; + } #define PRINT_ARGS 0 if (PRINT_ARGS event-print_fmt.args) @@ -5054,9 +5056,7 @@ enum pevent_errno pevent_parse_event(struct pevent *pevent, const char *buf, return 0; event_add_failed: - free(event-system); - free(event-name); - free(event); + pevent_free_format(event); return ret; } -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 1/9] perf hists: Move hists_init() from util/evsel.c to util/hist.c
2012-09-25 (화), 08:05 -0300, Arnaldo Carvalho de Melo: Em Tue, Sep 25, 2012 at 10:25:13AM +0900, Namhyung Kim escreveu: On Mon, 24 Sep 2012 13:02:39 -0300, Arnaldo Carvalho de Melo wrote: Em Mon, Sep 24, 2012 at 11:24:03PM +0800, Feng Tang escreveu: Which looks more natural It is there to avoid dragging the hist code into the python binding :-\ Hmm... it's so hairy. Can't we do better? We always can do better :-) I just stated why it was at that place. When doing refactorings we're all the time trying to make it better in many senses, one of them is trying to isolate code that is useful in a general way and thus should be made available via a library/scripting binding. Yeah, but the isolation sometimes got broken as code getting added like this. So we need a automatic way of detecting breakage. I thought about adding a perf test entry running python/twatch.py, but it will not work for an installed perf binary since it cannot find the twatch.py script and perf.so extension files which are not installed. Now I'm thinking of making it build-time test so that it can be executed by make when specific argument is given - e.g. make C=1 ? Thanks Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 3/4] perf annotate: configure objdump path at compile time
Hi Irina, 2012-09-23 (일), 22:27 +0300, Irina Tirdea: From: Irina Tirdea irina.tir...@intel.com The default name for objdump is objdump. For cross-compiling the name of objdump will be different (e.g. arm-eabi-objdump in Android). Set the default objdump name in the Makefile with DEFAULT_OBJDUMP_PATH. I thought about it twice and confused. For cross-compiling, the resulting perf binary will run on target - say Android - but the toolchain runs on host, right? So with this change the cross-built perf will try to find the arm-eabi-objdump on Android. Is it an intended behavior? Is there an arm-eabi-objdump on Android? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: perf tools regression testing was Re: [PATCH v3 1/9] perf hists: Move hists_init() from util/evsel.c to util/hist.c
2012-09-25 (화), 10:30 -0300, Arnaldo Carvalho de Melo: Em Tue, Sep 25, 2012 at 09:59:02PM +0900, Namhyung Kim escreveu: Now I'm thinking of making it build-time test so that it can be executed by make when specific argument is given - e.g. make C=1 ? I think there is room for a 'make -C tools/perf check' that would use the 'expect' tool to do not just this but also run record, report, etc and check its output against what is expected, perf test is ok for checking the APIs, but we need a test suite for the actual builtins as called from the command line. Hmm.. we have 'make check' but running it ended up tons of macro redefinition and unknown attribute warnings from sparse. :/ Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 10/16] perf report: Make another loop for output resorting
From: Namhyung Kim namhyung@lge.com Now the event grouping viewing requires collapsing all members in a group to the leader. Thus hists__output_resort should be called after collapsing all entries in evlist. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c | 5 + 1 file changed, 5 insertions(+) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1da243dfbc3e..7729c1c290e6 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -416,6 +416,11 @@ static int __cmd_report(struct perf_report *rep) hists-symbol_filter_str = rep-symbol_filter_str; hists__collapse_resort(hists); + } + + list_for_each_entry(pos, session-evlist-entries, node) { + struct hists *hists = pos-hists; + hists__output_resort(hists); nr_samples += hists-stats.nr_events[PERF_RECORD_SAMPLE]; } -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 02/16] perf hists: Introduce struct he_stat
From: Namhyung Kim namhyung@lge.com The struct he_stat is for separating out statistics data of a hist entry. It is required for later changes. It's just a mechanical change and should have no functional differences. Cc: Jiri Olsa jo...@redhat.com Cc: Arun Sharma asha...@fb.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/browsers/hists.c | 8 +++ tools/perf/ui/gtk/browser.c| 2 +- tools/perf/ui/hist.c | 32 +- tools/perf/ui/stdio/hist.c | 2 +- tools/perf/util/hist.c | 52 +++--- tools/perf/util/sort.h | 16 - 6 files changed, 60 insertions(+), 52 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a21f40bebbac..b9b1b173637c 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -569,7 +569,7 @@ static int hist_browser__show_callchain(struct hist_browser *browser, static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ - double percent = 100.0 * he-_field / hpp-total_period;\ + double percent = 100.0 * he-stat._field / hpp-total_period; \ *(double *)hpp-ptr = percent; \ return scnprintf(hpp-buf, hpp-size, %6.2f%%, percent); \ } @@ -982,7 +982,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, folded_sign = hist_entry__folded(he); hist_entry__sort_snprintf(he, s, sizeof(s), browser-hists); - percent = (he-period * 100.0) / browser-hists-stats.total_period; + percent = (he-stat.period * 100.0) / browser-hists-stats.total_period; if (symbol_conf.use_callchain) printed += fprintf(fp, %c , folded_sign); @@ -990,10 +990,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, printed += fprintf(fp, %5.2f%%, percent); if (symbol_conf.show_nr_samples) - printed += fprintf(fp, %11u, he-nr_events); + printed += fprintf(fp, %11u, he-stat.nr_events); if (symbol_conf.show_total_period) - printed += fprintf(fp, %12 PRIu64, he-period); + printed += fprintf(fp, %12 PRIu64, he-stat.period); printed += fprintf(fp, %s\n, rtrim(s)); diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 7ff99ec1d95e..7107edc6c08d 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -49,7 +49,7 @@ static const char *perf_gtk__get_percent_color(double percent) static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ - double percent = 100.0 * he-_field / hpp-total_period; \ + double percent = 100.0 * he-stat._field / hpp-total_period; \ const char *markup; \ int ret = 0; \ \ diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index e3f8cd46e7d7..d6ddeb10e678 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -20,12 +20,12 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) { - double percent = 100.0 * he-period / hpp-total_period; + double percent = 100.0 * he-stat.period / hpp-total_period; if (hpp-ptr) { struct hists *old_hists = hpp-ptr; u64 total_period = old_hists-stats.total_period; - u64 base_period = he-pair ? he-pair-period : 0; + u64 base_period = he-pair ? he-pair-stat.period : 0; if (total_period) percent = 100.0 * base_period / total_period; @@ -38,13 +38,13 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) { - double percent = 100.0 * he-period / hpp-total_period; + double percent = 100.0 * he-stat.period / hpp-total_period; const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; if (hpp-ptr) { struct hists *old_hists = hpp-ptr; u64 total_period = old_hists-stats.total_period; - u64 base_period = he-pair ? he-pair-period : 0; + u64 base_period = he-pair ? he-pair-stat.period : 0; if (total_period
[PATCH 05/16] perf tools: Keep group information
From: Namhyung Kim namhyung@lge.com Add a few of group-related field in struct perf_{evlist,evsel} so that the group information in a evlist can be known easily. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/evlist.c | 10 -- tools/perf/util/evlist.h | 1 + tools/perf/util/evsel.h| 10 ++ tools/perf/util/parse-events.c | 1 + tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.y | 4 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 892353729c7a..199b6f1c3b22 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -111,20 +111,26 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist, void __perf_evlist__set_leader(struct list_head *list) { struct perf_evsel *evsel, *leader; + int count = 0; leader = list_entry(list-next, struct perf_evsel, node); leader-leader = NULL; list_for_each_entry(evsel, list, node) { - if (evsel != leader) + if (evsel != leader) { evsel-leader = leader; + evsel-group_idx = count++; + } } + leader-nr_members = count; } void perf_evlist__set_leader(struct perf_evlist *evlist) { - if (evlist-nr_entries) + if (evlist-nr_entries) { + evlist-nr_groups = 1; __perf_evlist__set_leader(evlist-entries); + } } int perf_evlist__add_default(struct perf_evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 3f2e1e4ccdd5..946a6ada817b 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -21,6 +21,7 @@ struct perf_evlist { struct list_head entries; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; int nr_entries; + int nr_groups; int nr_fds; int nr_mmaps; int mmap_len; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index bb445d1cbc7b..820f005096c4 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -73,6 +73,10 @@ struct perf_evsel { int exclude_GH; struct perf_evsel *leader; char*group_name; + union { + int nr_members; + int group_idx; + }; }; struct cpu_map; @@ -211,4 +215,10 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) { return list_entry(evsel-node.next, struct perf_evsel, node); } + +/* Treat a non-group event as a leader */ +static inline bool perf_evsel__is_group_leader(struct perf_evsel *evsel) +{ + return evsel-leader == NULL; +} #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index bf5d033ee1b4..3c52d0ab9270 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -830,6 +830,7 @@ int parse_events(struct perf_evlist *evlist, const char *str, if (!ret) { int entries = data.idx - evlist-nr_entries; perf_evlist__splice_list_tail(evlist, data.list, entries); + evlist-nr_groups += data.nr_groups; return 0; } diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index c356e443448d..f6b0254afe17 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -65,6 +65,7 @@ struct parse_events__term { struct parse_events_data__events { struct list_head list; int idx; + int nr_groups; }; struct parse_events_data__terms { diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index cd88209e3c58..d14bb507594b 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -122,7 +122,9 @@ group_def: PE_NAME '{' events '}' { struct list_head *list = $3; + struct parse_events_data__events *data = _data; + data-nr_groups++; parse_events__set_leader($1, list); $$ = list; } @@ -130,7 +132,9 @@ PE_NAME '{' events '}' '{' events '}' { struct list_head *list = $2; + struct parse_events_data__events *data = _data; + data-nr_groups++; parse_events__set_leader(NULL, list); $$ = list; } -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 16/16] perf report: Add --group option
From: Namhyung Kim namhyung@lge.com Add --group option to enable event grouping. When enabled, all the group members information will be shown together with the leader. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 3a4bd13340db..034eec9f09f5 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -664,6 +664,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 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_BOOLEAN(0, group, symbol_conf.event_group, + Show event group information together), OPT_CALLBACK_NOOPT('b', branch-stack, sort__branch_mode, , use branch records for histogram filling, parse_branch_mode), OPT_STRING(0, objdump, objdump_path, path, -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 15/16] perf report: Show group description when event group is enabled
From: Namhyung Kim namhyung@lge.com When using event group viewer, it's better to show the group description rather than the leader information alone. If a leader did not contain any member, it's a non-group event. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Cc: Pekka Enberg penb...@kernel.org Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c| 18 ++ tools/perf/ui/browsers/hists.c | 31 +++ tools/perf/ui/gtk/browser.c| 14 +++--- tools/perf/util/evsel.c| 25 + tools/perf/util/evsel.h| 8 5 files changed, 93 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 52803a9d3e3e..3a4bd13340db 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -299,6 +299,24 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self, char unit; unsigned long nr_samples = self-stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = self-stats.total_period; + struct perf_evsel *evsel = hists_2_evsel(self); + char buf[512]; + size_t size = sizeof(buf); + + if (symbol_conf.event_group evsel-nr_members) { + int i; + struct events_stats *stats; + + perf_evsel__group_desc(evsel, buf, size); + evname = buf; + + for (i = 0; i evsel-nr_members; i++) { + stats = self-group_stats[i]; + + nr_samples += stats-nr_events[PERF_RECORD_SAMPLE]; + nr_events += stats-total_period; + } + } nr_samples = convert_unit(nr_samples, unit); ret = fprintf(fp, # Samples: %lu%c, nr_samples, unit); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 82d59be3c230..7903b98913c5 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1121,6 +1121,24 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size, const struct thread *thread = hists-thread_filter; unsigned long nr_samples = hists-stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = hists-stats.total_period; + struct perf_evsel *evsel = hists_2_evsel(hists); + char buf[512]; + size_t buflen = sizeof(buf); + + if (symbol_conf.event_group evsel-nr_members) { + int i; + struct events_stats *stats; + + perf_evsel__group_desc(evsel, buf, buflen); + ev_name = buf; + + for (i = 0; i evsel-nr_members; i++) { + stats = hists-group_stats[i]; + + nr_samples += stats-nr_events[PERF_RECORD_SAMPLE]; + nr_events += stats-total_period; + } + } nr_samples = convert_unit(nr_samples, unit); printed = scnprintf(bf, size, @@ -1467,6 +1485,19 @@ static void perf_evsel_menu__write(struct ui_browser *browser, ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : HE_COLORSET_NORMAL); + if (symbol_conf.event_group evsel-nr_members) { + int i; + struct events_stats *stats; + + ev_name = perf_evsel__group_name(evsel); + + for (i = 0; i evsel-nr_members; i++) { + stats = evsel-hists.group_stats[i]; + + nr_events += stats-nr_events[PERF_RECORD_SAMPLE]; + } + } + nr_events = convert_unit(nr_events, unit); printed = scnprintf(bf, sizeof(bf), %lu%c%s%s, nr_events, unit, unit == ' ' ? : , ev_name); diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 01bfa43db8e2..cb6241e7f9a5 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -305,10 +305,18 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *evname = perf_evsel__name(pos); GtkWidget *scrolled_window; GtkWidget *tab_label; + char buf[512]; + size_t size = sizeof(buf); - if (symbol_conf.event_group - !perf_evsel__is_group_leader(pos)) - continue; + if (symbol_conf.event_group) { + if (!perf_evsel__is_group_leader(pos)) + continue; + + if (pos-nr_members) { + perf_evsel__group_desc(pos, buf, size); + evname = buf; + } + } scrolled_window = gtk_scrolled_window_new(NULL, NULL); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 00936ad29ff2
[PATCH 04/16] perf hists: Add more helpers for hist entry stat
From: Namhyung Kim namhyung@lge.com Add and use he_stat__add_{period,stat} for calculating hist entry's stat. It will be used for accumulated stats later as well. Cc: Jiri Olsa jo...@redhat.com Cc: Arun Sharma asha...@fb.com Cc: Stephane Eranian eran...@google.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c | 26 ++ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index ef39e6714cbb..c742a723e850 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -151,6 +151,22 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he, } } +static void he_stat__add_period(struct he_stat *he_stat, u64 period) +{ + he_stat-period += period; + he_stat-nr_events += 1; +} + +static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) +{ + dest-period+= src-period; + dest-period_sys+= src-period_sys; + dest-period_us += src-period_us; + dest-period_guest_sys += src-period_guest_sys; + dest-period_guest_us += src-period_guest_us; + dest-nr_events += src-nr_events; +} + static void hist_entry__decay(struct hist_entry *he) { he-stat.period = (he-stat.period * 7) / 8; @@ -270,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, cmp = hist_entry__cmp(entry, he); if (!cmp) { - he-stat.period += period; - ++he-stat.nr_events; + he_stat__add_period(he-stat, period); /* If the map of an existing hist_entry has * become out-of-date due to an exec() or @@ -416,12 +431,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, cmp = hist_entry__collapse(iter, he); if (!cmp) { - iter-stat.period += he-stat.period; - iter-stat.period_sys += he-stat.period_sys; - iter-stat.period_us+= he-stat.period_us; - iter-stat.period_guest_sys += he-stat.period_guest_sys; - iter-stat.period_guest_us += he-stat.period_guest_us; - iter-stat.nr_events+= he-stat.nr_events; + he_stat__add_stat(iter-stat, he-stat); if (symbol_conf.use_callchain) { callchain_cursor_reset(callchain_cursor); -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 03/16] perf hists: Move he-stat.nr_events initialization to a template
From: Namhyung Kim namhyung@lge.com Since it is set to 1 for a new hist entry, no need to set to separately. Move it to a template entry. Cc: Jiri Olsa jo...@redhat.com Cc: Arun Sharma asha...@fb.com Cc: Stephane Eranian eran...@google.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index ab3d11491991..ef39e6714cbb 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -223,7 +223,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) if (he != NULL) { *he = *template; - he-stat.nr_events = 1; + if (he-ms.map) he-ms.map-referenced = true; if (symbol_conf.use_callchain) @@ -323,6 +323,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, .level = al-level, .stat = { .period = period, + .nr_events = 1, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), @@ -347,6 +348,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, .level = al-level, .stat = { .period = period, + .nr_events = 1, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 14/16] perf report: Bypass non-leader events when event group is enabled
From: Namhyung Kim namhyung@lge.com Since we have all necessary information in the leader events and other members don't, bypass members. Member events will be shown along with the leaders if event group is enabled. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Cc: Pekka Enberg penb...@kernel.org Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c| 4 tools/perf/ui/browsers/hists.c | 39 +-- tools/perf/ui/gtk/browser.c| 4 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 7729c1c290e6..52803a9d3e3e 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -319,6 +319,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, struct hists *hists = pos-hists; const char *evname = perf_evsel__name(pos); + if (symbol_conf.event_group + !perf_evsel__is_group_leader(pos)) + continue; + hists__fprintf_nr_sample_events(hists, evname, stdout); hists__fprintf(hists, NULL, false, true, 0, 0, stdout); fprintf(stdout, \n\n); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index da3d1e4a44fa..82d59be3c230 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1576,8 +1576,19 @@ out: return key; } +static bool filter_group_entries(struct ui_browser *self __maybe_unused, +void *entry) +{ + struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); + + if (symbol_conf.event_group !perf_evsel__is_group_leader(evsel)) + return true; + + return false; +} + static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, - const char *help, + int nr_entries, const char *help, void(*timer)(void *arg), void *arg, int delay_secs) { @@ -1588,7 +1599,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, .refresh= ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = perf_evsel_menu__write, - .nr_entries = evlist-nr_entries, + .filter = filter_group_entries, + .nr_entries = nr_entries, .priv = evlist, }, }; @@ -1603,7 +1615,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, menu.b.width = line_len; } - return perf_evsel_menu__run(menu, evlist-nr_entries, help, timer, + return perf_evsel_menu__run(menu, nr_entries, help, timer, arg, delay_secs); } @@ -1611,15 +1623,30 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, void(*timer)(void *arg), void *arg, int delay_secs) { - if (evlist-nr_entries == 1) { + int nr_entries = evlist-nr_entries; + +single_entry: + if (nr_entries == 1) { struct perf_evsel *first = list_entry(evlist-entries.next, struct perf_evsel, node); const char *ev_name = perf_evsel__name(first); - return perf_evsel__hists_browse(first, evlist-nr_entries, help, + return perf_evsel__hists_browse(first, nr_entries, help, ev_name, false, timer, arg, delay_secs); } - return __perf_evlist__tui_browse_hists(evlist, help, + if (symbol_conf.event_group) { + struct perf_evsel *pos; + + nr_entries = 0; + list_for_each_entry(pos, evlist-entries, node) + if (perf_evsel__is_group_leader(pos)) + nr_entries++; + + if (nr_entries == 1) + goto single_entry; + } + + return __perf_evlist__tui_browse_hists(evlist, nr_entries, help, timer, arg, delay_secs); } diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 775f209fe795..01bfa43db8e2 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -306,6 +306,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, GtkWidget *scrolled_window; GtkWidget *tab_label; + if (symbol_conf.event_group
[PATCH 13/16] perf ui/gtk: Add support for event group view
From: Namhyung Kim namhyung@lge.com Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Cc: Pekka Enberg penb...@kernel.org Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/gtk/browser.c | 58 +++-- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 7107edc6c08d..775f209fe795 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -45,25 +45,56 @@ static const char *perf_gtk__get_percent_color(double percent) return NULL; } +static int perf_gtk__percent_color_snprintf(char *buf, size_t size, + u64 period, u64 total_period) +{ + int ret = 0; + const char *markup; + double percent = 100.0 * period / total_period; + + markup = perf_gtk__get_percent_color(percent); + if (markup) + ret += scnprintf(buf, size, markup); + + ret += scnprintf(buf + ret, size - ret, %6.2f%%, percent); + + if (markup) + ret += scnprintf(buf + ret, size - ret, /span); + + return ret; +} + +static int perf_gtk__hpp_color_overhead(struct perf_hpp *hpp, + struct hist_entry *he) +{ + int ret; + + ret = perf_gtk__percent_color_snprintf(hpp-buf, hpp-size, + he-stat.period, hpp-total_period); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hpp-hists); + + for (i = 0; i evsel-nr_members; i++) { + ret += scnprintf(hpp-buf + ret, hpp-size - ret, ); + ret += perf_gtk__percent_color_snprintf(hpp-buf + ret, + hpp-size - ret, + he-group_stats[i].period, + hpp-hists-group_stats[i].total_period); + } + } + return ret; +} + #define HPP__COLOR_FN(_name, _field) \ static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ - double percent = 100.0 * he-stat._field / hpp-total_period; \ - const char *markup; \ - int ret = 0; \ - \ - markup = perf_gtk__get_percent_color(percent); \ - if (markup) \ - ret += scnprintf(hpp-buf, hpp-size, %s, markup); \ - ret += scnprintf(hpp-buf + ret, hpp-size - ret, %6.2f%%, percent); \ - if (markup) \ - ret += scnprintf(hpp-buf + ret, hpp-size - ret, /span); \ - \ - return ret; \ + return perf_gtk__percent_color_snprintf(hpp-buf, hpp-size, \ + he-stat._field, hpp-total_period); \ } -HPP__COLOR_FN(overhead, period) HPP__COLOR_FN(overhead_sys, period_sys) HPP__COLOR_FN(overhead_us, period_us) HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) @@ -103,6 +134,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) .buf= s, .size = sizeof(s), .total_period = hists-stats.total_period, + .hists = hists, }; nr_cols = 0; -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 12/16] perf ui/browser: Add support for event group view
From: Namhyung Kim namhyung@lge.com Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/browsers/hists.c | 29 - tools/perf/ui/hist.c | 5 - 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index b9b1b173637c..da3d1e4a44fa 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -565,6 +565,33 @@ static int hist_browser__show_callchain(struct hist_browser *browser, return row - first_row; } +static int hist_browser__hpp_color_overhead(struct perf_hpp *hpp, + struct hist_entry *he) +{ + int ret; + double percent = 100.0 * he-stat.period / hpp-total_period; + + /* the leader determines color */ + *(double *) hpp-ptr = percent; + + ret = scnprintf(hpp-buf, hpp-size, %6.2f%%, percent); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hpp-hists); + + for (i = 0; i evsel-nr_members; i++) { + u64 period = he-group_stats[i].period; + u64 total = hpp-hists-group_stats[i].total_period; + + percent = 100.0 * period / total; + ret += scnprintf(hpp-buf + ret, hpp-size - ret, + %6.2f%%, percent); + } + } + return ret; +} + #define HPP__COLOR_FN(_name, _field) \ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ @@ -574,7 +601,6 @@ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ return scnprintf(hpp-buf, hpp-size, %6.2f%%, percent); \ } -HPP__COLOR_FN(overhead, period) HPP__COLOR_FN(overhead_sys, period_sys) HPP__COLOR_FN(overhead_us, period_us) HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) @@ -625,6 +651,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, .buf= s, .size = sizeof(s), .total_period = browser-hists-stats.total_period, + .hists = browser-hists, }; ui_browser__gotorc(browser-b, row, 0); diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index b8e97c3577c1..d8491fcff6ee 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -422,6 +422,9 @@ unsigned int hists__sort_list_width(struct hists *hists) { struct sort_entry *se; int i, ret = 0; + struct perf_hpp dummy_hpp = { + .hists = hists, + }; for (i = 0; i PERF_HPP__MAX_INDEX; i++) { if (!perf_hpp__format[i].cond) @@ -429,7 +432,7 @@ unsigned int hists__sort_list_width(struct hists *hists) if (i) ret += 2; - ret += perf_hpp__format[i].width(NULL); + ret += perf_hpp__format[i].width(dummy_hpp); } list_for_each_entry(se, hist_entry__sort_list, list) -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 11/16] perf ui/hist: Add support for event group view
From: Namhyung Kim namhyung@lge.com Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/hist.c | 67 +- tools/perf/ui/stdio/hist.c | 2 ++ tools/perf/util/hist.h | 1 + 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index d6ddeb10e678..b8e97c3577c1 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -3,23 +3,40 @@ #include ../util/hist.h #include ../util/util.h #include ../util/sort.h +#include ../util/evsel.h /* hist period print (hpp) functions */ static int hpp__header_overhead(struct perf_hpp *hpp) { + int len = 8; const char *fmt = hpp-ptr ? Baseline : Overhead; - return scnprintf(hpp-buf, hpp-size, fmt); + if (symbol_conf.event_group) { + struct perf_evsel *evsel = hists_2_evsel(hpp-hists); + + BUG_ON(!perf_evsel__is_group_leader(evsel)); + + len += evsel-nr_members * 8; + } + return scnprintf(hpp-buf, hpp-size, %*s, len, fmt); } -static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_overhead(struct perf_hpp *hpp) { - return 8; + int len = 8; + + if (symbol_conf.event_group) { + struct perf_evsel *evsel = hists_2_evsel(hpp-hists); + + len += evsel-nr_members * 8; + } + return len; } static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) { + int ret; double percent = 100.0 * he-stat.period / hpp-total_period; if (hpp-ptr) { @@ -33,11 +50,29 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) percent = 0.0; } - return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); + ret = percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hpp-hists); + + for (i = 0; i evsel-nr_members; i++) { + u64 period = he-group_stats[i].period; + u64 total = hpp-hists-group_stats[i].total_period; + + percent = 100.0 * period / total; + ret += percent_color_snprintf(hpp-buf + ret, + hpp-size - ret, + %6.2f%%, percent); + } + + } + return ret; } static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) { + int ret; double percent = 100.0 * he-stat.period / hpp-total_period; const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; @@ -52,13 +87,32 @@ static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) percent = 0.0; } - return scnprintf(hpp-buf, hpp-size, fmt, percent); + ret = scnprintf(hpp-buf, hpp-size, fmt, percent); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hpp-hists); + + for (i = 0; i evsel-nr_members; i++) { + u64 period = he-group_stats[i].period; + u64 total = hpp-hists-group_stats[i].total_period; + + if (symbol_conf.field_sep) { + ret += scnprintf(hpp-buf + ret, +hpp-size - ret, ); + } + percent = 100.0 * period / total; + ret += scnprintf(hpp-buf + ret, hpp-size - ret, +fmt, percent); + } + + } + return ret; } static int hpp__header_overhead_sys(struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? %s : %7s; - return scnprintf(hpp-buf, hpp-size, fmt, sys); } @@ -84,7 +138,6 @@ static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) static int hpp__header_overhead_us(struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? %s : %7s; - return scnprintf(hpp-buf, hpp-size, fmt, user); } diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 4382a1995cda..8c417f036613 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -316,6 +316,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, .buf= bf, .size = size
[PATCH 09/16] perf hists: Maintain total periods of group members in the leader
From: Namhyung Kim namhyung@lge.com Like group_stats in hist_entry, total periods information also need to be known to the leader. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c | 25 + tools/perf/util/hist.h | 1 + 2 files changed, 26 insertions(+) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 319822dee77b..8f01fc46ca88 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -194,6 +194,28 @@ static void hist_entry__add_group_stat(struct hist_entry *he_dest, he_stat__add_stat(he_dest-group_stats[evsel-group_idx], src); } +static void hists__add_group_stat(struct hists *hists) +{ + struct perf_evsel *evsel = hists_2_evsel(hists); + struct perf_evsel *leader = evsel-leader; + struct hists *leader_hists; + + if (perf_evsel__is_group_leader(evsel)) + return; + + leader_hists = leader-hists; + + if (!leader_hists-group_stats) { + leader_hists-group_stats = calloc(leader-nr_members, + sizeof(struct events_stats)); + if (!leader_hists-group_stats) + return; + } + + memcpy(leader_hists-group_stats[evsel-group_idx], + hists-stats, sizeof(struct events_stats)); +} + static void hist_entry__decay(struct hist_entry *he) { he-stat.period = (he-stat.period * 7) / 8; @@ -557,6 +579,9 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded) hists__apply_filters(hists, n); } } + + if (symbol_conf.event_group) + hists__add_group_stat(hists); } void hists__collapse_resort(struct hists *hists) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index f011ad4756e8..e13db91bc246 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -66,6 +66,7 @@ struct hists { const char *symbol_filter_str; pthread_mutex_t lock; struct events_stats stats; + struct events_stats *group_stats; u64 event_stream; u16 col_len[HISTC_NR_COLS]; }; -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 07/16] perf header: Add HEADER_GROUP_DESC feature
From: Namhyung Kim namhyung@lge.com Save group relationship information so that it can be restored when perf report is running. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-record.c | 3 + tools/perf/util/header.c| 149 tools/perf/util/header.h| 2 + 3 files changed, 154 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 99ad5234e6ff..b2d9c0af9a15 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -561,6 +561,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) goto out_delete_session; } + if (!evsel_list-nr_groups) + perf_header__clear_feat(session-header, HEADER_GROUP_DESC); + /* * perf_session__delete(session) will be called at perf_record__exit() */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 6aae3290358e..0039c08ad4c7 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1072,6 +1072,41 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, } /* + * File format: + * + * struct group_descs { + * u32 nr_groups; + * struct group_desc { + * charname[]; + * u32 leader_idx; + * u32 nr_members; + * }[nr_groups]; + * }; + */ +static int write_group_desc(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist) +{ + u32 nr_groups = evlist-nr_groups; + struct perf_evsel *evsel; + + do_write(fd, nr_groups, sizeof(nr_groups)); + + list_for_each_entry(evsel, evlist-entries, node) { + if (perf_evsel__is_group_leader(evsel) + evsel-nr_members 0) { + const char *name = evsel-group_name ?: {anon_group}; + u32 leader_idx = evsel-idx; + u32 nr_members = evsel-nr_members; + + do_write_string(fd, name); + do_write(fd, leader_idx, sizeof(leader_idx)); + do_write(fd, nr_members, sizeof(nr_members)); + } + } + return 0; +} + +/* * default get_cpuid(): nothing gets recorded * actual implementation must be in arch/$(ARCH)/util/header.c */ @@ -1430,6 +1465,31 @@ error: fprintf(fp, # pmu mappings: unable to read\n); } +static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, +FILE *fp) +{ + struct perf_session *session; + struct perf_evsel *evsel; + u32 nr = 0; + + session = container_of(ph, struct perf_session, header); + + list_for_each_entry(evsel, session-evlist-entries, node) { + if (perf_evsel__is_group_leader(evsel) + evsel-nr_members 0) { + fprintf(fp, # group: %s{%s, evsel-group_name ?: , + perf_evsel__name(evsel)); + + nr = evsel-nr_members; + } else if (nr) { + fprintf(fp, ,%s, perf_evsel__name(evsel)); + + if (--nr == 0) + fprintf(fp, }\n); + } + } +} + static int __event_process_build_id(struct build_id_event *bev, char *filename, struct perf_session *session) @@ -1944,6 +2004,94 @@ error: return -1; } +static int process_group_desc(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int fd, + void *data __maybe_unused) +{ + size_t ret = -1; + u32 i, nr, nr_groups; + struct perf_session *session; + struct perf_evsel *evsel, *leader; + struct group_desc { + char *name; + u32 leader_idx; + u32 nr_members; + } *desc; + + ret = read(fd, nr_groups, sizeof(nr_groups)); + if (ret != sizeof(nr_groups)) + return -1; + + ph-env.nr_groups = nr_groups; + if (!nr_groups) { + pr_debug(group desc not available\n); + return 0; + } + + desc = calloc(nr_groups, sizeof(*desc)); + if (!desc) + return -1; + + for (i = 0; i nr_groups; i++) { + desc[i].name = do_read_string(fd, ph); + if (!desc[i].name) + goto out_free; + + ret = read(fd, desc[i].leader_idx, sizeof(u32)); + if (ret != sizeof(u32)) + goto out_free; + + ret = read(fd, desc[i].nr_members, sizeof(u32)); + if (ret != sizeof(u32)) + goto out_free
[PATCH 00/16] perf report: Add suppport for event group view (v2)
Hi, This is my second attempt to support event group on perf report. For basic idea and usage example, please see my original post [1]. The main difference than v1 is adding HEADER_GROUP_DESC feature and use it for regenerating group relationship on perf report. It will save actual (i.e. contains non-leader member) group information to perf header. Patch 1 is a bug fix which can be applied indenpedently. Patch 2-4 are cleanups to facilitate later changes and came from my cumulative report series [2]. You can also access it via my tree at: git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git perf/group-v2 Any comments are welcome, thanks, Namhyung v1 - v2: * save group relation to header (Jiri) * rebase on top of current acme/perf/core [1] https://lkml.org/lkml/2012/7/24/81 [2] https://lkml.org/lkml/2012/9/13/81 Namhyung Kim (16): perf hists: Add missing period_* fields when collapsing a hist entry perf hists: Introduce struct he_stat perf hists: Move he-stat.nr_events initialization to a template perf hists: Add more helpers for hist entry stat perf tools: Keep group information perf evlist: Add perf_evlist__recalc_nr_groups perf header: Add HEADER_GROUP_DESC feature perf hists: Collapse group hist_entries to a leader perf hists: Maintain total periods of group members in the leader perf report: Make another loop for output resorting perf ui/hist: Add support for event group view perf ui/browser: Add support for event group view perf ui/gtk: Add support for event group view perf report: Bypass non-leader events when event group is enabled perf report: Show group description when event group is enabled perf report: Add --group option tools/perf/builtin-record.c| 6 ++ tools/perf/builtin-report.c| 29 +++ tools/perf/ui/browsers/hists.c | 107 --- tools/perf/ui/gtk/browser.c| 70 --- tools/perf/ui/hist.c | 104 +-- tools/perf/ui/stdio/hist.c | 4 +- tools/perf/util/evlist.c | 26 +- tools/perf/util/evlist.h | 2 + tools/perf/util/evsel.c| 25 ++ tools/perf/util/evsel.h| 23 + tools/perf/util/header.c | 149 tools/perf/util/header.h | 2 + tools/perf/util/hist.c | 188 +++-- tools/perf/util/hist.h | 2 + tools/perf/util/parse-events.c | 1 + tools/perf/util/parse-events.h | 1 + tools/perf/util/parse-events.y | 4 + tools/perf/util/sort.h | 17 ++-- tools/perf/util/symbol.c | 4 + tools/perf/util/symbol.h | 3 +- 20 files changed, 683 insertions(+), 84 deletions(-) -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 08/16] perf hists: Collapse group hist_entries to a leader
From: Namhyung Kim namhyung@lge.com To support viewing an event group together, collapse all of members in the group to the leader's tree. The entries in the leaders' tree will have group_stats to store those information. This patch introduced an additional field 'event_group' in symbol_conf to distinguish whether event grouping is enabled or not. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/evsel.h | 5 +++ tools/perf/util/hist.c | 106 +++ tools/perf/util/sort.h | 1 + tools/perf/util/symbol.c | 4 ++ tools/perf/util/symbol.h | 3 +- 5 files changed, 110 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 820f005096c4..95f0bf17e79c 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -221,4 +221,9 @@ static inline bool perf_evsel__is_group_leader(struct perf_evsel *evsel) { return evsel-leader == NULL; } + +static inline struct perf_evsel *hists_2_evsel(struct hists *hists) +{ + return container_of(hists, struct perf_evsel, hists); +} #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index c742a723e850..319822dee77b 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -4,6 +4,7 @@ #include hist.h #include session.h #include sort.h +#include evsel.h #include math.h static bool hists__filter_entry_by_dso(struct hists *hists, @@ -167,6 +168,32 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) dest-nr_events += src-nr_events; } +static void hist_entry__add_group_stat(struct hist_entry *he_dest, + struct he_stat *src, + struct perf_evsel *evsel) +{ + struct perf_evsel *leader = evsel-leader; + + if (perf_evsel__is_group_leader(evsel)) + leader = evsel; + + if (leader-nr_members !he_dest-group_stats) { + /* +* A group whose nr_members equals to 0 is a leader-only group. +* So no need to allocate group_stats. +*/ + he_dest-group_stats = calloc(leader-nr_members, + sizeof(struct he_stat)); + if (!he_dest-group_stats) + return; + } + + if (perf_evsel__is_group_leader(evsel)) + he_stat__add_stat(he_dest-stat, src); + else + he_stat__add_stat(he_dest-group_stats[evsel-group_idx], src); +} + static void hist_entry__decay(struct hist_entry *he) { he-stat.period = (he-stat.period * 7) / 8; @@ -415,13 +442,14 @@ void hist_entry__free(struct hist_entry *he) * collapse the histogram */ -static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, +static bool hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, struct hist_entry *he) { struct rb_node **p = root-rb_node; struct rb_node *parent = NULL; struct hist_entry *iter; + struct perf_evsel *evsel = hists_2_evsel(hists); int64_t cmp; while (*p != NULL) { @@ -431,7 +459,10 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, cmp = hist_entry__collapse(iter, he); if (!cmp) { - he_stat__add_stat(iter-stat, he-stat); + if (symbol_conf.event_group) + hist_entry__add_group_stat(iter, he-stat, evsel); + else + he_stat__add_stat(iter-stat, he-stat); if (symbol_conf.use_callchain) { callchain_cursor_reset(callchain_cursor); @@ -449,6 +480,17 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, p = (*p)-rb_right; } + if (symbol_conf.event_group) { + /* +* 'he' is not found in the leader's tree. +* Insert it to the tree and setup stats properly. +*/ + hist_entry__add_group_stat(he, he-stat, evsel); + + if (!perf_evsel__is_group_leader(evsel)) + memset(he-stat, 0, sizeof(he-stat)); + } + rb_link_node(he-rb_node_in, parent, p); rb_insert_color(he-rb_node_in, root); return true; @@ -479,6 +521,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he) static void __hists__collapse_resort(struct hists *hists, bool threaded) { struct rb_root *root; + struct rb_root *dest; struct rb_node *next; struct hist_entry *n; @@ -486,14 +529,26 @@ static void
[PATCH 06/16] perf evlist: Add perf_evlist__recalc_nr_groups
From: Namhyung Kim namhyung@lge.com During the event parsing, perf_evlist can have leader-only groups which has nr_members as 1. Since they has no difference than a normal non-group event don't count them as a event group. Add perf_evlist__recalc_nr_groups to count actual group numbers. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-record.c | 3 +++ tools/perf/util/evlist.c| 16 tools/perf/util/evlist.h| 1 + 3 files changed, 20 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 2cb74343de3e..99ad5234e6ff 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -212,6 +212,9 @@ static int perf_record__open(struct perf_record *rec) if (opts-group) perf_evlist__set_leader(evlist); + if (evlist-nr_groups) + perf_evlist__recalc_nr_groups(evlist); + list_for_each_entry(pos, evlist-entries, node) { struct perf_event_attr *attr = pos-attr; /* diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index 199b6f1c3b22..0dcc443716b7 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -133,6 +133,22 @@ void perf_evlist__set_leader(struct perf_evlist *evlist) } } +void perf_evlist__recalc_nr_groups(struct perf_evlist *evlist) +{ + int count = 0; + struct perf_evsel *evsel; + + list_for_each_entry(evsel, evlist-entries, node) { + /* +* Don't count leader-only groups for simplicity. +*/ + if (perf_evsel__is_group_leader(evsel) + evsel-nr_members 0) + count++; + } + evlist-nr_groups = count; +} + int perf_evlist__add_default(struct perf_evlist *evlist) { struct perf_event_attr attr = { diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 946a6ada817b..439b1375c4ea 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -120,6 +120,7 @@ int perf_evlist__set_filters(struct perf_evlist *evlist); void __perf_evlist__set_leader(struct list_head *list); void perf_evlist__set_leader(struct perf_evlist *evlist); +void perf_evlist__recalc_nr_groups(struct perf_evlist *evlist); u64 perf_evlist__sample_type(struct perf_evlist *evlist); bool perf_evlist__sample_id_all(struct perf_evlist *evlist); -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 01/16] perf hists: Add missing period_* fields when collapsing a hist entry
From: Namhyung Kim namhyung@lge.com So that the perf report won't lost the cpu utilization information. For example, if there're two process that have same name. $ perf report --stdio --showcpuutilization -s pid [SNIP] # Overhead sysus Command: Pid # . # 55.12% 0.01%55.10% noploop:28781 44.88% 0.06%44.83% noploop:28782 Before: $ perf report --stdio --showcpuutilization -s comm [SNIP] # Overhead sysus # # 100.00% 0.06%44.83% After: $ perf report --stdio --showcpuutilization -s comm [SNIP] # Overhead sysus # # 100.00% 0.07%99.93% Cc: Jiri Olsa jo...@redhat.com Cc: Arun Sharma asha...@fb.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 6ec5398de89d..236bc9d98ff2 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -410,8 +410,13 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, cmp = hist_entry__collapse(iter, he); if (!cmp) { - iter-period += he-period; - iter-nr_events += he-nr_events; + iter-period+= he-period; + iter-period_sys+= he-period_sys; + iter-period_us += he-period_us; + iter-period_guest_sys += he-period_guest_sys; + iter-period_guest_us += he-period_guest_us; + iter-nr_events += he-nr_events; + if (symbol_conf.use_callchain) { callchain_cursor_reset(callchain_cursor); callchain_merge(callchain_cursor, -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 3/4] perf annotate: configure objdump path at compile time
On Thu, 27 Sep 2012 03:51:07 +0300, Irina Tirdea wrote: On Tue, Sep 25, 2012 at 4:08 PM, Namhyung Kim namhy...@kernel.org wrote: I thought about it twice and confused. For cross-compiling, the resulting perf binary will run on target - say Android - but the toolchain runs on host, right? So with this change the cross-built perf will try to find the arm-eabi-objdump on Android. Is it an intended behavior? Is there an arm-eabi-objdump on Android? Apparently I got confused about this as well... :) There are two perf binaries built for Android: one for the target (that will run on Android) and the other one for the host (that can be used to analyse data recorded on the target). As you mentioned, the perf built to run on Android needs to use objdump as objdump (actually Android does not yet have objdump, but this is the naming convention). In this case, objdump should not have the CROSS_COMPILE prefix. Ok. The perf built to run on the host needs to use arm-eabi-objdump from the toolchain so that it can analyse data recorded on Android. This patch is targeting this scenario, not the previous one. In this case, the CROSS_COMPILE option would be different than arm-eabi- so using $(CROSS_COMPILE)objdump would be wrong. objdump should be overridden when running make since there is no connection between the toolchain used here and the path for objdump. I am always overriding objdump when calling make, so I did not catch this. I think that I should change DEFAULT_OBJDUMP_PATH=objdump in the Makefile to handle the first scenario. I'll also explain this in the commit message so that it is more clear and make the same change for the addr2line patch. What do you think? I think the right thing to do is finding a correct objdump at runtime in some way. Why do you want to make it compile-time configurable? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 8/9] perf hists browser: Add option for runtime switching perf data file
Hi Feng, On Wed, 26 Sep 2012 15:57:07 +0800, Feng Tang wrote: On Tue, Sep 25, 2012 at 08:17:03AM -0300, Arnaldo Carvalho de Melo wrote: Em Tue, Sep 25, 2012 at 04:20:53PM +0800, Feng Tang escreveu: On Tue, 25 Sep 2012 11:11:21 +0900 Namhyung Kim namhy...@kernel.org wrote: Ditto. Plus it might leak previous input_name. Nice catch, will check the return value of strdup. For input_name mem leak, in some cases the input_name can't be called with free(), like those got from parse -i option. In case the old input_name is got from malloc through strdup, I think it's not a big issue given that buffer will be freed any way when the application exit. I think this is a matter of discipline, leaking is bad, kernel or userspace, why special case it? I see, then we need make sure all input_name point to a malloced buffer, here is a initial debug patch will only touch the annotate/report/script cmds, pls review and more suggestions are welcomed: Well, how about adding a flag like input_name_alloced and checking it before new allocation? This way we can avoid needless strdup when runtime switching is not used. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[BUG] build error on compiling builtin-trace
Hi Arnaldo, I've encountered a following error when building current acme/perf/core: CC builtin-trace.o builtin-trace.c:7:22: fatal error: libaudit.h: No such file or directory compilation terminated. make: *** [builtin-trace.o] Error 1 It'd better if you post patches to the list before updating your perf/core branch as many people rebase on the branch regularly. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 3/9] perf script: Add more filter to find_scripts()
On Wed, 26 Sep 2012 16:56:41 +0800, Feng Tang wrote: On Tue, 25 Sep 2012 10:47:03 +0900 Namhyung Kim namhy...@kernel.org wrote: It can't recognize extra spaces, multiple events connected by commas, event groups and probably more.. So I think it'd better if we can use parse_events() here - but w/o an evlist. Jiri, what do you think? Yes, this func was really a pain to me :) And fortunately, current intree xxx-record scripts are all in simple format: -e eventname , and this lightweight func basically works fine. I agree that we'd better have a separate parse_events() similar func to cherry-pick the events names in parse-events.c, to not make hists.c too heavy. And frankly speaking, I'm not familiar at all with these flex/bison handling, so can we do things in steps: fixes those space issue, add a fixme in comments and push the basically working version first? It'd not that hard. How about using below (untested) patch? Thanks, Namhyung diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index bf5d033ee1b4..5dc71f598028 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -817,6 +817,21 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } +int __parse_events(struct list_head *evsel_list, const char *str) +{ + int ret; + struct parse_events_data__events data = { + .list = LIST_HEAD_INIT(data.list), + }; + + ret = parse_events__scanner(str, data, PE_START_EVENTS); + if (!ret) { + list_splice(evsel_list, data.list); + return 0; + } + return -1; +} + int parse_events(struct perf_evlist *evlist, const char *str, int unset __maybe_unused) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index c356e443448d..c13e9bd0f041 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -32,6 +32,7 @@ extern int parse_events_option(const struct option *opt, const char *str, extern int parse_events(struct perf_evlist *evlist, const char *str, int unset); extern int parse_events_terms(struct list_head *terms, const char *str); +extern int __parse_events(struct list_head *evsel_list, const char *str); extern int parse_filter(const struct option *opt, const char *str, int unset); #define EVENTS_HELP_MAX (128*1024) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v3 3/9] perf script: Add more filter to find_scripts()
On Thu, 27 Sep 2012 13:45:30 +0900, Namhyung Kim wrote: It'd not that hard. How about using below (untested) patch? Hmm... it won't work for some cases. Please ignore this. Thanks, Namhyung diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index bf5d033ee1b4..5dc71f598028 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -817,6 +817,21 @@ int parse_events_terms(struct list_head *terms, const char *str) return ret; } +int __parse_events(struct list_head *evsel_list, const char *str) +{ + int ret; + struct parse_events_data__events data = { + .list = LIST_HEAD_INIT(data.list), + }; + + ret = parse_events__scanner(str, data, PE_START_EVENTS); + if (!ret) { + list_splice(evsel_list, data.list); + return 0; + } + return -1; +} + int parse_events(struct perf_evlist *evlist, const char *str, int unset __maybe_unused) { diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index c356e443448d..c13e9bd0f041 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -32,6 +32,7 @@ extern int parse_events_option(const struct option *opt, const char *str, extern int parse_events(struct perf_evlist *evlist, const char *str, int unset); extern int parse_events_terms(struct list_head *terms, const char *str); +extern int __parse_events(struct list_head *evsel_list, const char *str); extern int parse_filter(const struct option *opt, const char *str, int unset); #define EVENTS_HELP_MAX (128*1024) -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf tools: Check libaudit for perf-trace builtin
From: Namhyung Kim namhyung@lge.com The newly added trace command requires an external audit library. However it can cause a build error because it's not checked whether the libaudit is installed on system: CC builtin-trace.o builtin-trace.c:7:22: fatal error: libaudit.h: No such file or directory compilation terminated. make: *** [builtin-trace.o] Error 1 Cc: David Ahern dsah...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/Makefile | 16 ++-- tools/perf/config/feature-tests.mak | 11 +++ tools/perf/perf.c | 2 ++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 6958ba4f5dcb..5973f383eb8e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -102,7 +102,7 @@ ifdef PARSER_DEBUG endif CFLAGS = -fno-omit-frame-pointer -ggdb3 -funwind-tables -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS) -EXTLIBS = -lpthread -lrt -lelf -lm -laudit +EXTLIBS = -lpthread -lrt -lelf -lm ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE ALL_LDFLAGS = $(LDFLAGS) STRIP ?= strip @@ -442,7 +442,6 @@ BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o BUILTIN_OBJS += $(OUTPUT)builtin-lock.o BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o BUILTIN_OBJS += $(OUTPUT)builtin-test.o -BUILTIN_OBJS += $(OUTPUT)builtin-trace.o BUILTIN_OBJS += $(OUTPUT)builtin-inject.o PERFLIBS = $(LIB_FILE) $(LIBTRACEEVENT) @@ -560,6 +559,19 @@ else LIB_OBJS += $(OUTPUT)util/unwind.o endif +ifdef NO_LIBAUDIT + BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT +else + FLAGS_LIBAUDIT = $(ALL_CFLAGS) $(ALL_LDFLAGS) -laudit + ifneq ($(call try-cc,$(SOURCE_LIBAUDIT),$(FLAGS_LIBAUDIT)),y) + msg := $(warning No libaudit.h found, please install audit-libs-devel or libaudit-dev); + BASIC_CFLAGS += -DNO_LIBAUDIT_SUPPORT + else + BUILTIN_OBJS += $(OUTPUT)builtin-trace.o + EXTLIBS += -laudit + endif +endif + ifdef NO_NEWT BASIC_CFLAGS += -DNO_NEWT_SUPPORT else diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak index 116690a669d2..4add41bb0c7e 100644 --- a/tools/perf/config/feature-tests.mak +++ b/tools/perf/config/feature-tests.mak @@ -193,3 +193,14 @@ int main(void) } endef endif + +ifndef NO_LIBAUDIT +define SOURCE_LIBAUDIT +#include libaudit.h + +int main(void) +{ + return audit_open(); +} +endef +endif \ No newline at end of file diff --git a/tools/perf/perf.c b/tools/perf/perf.c index 3fb052c9a27f..fc2f770e3027 100644 --- a/tools/perf/perf.c +++ b/tools/perf/perf.c @@ -55,7 +55,9 @@ static struct cmd_struct commands[] = { { lock, cmd_lock, 0 }, { kvm,cmd_kvm,0 }, { test, cmd_test, 0 }, +#ifndef NO_LIBAUDIT_SUPPORT { trace, cmd_trace, 0 }, +#endif { inject, cmd_inject, 0 }, }; -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH v2 3/4] perf annotate: configure objdump path at compile time
On Thu, 27 Sep 2012 14:25:10 +0300, Irina Tirdea wrote: The perf built to run on the host needs to use arm-eabi-objdump from the toolchain so that it can analyse data recorded on Android. This patch is targeting this scenario, not the previous one. In this case, the CROSS_COMPILE option would be different than arm-eabi- so using $(CROSS_COMPILE)objdump would be wrong. objdump should be overridden when running make since there is no connection between the toolchain used here and the path for objdump. I am always overriding objdump when calling make, so I did not catch this. I think that I should change DEFAULT_OBJDUMP_PATH=objdump in the Makefile to handle the first scenario. I'll also explain this in the commit message so that it is more clear and make the same change for the addr2line patch. What do you think? I think the right thing to do is finding a correct objdump at runtime in some way. Why do you want to make it compile-time configurable? The correct objdump path can be detected at runtime by setting the toolchain path. But since the name is arm-eabi-objdump and not objdump, it does not know to use it instead. The only way (I can think of) to change objdump at runtime would be to use the --objdump option for perf annotate (and provide a similar option for addr2line). The problem with this approach is that the user has to be aware that perf annotate uses the objdump tool and that he has to use the cross-compiler version instead. Since the user will have perf compiled for host as part of his Android tree, he will expect it to work without these further changes from his part. The path for objdump can be set in the Android Makefile at compile time so that the user doesn't need to be aware of it. What I'm thinking is that perf can try to find cross-built binutils when it detects perf.data file is came from other machine/architecture. Fortunately perf_session_env was added recently and it has the arch information from the file so we can use it to find the path. Following patch is a proof-of-concept patch and only build tested. What do you think? Could you play with it for some time? :) Thanks, Namhyung From 7068a43a4b450c60fdcc8a3916ce624c1ef2c9b2 Mon Sep 17 00:00:00 2001 From: Namhyung Kim namhyung@lge.com Date: Thu, 27 Sep 2012 21:54:33 +0900 Subject: [RFC] perf tools: Try to find cross-built objdump path As we have architecture information of saved perf.data file, we can try to find cross-built objdump path. The triplets are incomplete and maybe need some regexp works. Cc: Irina Tirdea irina.tir...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/Makefile | 2 + tools/perf/arch/common.c | 42 +++ tools/perf/builtin-annotate.c | 3 ++ tools/perf/util/annotate.c| 96 +++ tools/perf/util/annotate.h| 10 + 5 files changed, 153 insertions(+) create mode 100644 tools/perf/arch/common.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 5973f383eb8e..b189229eb576 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -412,6 +412,8 @@ LIB_OBJS += $(OUTPUT)ui/helpline.o LIB_OBJS += $(OUTPUT)ui/hist.o LIB_OBJS += $(OUTPUT)ui/stdio/hist.o +LIB_OBJS += $(OUTPUT)arch/common.o + BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o # Benchmark modules diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c new file mode 100644 index ..c3872427d135 --- /dev/null +++ b/tools/perf/arch/common.c @@ -0,0 +1,42 @@ +#include stdio.h + +const char * const arm_triplets[] = { + arm-eabi-, + arm-unknown-linux-, + arm-unknown-linux-gnu-, + arm-unknown-linux-gnueabi-, + NULL +}; + +const char * const powerpc_triplets[] = { + powerpc-unknown-linux-gnu-, + powerpc64-unknown-linux-gnu-, + NULL +}; + +const char * const s390_triplets[] = { + s390-ibm-linux-, + NULL +}; + +const char * const sh_triplets[] = { + sh-unknown-linux-gnu-, + sh64-unknown-linux-gnu-, + NULL +}; + +const char * const sparc_triplets[] = { + sparc-unknown-linux-gnu-, + sparc64-unknown-linux-gnu-, + NULL +}; + +const char * const x86_triplets[] = { + x86_64-pc-linux-gnu-, + x86_64-unknown-linux-gnu-, + i686-pc-linux-gnu-, + i586-pc-linux-gnu-, + i486-pc-linux-gnu-, + i386-pc-linux-gnu-, + NULL +}; diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 9ea38540b873..20fe9bb6505b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -186,6 +186,9 @@ static int __cmd_annotate(struct perf_annotate *ann) goto out_delete; } + if (!objdump_path) + try_objdump_path(session); + ret = perf_session__process_events(session, ann-tool); if (ret) goto out_delete; diff
[RFC v2] perf tools: Try to find cross-built objdump path
From: Namhyung Kim namhyung@lge.com As we have architecture information of saved perf.data file, we can try to find cross-built objdump path. The triplets are incomplete and maybe need some regexp works. Cc: Irina Tirdea irina.tir...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- v2: don't modify env string tools/perf/Makefile | 2 + tools/perf/arch/common.c | 42 + tools/perf/builtin-annotate.c | 3 ++ tools/perf/util/annotate.c| 103 ++ tools/perf/util/annotate.h| 10 5 files changed, 160 insertions(+) create mode 100644 tools/perf/arch/common.c diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 5973f383eb8e..b189229eb576 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -412,6 +412,8 @@ LIB_OBJS += $(OUTPUT)ui/helpline.o LIB_OBJS += $(OUTPUT)ui/hist.o LIB_OBJS += $(OUTPUT)ui/stdio/hist.o +LIB_OBJS += $(OUTPUT)arch/common.o + BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o BUILTIN_OBJS += $(OUTPUT)builtin-bench.o # Benchmark modules diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c new file mode 100644 index ..c3872427d135 --- /dev/null +++ b/tools/perf/arch/common.c @@ -0,0 +1,42 @@ +#include stdio.h + +const char * const arm_triplets[] = { + arm-eabi-, + arm-unknown-linux-, + arm-unknown-linux-gnu-, + arm-unknown-linux-gnueabi-, + NULL +}; + +const char * const powerpc_triplets[] = { + powerpc-unknown-linux-gnu-, + powerpc64-unknown-linux-gnu-, + NULL +}; + +const char * const s390_triplets[] = { + s390-ibm-linux-, + NULL +}; + +const char * const sh_triplets[] = { + sh-unknown-linux-gnu-, + sh64-unknown-linux-gnu-, + NULL +}; + +const char * const sparc_triplets[] = { + sparc-unknown-linux-gnu-, + sparc64-unknown-linux-gnu-, + NULL +}; + +const char * const x86_triplets[] = { + x86_64-pc-linux-gnu-, + x86_64-unknown-linux-gnu-, + i686-pc-linux-gnu-, + i586-pc-linux-gnu-, + i486-pc-linux-gnu-, + i386-pc-linux-gnu-, + NULL +}; diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 9ea38540b873..20fe9bb6505b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -186,6 +186,9 @@ static int __cmd_annotate(struct perf_annotate *ann) goto out_delete; } + if (!objdump_path) + try_objdump_path(session); + ret = perf_session__process_events(session, ann-tool); if (ret) goto out_delete; diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index f0a910371377..df17c443e3b3 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -15,6 +15,7 @@ #include debug.h #include annotate.h #include pthread.h +#include sys/utsname.h const char *disassembler_style; const char *objdump_path; @@ -1140,3 +1141,105 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map, int evidx, return 0; } + +static bool lookup_path(char *name) +{ + bool found = false; + char *path, *tmp; + char buf[PATH_MAX]; + char *env = getenv(PATH); + + if (!env) + return false; + + env = strdup(env); + if (!env) + return false; + + path = strtok_r(env, :, tmp); + while (path) { + scnprintf(buf, sizeof(buf), %s%s, path, name); + if (access(buf, F_OK) == 0) { + found = true; + break; + } + strtok_r(NULL, :, tmp); + } + free(env); + return found; +} + +static int lookup_triplets(const char **triplets, const char *name) +{ + int i; + char buf[PATH_MAX]; + + for (i = 0; triplets[i] != NULL; i++) { + scnprintf(buf, sizeof(buf), %s%s, triplets[i], name); + if (lookup_path(buf)) + return i; + } + return -1; +} + +static char *try_binutils_path(struct perf_session *session, const char *name) +{ + int idx; + char *arch, *env; + struct utsname uts; + const char **path_list; + char buf[PATH_MAX]; + + if (uname(uts) 0) + return NULL; + + /* +* We don't need to try to find objdump path for native system. +* Just use default objdump. +*/ + if (!strcmp(uts.machine, session-header.env.arch)) + return NULL; + + env = getenv(CROSS_COMPILE); + if (env) { + scnprintf(buf, sizeof(buf), %s%s, env, name); + if (buf[0] == '/') { + if (access(buf, F_OK) == 0) + return strdup(buf); + + return NULL; + } + + if (lookup_path(buf)) + return
Re: [PATCH 05/16] perf tools: Keep group information
Hi Jiri, On Thu, 27 Sep 2012 19:03:52 +0200, Jiri Olsa wrote: diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index bf5d033ee1b4..3c52d0ab9270 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -830,6 +830,7 @@ int parse_events(struct perf_evlist *evlist, const char *str, if (!ret) { int entries = data.idx - evlist-nr_entries; perf_evlist__splice_list_tail(evlist, data.list, entries); +evlist-nr_groups += data.nr_groups; return 0; } diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index c356e443448d..f6b0254afe17 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -65,6 +65,7 @@ struct parse_events__term { struct parse_events_data__events { struct list_head list; int idx; +int nr_groups; }; struct parse_events_data__terms { diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index cd88209e3c58..d14bb507594b 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -122,7 +122,9 @@ group_def: PE_NAME '{' events '}' { struct list_head *list = $3; +struct parse_events_data__events *data = _data; +data-nr_groups++; perhaps if you inc nr_groups only if there's more than 1 event, you would not need your next patch: perf evlist: Add perf_evlist__recalc_nr_groups something like: if (!list_is_last(list)) data-nr_groups++; Right! Will use it in next version. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [RFC/PATCHSET 00/15] perf report: Add support to accumulate hist periods
Hi Frederic, On Fri, 28 Sep 2012 01:01:48 +0200, Frederic Weisbecker wrote: When Arun was working on this, I asked him to explore if it could make sense to reuse the -b, --branch-stack perf report option. Because after all, this feature is doing about the same than -b except it's using callchains instead of full branch tracing. But callchains are branches. Just a limited subset of all branches taken on excecution. So you can probably reuse some interface and even ground code there. What do you think? Umm.. first of all, I'm not familiar with the branch stack thing. It's intel-specific, right? Also I don't understand what exactly you want here. What kind of interface did you say? Can you elaborate it bit more? And AFAIK branch stack can collect much more branch information than just callstacks. Can we differentiate which is which easily? Is there any limitation on using it? What if callstacks are not sync'ed with branch stacks - is it possible though? But I think it'd be good if the branch stack can be changed to call stack in general. Did you mean this? Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 03/14] perf hists: Separate overhead and baseline columns
On Thu, 27 Sep 2012 13:09:24 +0200, Jiri Olsa wrote: Currently the overhead and baseline columns are handled within single function and the distinction is made by 'baseline hists' pointer passed by 'struct perf_hpp::ptr'. Since hists pointer is now part of each hist_entry, it's possible to locate paired hists pointer directly from the passed struct hist_entry pointer. Also separating those 2 columns makes the code more obvious. Yes, it was thinking about something like this. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org Signed-off-by: Jiri Olsa jo...@redhat.com --- [snip] +static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = baseline_percent(he); + + return percent_color_snprintf(hpp-buf, hpp-size, %5.2f%%, percent); Is it possible to have a baseline value over 100%? I changed 'overhead' colum format from '2 spaces + %5.2f + %' to '1 space + %6.2f + %' for the case. Probably it'd better using it here too for consistency. +} + +static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = baseline_percent(he); + const char *fmt = symbol_conf.field_sep ? %.2f : %5.2f%%; Ditto. Thanks, Namhyung + + return scnprintf(hpp-buf, hpp-size, fmt, percent); +} + -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 06/14] perf tool: Add hpp interface to enable/disable hpp column
On Thu, 27 Sep 2012 13:09:27 +0200, Jiri Olsa wrote: Adding perf_hpp__column_enable function to enable/disable hists column and removing diff command specific stuff 'need_pair and show_displacement' from hpp code. The diff command now enables/disables columns separately according to the user arguments. This will be helpful in future patches where more columns are added into diff output. This is what I wanted to do. :) Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH] perf tool: Fix build for NO_DWARF=1 case
Hi all, On Wed, 3 Oct 2012 12:29:28 +0200, Jiri Olsa wrote: On Tue, Oct 02, 2012 at 06:45:36PM -0300, Arnaldo Carvalho de Melo wrote: Em Tue, Oct 02, 2012 at 03:10:49PM +0200, Jiri Olsa escreveu: On Tue, Oct 02, 2012 at 07:39:23AM -0400, Ben Guthro wrote: Actually - I hadn't noticed these warnings before. After installing libdw-dev - the perf build completed successfully. Perhaps this should be fatal, rather than a warning? attached patch fixies the issue for me. Adding Arnaldo to the loop. [acme@sandy linux]$ make -j8 -C tools/perf/ LIBUNWIND_DIR=/opt/libunwind O=/home/acme/git/build/perf install cc1: warnings being treated as errors arch/x86/util/dwarf-regs.c:72: error: no previous prototype for ‘get_arch_regstr’ make: *** [/home/acme/git/build/perf/arch/x86/util/dwarf-regs.o] Error 1 make: *** Waiting for unfinished jobs make: Leaving directory `/home/git/linux/tools/perf' [acme@sandy linux]$ - Arnaldo ugh.. forgot the way you build perf ;) (also smells like 'automated make test' adept) Anyway, there's Makefile dependency on PERF_HAVE_DWARF_REGS which is defined in arch/x86/Makefile. So, there's only one right place for '-include arch/$(ARCH)/Makefile'. We should think of some other solution, since this seems fragile. I checked your make and simple make with attached patch (only x86_64 arch, and with and without libdw installed). I posted similar patch few days ago and it slipped into acme/perf/core: https://lkml.org/lkml/2012/9/28/194 Can you reproduce it with above change? Anyway, my apologies, sorry for the inconvenience. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/3] perf tools: Check existence of _get_comp_words_by_ref when bash completing
Hi Frederic, On Tue, 2 Oct 2012 17:54:10 +0200, Frederic Weisbecker wrote: On Wed, Oct 03, 2012 at 12:21:32AM +0900, Namhyung Kim wrote: The '_get_comp_words_by_ref' function is available from the bash completion v1.2 so that earlier version emits following warning: $ perf reTAB_get_comp_words_by_ref: command not found Use older '_get_cword' method when the above function doesn't exist. May be only use _get_cword then, if it works everywhere? It'll work but it's deprecated. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH] perf tools: Complete tracepoint event names
From: Namhyung Kim namhyung@lge.com Currently tracepoint events cannot be completed because they contain a colon (:) character. The colon is considered as a word separator when bash completion is done - variable COMP_WORDBREAKS contains colon - so if a word being completed contains a colon it can be a problem. Recent versions of bash completion provide -n switch to _get_comp_words_by_ref and __ltrim_colon_completions functions in order to resolve this issue. Copy the latter in case not exists. Cc: Frederic Weisbecker fweis...@gmail.com Cc: David Ahern dsah...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- This patch is based on my previous completion updates set. tools/perf/bash_completion | 18 -- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/tools/perf/bash_completion b/tools/perf/bash_completion index 5c355ababf80..56e6a12aab59 100644 --- a/tools/perf/bash_completion +++ b/tools/perf/bash_completion @@ -6,6 +6,19 @@ function_exists() return $? } +function_exists __ltrim_colon_completions || +__ltrim_colon_completions() +{ + if [[ $1 == *:* $COMP_WORDBREAKS == *:* ]]; then + # Remove colon-word prefix from COMPREPLY items + local colon_word=${1%${1##*:}} + local i=${#COMPREPLY[*]} + while [[ $((--i)) -ge 0 ]]; do + COMPREPLY[$i]=${COMPREPLY[$i]#$colon_word} + done + fi +} + have perf _perf() { @@ -13,9 +26,9 @@ _perf() COMPREPLY=() if function_exists _get_comp_words_by_ref; then - _get_comp_words_by_ref cur prev + _get_comp_words_by_ref -n : cur prev else - cur=$(_get_cword) + cur=$(_get_cword :) prev=${COMP_WORDS[COMP_CWORD-1]} fi @@ -35,6 +48,7 @@ _perf() elif [[ $prev == -e ${COMP_WORDS[1]} == @(record|stat|top) ]]; then evts=$($cmd list --raw-dump) COMPREPLY=( $( compgen -W '$evts' -- $cur ) ) + __ltrim_colon_completions $cur # List long option names elif [[ $cur == --* ]]; then subcmd=${COMP_WORDS[1]} -- 1.7.11.4 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 14/14] perf diff: Display empty space for non paired samples
On Thu, 27 Sep 2012 13:09:35 +0200, Jiri Olsa wrote: Currently in 'Baseline' and 'Period Base' columns zero values are displayed in case no pair is found for the sample. This might be confusing, using empty space instead. [snip] @@ -246,8 +249,12 @@ static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *h u64 period = pair ? pair-period : 0; const char *fmt = symbol_conf.field_sep ? % PRIu64 : %12 PRIu64; - return scnprintf(hpp-buf, hpp-size, fmt, period); + if (pair) + return scnprintf(hpp-buf, hpp-size, fmt, period); + else + return scnprintf(hpp-buf, hpp-size, ); It seems that it's not needed when -t (field separator) switch is given. Thanks, Namhyung -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 00/20] perf report: Add support for event group view (v3)
Hi, This is my v3 of event group view support. For basic idea and usage example, please see my original post [1]. I rebased the series on top of selected hpp changes from Jiri's diff patchset [2] since it contains cleanups and improves that can be used in this series too. You can also get it via my tree at: git://git.kernel.org/pub/scm/linux/kernel/git/namhyung/linux-perf.git perf/group-v3 Any comments are welcome, thanks, Namhyung v2 - v3: * drop patch 1 since it's merged into acme/perf/core * cherry-pick Jiri's hpp changes * add missing bswap_32 on reading nr_groups (Jiri) * remove perf_evlist__recalc_nr_groups() in favor of list_is_last (Jiri) v1 - v2: * save group relation to header (Jiri) [1] https://lkml.org/lkml/2012/7/24/81 [2] https://lkml.org/lkml/2012/9/27/254 Jiri Olsa (6): perf hists: Add struct hists pointer to struct hist_entry perf diff: Refactor diff displacement possition info perf hists: Separate overhead and baseline columns perf tools: Removing hists pair argument from output path perf tool: Add hpp interface to enable/disable hpp column perf diff: Removing the total_period argument from output code Namhyung Kim (14): perf hists: Introduce struct he_stat perf hists: Move he-stat.nr_events initialization to a template perf hists: Add more helpers for hist entry stat perf tools: Keep group information perf header: Add HEADER_GROUP_DESC feature perf hists: Collapse group hist_entries to a leader perf hists: Maintain total periods of group members in the leader perf report: Make another loop for output resorting perf ui/hist: Add support for event group view perf ui/browser: Add support for event group view perf ui/gtk: Add support for event group view perf report: Bypass non-leader events when event group is enabled perf report: Show group description when event group is enabled perf report: Add --group option tools/perf/builtin-diff.c | 68 ++ tools/perf/builtin-record.c|3 + tools/perf/builtin-report.c| 33 ++- tools/perf/builtin-top.c |2 +- tools/perf/ui/browsers/hists.c | 115 +++--- tools/perf/ui/gtk/browser.c| 74 --- tools/perf/ui/hist.c | 204 +--- tools/perf/ui/setup.c |2 +- tools/perf/ui/stdio/hist.c | 47 - tools/perf/util/evlist.c | 10 +- tools/perf/util/evlist.h |1 + tools/perf/util/evsel.c| 25 + tools/perf/util/evsel.h| 23 + tools/perf/util/header.c | 152 ++ tools/perf/util/header.h |2 + tools/perf/util/hist.c | 195 -- tools/perf/util/hist.h | 12 +-- tools/perf/util/parse-events.c |1 + tools/perf/util/parse-events.h |1 + tools/perf/util/parse-events.y | 10 ++ tools/perf/util/sort.h | 20 ++-- tools/perf/util/symbol.c |4 + tools/perf/util/symbol.h |3 +- 23 files changed, 826 insertions(+), 181 deletions(-) -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 01/20] perf hists: Add struct hists pointer to struct hist_entry
From: Jiri Olsa jo...@redhat.com Adding pointer back to the parent struct hists for struct hists_entry. This will be useful in future for any hist_entry's data computation, that depends on total data of its parent hists. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c |2 ++ tools/perf/util/sort.h |1 + 2 files changed, 3 insertions(+) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 236bc9d98ff2..040f34c79a53 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -325,6 +325,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), .branch_info = bi, + .hists = self, }; return add_hist_entry(self, entry, al, period); @@ -346,6 +347,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, .period = period, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), + .hists = self, }; return add_hist_entry(self, entry, al, period); diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 12d634792de5..eb3959b8e9d9 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h @@ -79,6 +79,7 @@ struct hist_entry { struct rb_rootsorted_chain; }; struct branch_info *branch_info; + struct hists*hists; struct callchain_root callchain[0]; }; -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 02/20] perf diff: Refactor diff displacement possition info
From: Jiri Olsa jo...@redhat.com Moving the position calculation into the diff command, so the position is prepared inside struct hist_entry data and there's no need to compute in the output display path. Removing 'displacement' from struct perf_hpp as it is no longer needed. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 49 --- tools/perf/builtin-report.c |2 +- tools/perf/builtin-top.c|2 +- tools/perf/ui/hist.c|8 --- tools/perf/ui/stdio/hist.c | 17 +++ tools/perf/util/hist.h |4 +--- tools/perf/util/sort.h |2 +- 7 files changed, 44 insertions(+), 40 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 761f4197a9e2..5cb577a3c5b2 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -70,8 +70,8 @@ static struct perf_tool tool = { .ordering_requires_timestamps = true, }; -static void perf_session__insert_hist_entry_by_name(struct rb_root *root, - struct hist_entry *he) +static void insert_hist_entry_by_name(struct rb_root *root, + struct hist_entry *he) { struct rb_node **p = root-rb_node; struct rb_node *parent = NULL; @@ -90,7 +90,7 @@ static void perf_session__insert_hist_entry_by_name(struct rb_root *root, rb_insert_color(he-rb_node, root); } -static void hists__resort_entries(struct hists *self) +static void hists__name_resort(struct hists *self, bool sort) { unsigned long position = 1; struct rb_root tmp = RB_ROOT; @@ -100,12 +100,16 @@ static void hists__resort_entries(struct hists *self) struct hist_entry *n = rb_entry(next, struct hist_entry, rb_node); next = rb_next(n-rb_node); - rb_erase(n-rb_node, self-entries); n-position = position++; - perf_session__insert_hist_entry_by_name(tmp, n); + + if (sort) { + rb_erase(n-rb_node, self-entries); + insert_hist_entry_by_name(tmp, n); + } } - self-entries = tmp; + if (sort) + self-entries = tmp; } static struct hist_entry *hists__find_entry(struct hists *self, @@ -121,7 +125,7 @@ static struct hist_entry *hists__find_entry(struct hists *self, n = n-rb_left; else if (cmp 0) n = n-rb_right; - else + else return iter; } @@ -150,6 +154,24 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel, return NULL; } +static void perf_evlist__resort_hists(struct perf_evlist *evlist, bool name) +{ + struct perf_evsel *evsel; + + list_for_each_entry(evsel, evlist-entries, node) { + struct hists *hists = evsel-hists; + + hists__output_resort(hists); + + /* +* The hists__name_resort only sets possition +* if name is false. +*/ + if (name || ((!name) show_displacement)) + hists__name_resort(hists, name); + } +} + static int __cmd_diff(void) { int ret, i; @@ -176,15 +198,8 @@ static int __cmd_diff(void) evlist_old = older-evlist; evlist_new = newer-evlist; - list_for_each_entry(evsel, evlist_new-entries, node) - hists__output_resort(evsel-hists); - - list_for_each_entry(evsel, evlist_old-entries, node) { - hists__output_resort(evsel-hists); - - if (show_displacement) - hists__resort_entries(evsel-hists); - } + perf_evlist__resort_hists(evlist_old, true); + perf_evlist__resort_hists(evlist_new, false); list_for_each_entry(evsel, evlist_new-entries, node) { struct perf_evsel *evsel_old; @@ -200,7 +215,7 @@ static int __cmd_diff(void) hists__match(evsel_old-hists, evsel-hists); hists__fprintf(evsel-hists, evsel_old-hists, - show_displacement, true, 0, 0, stdout); + true, 0, 0, stdout); } out_delete: diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1da243dfbc3e..6748cac919d1 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, const char
[PATCH 04/20] perf tools: Removing hists pair argument from output path
From: Jiri Olsa jo...@redhat.com The hists pointer is now part of the 'struct hist_entry'. And since the overhead and baseline columns are split now, there's no reason to pass it through the output path. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c |3 +-- tools/perf/builtin-report.c |2 +- tools/perf/builtin-top.c|2 +- tools/perf/ui/hist.c|9 + tools/perf/ui/stdio/hist.c | 10 +++--- tools/perf/util/hist.h |4 ++-- 6 files changed, 13 insertions(+), 17 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 5cb577a3c5b2..413c65a1ba39 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -214,8 +214,7 @@ static int __cmd_diff(void) first = false; hists__match(evsel_old-hists, evsel-hists); - hists__fprintf(evsel-hists, evsel_old-hists, - true, 0, 0, stdout); + hists__fprintf(evsel-hists, true, 0, 0, stdout); } out_delete: diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 6748cac919d1..95e7ea879b8a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -320,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, const char *evname = perf_evsel__name(pos); hists__fprintf_nr_sample_events(hists, evname, stdout); - hists__fprintf(hists, NULL, true, 0, 0, stdout); + hists__fprintf(hists, true, 0, 0, stdout); fprintf(stdout, \n\n); } diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index 6b8c62918f41..dd7ff2b74675 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c @@ -316,7 +316,7 @@ static void perf_top__print_sym_table(struct perf_top *top) hists__output_recalc_col_len(top-sym_evsel-hists, top-winsize.ws_row - 3); putchar('\n'); - hists__fprintf(top-sym_evsel-hists, NULL, false, + hists__fprintf(top-sym_evsel-hists, false, top-winsize.ws_row - 4 - printed, win_width, stdout); } diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 532a60177c32..6b0138e5f332 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -228,16 +228,17 @@ static int hpp__width_delta(struct perf_hpp *hpp __maybe_unused) static int hpp__entry_delta(struct perf_hpp *hpp, struct hist_entry *he) { - struct hists *pair_hists = hpp-ptr; + struct hist_entry *pair = he-pair; + struct hists *pair_hists = pair ? pair-hists : NULL; u64 old_total, new_total; double old_percent = 0, new_percent = 0; double diff; const char *fmt = symbol_conf.field_sep ? %s : %7.7s; char buf[32] = ; - old_total = pair_hists-stats.total_period; - if (old_total 0 he-pair) - old_percent = 100.0 * he-pair-period / old_total; + old_total = pair_hists ? pair_hists-stats.total_period : 0; + if (old_total 0 pair) + old_percent = 100.0 * pair-period / old_total; new_total = hpp-total_period; if (new_total 0) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index 0aa6776caba5..1340c93aa619 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -307,8 +307,7 @@ static size_t hist_entry__callchain_fprintf(struct hist_entry *he, } static int hist_entry__fprintf(struct hist_entry *he, size_t size, - struct hists *hists, struct hists *pair_hists, - u64 total_period, FILE *fp) + struct hists *hists, u64 total_period, FILE *fp) { char bf[512]; int ret; @@ -316,7 +315,6 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, .buf= bf, .size = size, .total_period = total_period, - .ptr= pair_hists, }; bool color = !symbol_conf.field_sep; @@ -335,8 +333,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size, return ret; } -size_t hists__fprintf(struct hists *hists, struct hists *pair, - bool show_header, int max_rows, +size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, int max_cols, FILE *fp) { struct sort_entry *se; @@ -351,7 +348,6 @@ size_t hists__fprintf(struct hists *hists, struct hists *pair
[PATCH 05/20] perf tool: Add hpp interface to enable/disable hpp column
From: Jiri Olsa jo...@redhat.com Adding perf_hpp__column_enable function to enable/disable hists column and removing diff command specific stuff 'need_pair and show_displacement' from hpp code. The diff command now enables/disables columns separately according to the user arguments. This will be helpful in future patches where more columns are added into diff output. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-diff.c | 18 +- tools/perf/builtin-report.c|2 +- tools/perf/ui/browsers/hists.c |2 +- tools/perf/ui/gtk/browser.c|2 +- tools/perf/ui/hist.c | 15 ++- tools/perf/ui/setup.c |2 +- tools/perf/util/hist.h |3 ++- 7 files changed, 29 insertions(+), 15 deletions(-) diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 413c65a1ba39..a0b531c14b97 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c @@ -256,6 +256,21 @@ static const struct option options[] = { OPT_END() }; +static void ui_init(void) +{ + perf_hpp__init(); + + /* No overhead column. */ + perf_hpp__column_enable(PERF_HPP__OVERHEAD, false); + + /* Display baseline/delta/displacement columns. */ + perf_hpp__column_enable(PERF_HPP__BASELINE, true); + perf_hpp__column_enable(PERF_HPP__DELTA, true); + + if (show_displacement) + perf_hpp__column_enable(PERF_HPP__DISPL, true); +} + int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) { sort_order = diff__default_sort_order; @@ -278,7 +293,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix __maybe_unused) if (symbol__init() 0) return -1; - perf_hpp__init(true, show_displacement); + ui_init(); + setup_sorting(diff_usage, options); setup_pager(); diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 95e7ea879b8a..a61725d89d3e 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -691,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) setup_browser(true); else { use_browser = 0; - perf_hpp__init(false, false); + perf_hpp__init(); } setup_sorting(report_usage, options); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index a21f40bebbac..bbd11c2f69db 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -584,7 +584,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us) void hist_browser__init_hpp(void) { - perf_hpp__init(false, false); + perf_hpp__init(); perf_hpp__format[PERF_HPP__OVERHEAD].color = hist_browser__hpp_color_overhead; diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 7ff99ec1d95e..2bc08f6af714 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -73,7 +73,7 @@ HPP__COLOR_FN(overhead_guest_us, period_guest_us) void perf_gtk__init_hpp(void) { - perf_hpp__init(false, false); + perf_hpp__init(); perf_hpp__format[PERF_HPP__OVERHEAD].color = perf_gtk__hpp_color_overhead; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 6b0138e5f332..e8853f7780a3 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -302,7 +302,7 @@ struct perf_hpp_fmt perf_hpp__format[] = { #undef HPP__COLOR_PRINT_FNS #undef HPP__PRINT_FNS -void perf_hpp__init(bool need_pair, bool show_displacement) +void perf_hpp__init(void) { if (symbol_conf.show_cpu_utilization) { perf_hpp__format[PERF_HPP__OVERHEAD_SYS].cond = true; @@ -319,15 +319,12 @@ void perf_hpp__init(bool need_pair, bool show_displacement) if (symbol_conf.show_total_period) perf_hpp__format[PERF_HPP__PERIOD].cond = true; +} - if (need_pair) { - perf_hpp__format[PERF_HPP__OVERHEAD].cond = false; - perf_hpp__format[PERF_HPP__BASELINE].cond = true; - perf_hpp__format[PERF_HPP__DELTA].cond = true; - - if (show_displacement) - perf_hpp__format[PERF_HPP__DISPL].cond = true; - } +void perf_hpp__column_enable(unsigned col, bool enable) +{ + BUG_ON(col = PERF_HPP__MAX_INDEX); + perf_hpp__format[col].cond = enable; } static inline void advance_hpp(struct perf_hpp *hpp, int inc) diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c index
[PATCH 07/20] perf hists: Introduce struct he_stat
From: Namhyung Kim namhyung@lge.com The struct he_stat is for separating out statistics data of a hist entry. It is required for later changes. It's just a mechanical change and should have no functional differences. Cc: Jiri Olsa jo...@redhat.com Cc: Arun Sharma asha...@fb.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/browsers/hists.c |8 +++ tools/perf/ui/gtk/browser.c|2 +- tools/perf/ui/hist.c | 30 +++ tools/perf/ui/stdio/hist.c |2 +- tools/perf/util/hist.c | 52 +--- tools/perf/util/sort.h | 16 - 6 files changed, 59 insertions(+), 51 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index d359795454d0..0568536ecf67 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -570,7 +570,7 @@ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ struct hists *hists = he-hists;\ - double percent = 100.0 * he-_field / hists-stats.total_period;\ + double percent = 100.0 * he-stat._field / hists-stats.total_period; \ *(double *)hpp-ptr = percent; \ return scnprintf(hpp-buf, hpp-size, %6.2f%%, percent); \ } @@ -982,7 +982,7 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, folded_sign = hist_entry__folded(he); hist_entry__sort_snprintf(he, s, sizeof(s), browser-hists); - percent = (he-period * 100.0) / browser-hists-stats.total_period; + percent = (he-stat.period * 100.0) / browser-hists-stats.total_period; if (symbol_conf.use_callchain) printed += fprintf(fp, %c , folded_sign); @@ -990,10 +990,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, printed += fprintf(fp, %5.2f%%, percent); if (symbol_conf.show_nr_samples) - printed += fprintf(fp, %11u, he-nr_events); + printed += fprintf(fp, %11u, he-stat.nr_events); if (symbol_conf.show_total_period) - printed += fprintf(fp, %12 PRIu64, he-period); + printed += fprintf(fp, %12 PRIu64, he-stat.period); printed += fprintf(fp, %s\n, rtrim(s)); diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 3cbb1d622ed2..4125c6284114 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -50,7 +50,7 @@ static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp,\ struct hist_entry *he) \ { \ struct hists *hists = he-hists; \ - double percent = 100.0 * he-_field / hists-stats.total_period; \ + double percent = 100.0 * he-stat._field / hists-stats.total_period; \ const char *markup; \ int ret = 0; \ \ diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 7f043394bef1..f5a1e4f65263 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -19,7 +19,7 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) { struct hists *hists = he-hists; - double percent = 100.0 * he-period / hists-stats.total_period; + double percent = 100.0 * he-stat.period / hists-stats.total_period; return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); } @@ -27,7 +27,7 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) { struct hists *hists = he-hists; - double percent = 100.0 * he-period / hists-stats.total_period; + double percent = 100.0 * he-stat.period / hists-stats.total_period; const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; return scnprintf(hpp-buf, hpp-size, fmt, percent); @@ -48,7 +48,7 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) { struct hists *hists = he-hists; - double percent = 100.0 * he-period_sys / hists-stats.total_period; + double percent = 100.0 * he-stat.period_sys / hists-stats.total_period; return
[PATCH 09/20] perf hists: Add more helpers for hist entry stat
From: Namhyung Kim namhyung@lge.com Add and use he_stat__add_{period,stat} for calculating hist entry's stat. It will be used for accumulated stats later as well. Cc: Jiri Olsa jo...@redhat.com Cc: Arun Sharma asha...@fb.com Cc: Stephane Eranian eran...@google.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c | 26 ++ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 02476cb3167d..277947a669b2 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -151,6 +151,22 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he, } } +static void he_stat__add_period(struct he_stat *he_stat, u64 period) +{ + he_stat-period += period; + he_stat-nr_events += 1; +} + +static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) +{ + dest-period+= src-period; + dest-period_sys+= src-period_sys; + dest-period_us += src-period_us; + dest-period_guest_sys += src-period_guest_sys; + dest-period_guest_us += src-period_guest_us; + dest-nr_events += src-nr_events; +} + static void hist_entry__decay(struct hist_entry *he) { he-stat.period = (he-stat.period * 7) / 8; @@ -270,8 +286,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, cmp = hist_entry__cmp(entry, he); if (!cmp) { - he-stat.period += period; - ++he-stat.nr_events; + he_stat__add_period(he-stat, period); /* If the map of an existing hist_entry has * become out-of-date due to an exec() or @@ -418,12 +433,7 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, cmp = hist_entry__collapse(iter, he); if (!cmp) { - iter-stat.period += he-stat.period; - iter-stat.period_sys += he-stat.period_sys; - iter-stat.period_us+= he-stat.period_us; - iter-stat.period_guest_sys += he-stat.period_guest_sys; - iter-stat.period_guest_us += he-stat.period_guest_us; - iter-stat.nr_events+= he-stat.nr_events; + he_stat__add_stat(iter-stat, he-stat); if (symbol_conf.use_callchain) { callchain_cursor_reset(callchain_cursor); -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 17/20] perf ui/gtk: Add support for event group view
From: Namhyung Kim namhyung@lge.com Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Cc: Pekka Enberg penb...@kernel.org Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/gtk/browser.c | 60 +-- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 4125c6284114..b2c8b8e69e4d 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -45,26 +45,57 @@ static const char *perf_gtk__get_percent_color(double percent) return NULL; } +static int perf_gtk__percent_color_snprintf(char *buf, size_t size, + u64 period, u64 total_period) +{ + int ret = 0; + const char *markup; + double percent = 100.0 * period / total_period; + + markup = perf_gtk__get_percent_color(percent); + if (markup) + ret += scnprintf(buf, size, markup); + + ret += scnprintf(buf + ret, size - ret, %6.2f%%, percent); + + if (markup) + ret += scnprintf(buf + ret, size - ret, /span); + + return ret; +} + +static int perf_gtk__hpp_color_overhead(struct perf_hpp *hpp, + struct hist_entry *he) +{ + int ret; + struct hists *hists = he-hists; + + ret = perf_gtk__percent_color_snprintf(hpp-buf, hpp-size, + he-stat.period, hists-stats.total_period); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hists); + + for (i = 0; i evsel-nr_members; i++) { + ret += scnprintf(hpp-buf + ret, hpp-size - ret, ); + ret += perf_gtk__percent_color_snprintf(hpp-buf + ret, + hpp-size - ret, + he-group_stats[i].period, + hists-group_stats[i].total_period); + } + } + return ret; +} + #define HPP__COLOR_FN(_name, _field) \ static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ - struct hists *hists = he-hists; \ - double percent = 100.0 * he-stat._field / hists-stats.total_period; \ - const char *markup; \ - int ret = 0; \ - \ - markup = perf_gtk__get_percent_color(percent); \ - if (markup) \ - ret += scnprintf(hpp-buf, hpp-size, %s, markup); \ - ret += scnprintf(hpp-buf + ret, hpp-size - ret, %6.2f%%, percent); \ - if (markup) \ - ret += scnprintf(hpp-buf + ret, hpp-size - ret, /span); \ - \ - return ret; \ + return perf_gtk__percent_color_snprintf(hpp-buf, hpp-size, \ + he-stat._field, he-hists-stats.total_period); \ } -HPP__COLOR_FN(overhead, period) HPP__COLOR_FN(overhead_sys, period_sys) HPP__COLOR_FN(overhead_us, period_us) HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) @@ -103,6 +134,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) struct perf_hpp hpp = { .buf= s, .size = sizeof(s), + .ptr= hists_2_evsel(hists), }; nr_cols = 0; -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 19/20] perf report: Show group description when event group is enabled
From: Namhyung Kim namhyung@lge.com When using event group viewer, it's better to show the group description rather than the leader information alone. If a leader did not contain any member, it's a non-group event. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Cc: Pekka Enberg penb...@kernel.org Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c| 18 ++ tools/perf/ui/browsers/hists.c | 31 +++ tools/perf/ui/gtk/browser.c| 14 +++--- tools/perf/util/evsel.c| 25 + tools/perf/util/evsel.h|8 5 files changed, 93 insertions(+), 3 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index ba5cfb40818d..e9c9687e021a 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -299,6 +299,24 @@ static size_t hists__fprintf_nr_sample_events(struct hists *self, char unit; unsigned long nr_samples = self-stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = self-stats.total_period; + struct perf_evsel *evsel = hists_2_evsel(self); + char buf[512]; + size_t size = sizeof(buf); + + if (symbol_conf.event_group evsel-nr_members) { + int i; + struct events_stats *stats; + + perf_evsel__group_desc(evsel, buf, size); + evname = buf; + + for (i = 0; i evsel-nr_members; i++) { + stats = self-group_stats[i]; + + nr_samples += stats-nr_events[PERF_RECORD_SAMPLE]; + nr_events += stats-total_period; + } + } nr_samples = convert_unit(nr_samples, unit); ret = fprintf(fp, # Samples: %lu%c, nr_samples, unit); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 43eb90969799..e81773bd272e 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1123,6 +1123,24 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size, const struct thread *thread = hists-thread_filter; unsigned long nr_samples = hists-stats.nr_events[PERF_RECORD_SAMPLE]; u64 nr_events = hists-stats.total_period; + struct perf_evsel *evsel = hists_2_evsel(hists); + char buf[512]; + size_t buflen = sizeof(buf); + + if (symbol_conf.event_group evsel-nr_members) { + int i; + struct events_stats *stats; + + perf_evsel__group_desc(evsel, buf, buflen); + ev_name = buf; + + for (i = 0; i evsel-nr_members; i++) { + stats = hists-group_stats[i]; + + nr_samples += stats-nr_events[PERF_RECORD_SAMPLE]; + nr_events += stats-total_period; + } + } nr_samples = convert_unit(nr_samples, unit); printed = scnprintf(bf, size, @@ -1469,6 +1487,19 @@ static void perf_evsel_menu__write(struct ui_browser *browser, ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED : HE_COLORSET_NORMAL); + if (symbol_conf.event_group evsel-nr_members) { + int i; + struct events_stats *stats; + + ev_name = perf_evsel__group_name(evsel); + + for (i = 0; i evsel-nr_members; i++) { + stats = evsel-hists.group_stats[i]; + + nr_events += stats-nr_events[PERF_RECORD_SAMPLE]; + } + } + nr_events = convert_unit(nr_events, unit); printed = scnprintf(bf, sizeof(bf), %lu%c%s%s, nr_events, unit, unit == ' ' ? : , ev_name); diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index ae6b941ef3d4..2c0e3e95dbca 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -305,10 +305,18 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, const char *evname = perf_evsel__name(pos); GtkWidget *scrolled_window; GtkWidget *tab_label; + char buf[512]; + size_t size = sizeof(buf); - if (symbol_conf.event_group - !perf_evsel__is_group_leader(pos)) - continue; + if (symbol_conf.event_group) { + if (!perf_evsel__is_group_leader(pos)) + continue; + + if (pos-nr_members) { + perf_evsel__group_desc(pos, buf, size); + evname = buf; + } + } scrolled_window = gtk_scrolled_window_new(NULL, NULL); diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index
[PATCH 10/20] perf tools: Keep group information
From: Namhyung Kim namhyung@lge.com Add a few of group-related field in struct perf_{evlist,evsel} so that the group information in a evlist can be known easily. It only counts groups which have more than 1 members since leader-only groups are treated as non-group events. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/evlist.c | 10 -- tools/perf/util/evlist.h |1 + tools/perf/util/evsel.h| 10 ++ tools/perf/util/parse-events.c |1 + tools/perf/util/parse-events.h |1 + tools/perf/util/parse-events.y | 10 ++ 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c index ae89686102f4..ac9730c12884 100644 --- a/tools/perf/util/evlist.c +++ b/tools/perf/util/evlist.c @@ -111,20 +111,26 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist, void __perf_evlist__set_leader(struct list_head *list) { struct perf_evsel *evsel, *leader; + int count = 0; leader = list_entry(list-next, struct perf_evsel, node); leader-leader = NULL; list_for_each_entry(evsel, list, node) { - if (evsel != leader) + if (evsel != leader) { evsel-leader = leader; + evsel-group_idx = count++; + } } + leader-nr_members = count; } void perf_evlist__set_leader(struct perf_evlist *evlist) { - if (evlist-nr_entries) + if (evlist-nr_entries) { + evlist-nr_groups = evlist-nr_entries 1 ? 1 : 0; __perf_evlist__set_leader(evlist-entries); + } } int perf_evlist__add_default(struct perf_evlist *evlist) diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h index 3f1fb66be022..a3a4906d4a4e 100644 --- a/tools/perf/util/evlist.h +++ b/tools/perf/util/evlist.h @@ -21,6 +21,7 @@ struct perf_evlist { struct list_head entries; struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; int nr_entries; + int nr_groups; int nr_fds; int nr_mmaps; int mmap_len; diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 3ead0d59c03d..407c8e84fee3 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -74,6 +74,10 @@ struct perf_evsel { int exclude_GH; struct perf_evsel *leader; char*group_name; + union { + int nr_members; + int group_idx; + }; }; struct cpu_map; @@ -225,4 +229,10 @@ static inline struct perf_evsel *perf_evsel__next(struct perf_evsel *evsel) { return list_entry(evsel-node.next, struct perf_evsel, node); } + +/* Treat a non-group event as a leader */ +static inline bool perf_evsel__is_group_leader(struct perf_evsel *evsel) +{ + return evsel-leader == NULL; +} #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index aed38e4b9dfa..364e518b0fce 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -816,6 +816,7 @@ int parse_events(struct perf_evlist *evlist, const char *str, if (!ret) { int entries = data.idx - evlist-nr_entries; perf_evlist__splice_list_tail(evlist, data.list, entries); + evlist-nr_groups += data.nr_groups; return 0; } diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index c356e443448d..f6b0254afe17 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -65,6 +65,7 @@ struct parse_events__term { struct parse_events_data__events { struct list_head list; int idx; + int nr_groups; }; struct parse_events_data__terms { diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index cd88209e3c58..a7810dd0938a 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -122,6 +122,11 @@ group_def: PE_NAME '{' events '}' { struct list_head *list = $3; + struct parse_events_data__events *data = _data; + + /* Count groups only have more than 1 members */ + if (!list_is_last(list-next, list)) + data-nr_groups++; parse_events__set_leader($1, list); $$ = list; @@ -130,6 +135,11 @@ PE_NAME '{' events '}' '{' events '}' { struct list_head *list = $2; + struct parse_events_data__events *data = _data; + + /* Count groups only have more than 1 members */ + if (!list_is_last(list-next, list)) + data-nr_groups++; parse_events__set_leader(NULL, list); $$ = list; -- 1.7.9.2 -- To unsubscribe from this list: send the line
[PATCH 12/20] perf hists: Collapse group hist_entries to a leader
From: Namhyung Kim namhyung@lge.com To support viewing an event group together, collapse all of members in the group to the leader's tree. The entries in the leaders' tree will have group_stats to store those information. This patch introduced an additional field 'event_group' in symbol_conf to distinguish whether event grouping is enabled or not. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/evsel.h |5 +++ tools/perf/util/hist.c | 108 ++ tools/perf/util/sort.h |1 + tools/perf/util/symbol.c |4 ++ tools/perf/util/symbol.h |3 +- 5 files changed, 112 insertions(+), 9 deletions(-) diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h index 407c8e84fee3..039c67297388 100644 --- a/tools/perf/util/evsel.h +++ b/tools/perf/util/evsel.h @@ -235,4 +235,9 @@ static inline bool perf_evsel__is_group_leader(struct perf_evsel *evsel) { return evsel-leader == NULL; } + +static inline struct perf_evsel *hists_2_evsel(struct hists *hists) +{ + return container_of(hists, struct perf_evsel, hists); +} #endif /* __PERF_EVSEL_H */ diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 277947a669b2..95415716c708 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -4,6 +4,7 @@ #include hist.h #include session.h #include sort.h +#include evsel.h #include math.h static bool hists__filter_entry_by_dso(struct hists *hists, @@ -167,6 +168,32 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) dest-nr_events += src-nr_events; } +static void hist_entry__add_group_stat(struct hist_entry *he_dest, + struct he_stat *src, + struct perf_evsel *evsel) +{ + struct perf_evsel *leader = evsel-leader; + + if (perf_evsel__is_group_leader(evsel)) + leader = evsel; + + if (leader-nr_members !he_dest-group_stats) { + /* +* A group whose nr_members equals to 0 is a leader-only group. +* So no need to allocate group_stats. +*/ + he_dest-group_stats = calloc(leader-nr_members, + sizeof(struct he_stat)); + if (!he_dest-group_stats) + return; + } + + if (perf_evsel__is_group_leader(evsel)) + he_stat__add_stat(he_dest-stat, src); + else + he_stat__add_stat(he_dest-group_stats[evsel-group_idx], src); +} + static void hist_entry__decay(struct hist_entry *he) { he-stat.period = (he-stat.period * 7) / 8; @@ -417,13 +444,14 @@ void hist_entry__free(struct hist_entry *he) * collapse the histogram */ -static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, +static bool hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, struct hist_entry *he) { struct rb_node **p = root-rb_node; struct rb_node *parent = NULL; struct hist_entry *iter; + struct perf_evsel *evsel = hists_2_evsel(hists); int64_t cmp; while (*p != NULL) { @@ -433,7 +461,10 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, cmp = hist_entry__collapse(iter, he); if (!cmp) { - he_stat__add_stat(iter-stat, he-stat); + if (symbol_conf.event_group) + hist_entry__add_group_stat(iter, he-stat, evsel); + else + he_stat__add_stat(iter-stat, he-stat); if (symbol_conf.use_callchain) { callchain_cursor_reset(callchain_cursor); @@ -451,6 +482,19 @@ static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused, p = (*p)-rb_right; } + if (symbol_conf.event_group) { + /* +* 'he' is not found in the leader's tree. +* Insert it to the tree and setup stats properly. +*/ + hist_entry__add_group_stat(he, he-stat, evsel); + + if (!perf_evsel__is_group_leader(evsel)) { + he-hists = evsel-leader-hists; + memset(he-stat, 0, sizeof(he-stat)); + } + } + rb_link_node(he-rb_node_in, parent, p); rb_insert_color(he-rb_node_in, root); return true; @@ -481,6 +525,7 @@ static void hists__apply_filters(struct hists *hists, struct hist_entry *he) static void __hists__collapse_resort(struct hists *hists, bool threaded) { struct rb_root *root; + struct rb_root *dest; struct
[PATCH 14/20] perf report: Make another loop for output resorting
From: Namhyung Kim namhyung@lge.com Now the event grouping viewing requires collapsing all members in a group to the leader. Thus hists__output_resort should be called after collapsing all entries in evlist. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c |5 + 1 file changed, 5 insertions(+) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index a61725d89d3e..b7e250d63892 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -416,6 +416,11 @@ static int __cmd_report(struct perf_report *rep) hists-symbol_filter_str = rep-symbol_filter_str; hists__collapse_resort(hists); + } + + list_for_each_entry(pos, session-evlist-entries, node) { + struct hists *hists = pos-hists; + hists__output_resort(hists); nr_samples += hists-stats.nr_events[PERF_RECORD_SAMPLE]; } -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 16/20] perf ui/browser: Add support for event group view
From: Namhyung Kim namhyung@lge.com Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/browsers/hists.c | 33 +++-- tools/perf/ui/hist.c |5 - 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index 0568536ecf67..df0ddeeeb860 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -565,6 +565,34 @@ static int hist_browser__show_callchain(struct hist_browser *browser, return row - first_row; } +static int hist_browser__hpp_color_overhead(struct perf_hpp *hpp, + struct hist_entry *he) +{ + int ret; + struct hists *hists = he-hists; + double percent = 100.0 * he-stat.period / hists-stats.total_period; + + /* the leader determines color */ + *(double *) hpp-ptr = percent; + + ret = scnprintf(hpp-buf, hpp-size, %6.2f%%, percent); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hists); + + for (i = 0; i evsel-nr_members; i++) { + u64 period = he-group_stats[i].period; + u64 total = hists-group_stats[i].total_period; + + percent = 100.0 * period / total; + ret += scnprintf(hpp-buf + ret, hpp-size - ret, + %6.2f%%, percent); + } + } + return ret; +} + #define HPP__COLOR_FN(_name, _field) \ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ @@ -575,7 +603,6 @@ static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ return scnprintf(hpp-buf, hpp-size, %6.2f%%, percent); \ } -HPP__COLOR_FN(overhead, period) HPP__COLOR_FN(overhead_sys, period_sys) HPP__COLOR_FN(overhead_us, period_us) HPP__COLOR_FN(overhead_guest_sys, period_guest_sys) @@ -610,6 +637,7 @@ static int hist_browser__show_entry(struct hist_browser *browser, char folded_sign = ' '; bool current_entry = ui_browser__is_current_entry(browser-b, row); off_t row_offset = entry-row_offset; + bool first = true; if (current_entry) { browser-he_selection = entry; @@ -633,10 +661,11 @@ static int hist_browser__show_entry(struct hist_browser *browser, if (!perf_hpp__format[i].cond) continue; - if (i) { + if (!first) { slsmg_printf( ); width -= 2; } + first = false; if (perf_hpp__format[i].color) { hpp.ptr = percent; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index ad4efb772796..624f3d08937f 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -462,6 +462,9 @@ unsigned int hists__sort_list_width(struct hists *hists) { struct sort_entry *se; int i, ret = 0; + struct perf_hpp dummy_hpp = { + .ptr= hists_2_evsel(hists), + }; for (i = 0; i PERF_HPP__MAX_INDEX; i++) { if (!perf_hpp__format[i].cond) @@ -469,7 +472,7 @@ unsigned int hists__sort_list_width(struct hists *hists) if (i) ret += 2; - ret += perf_hpp__format[i].width(NULL); + ret += perf_hpp__format[i].width(dummy_hpp); } list_for_each_entry(se, hist_entry__sort_list, list) -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 20/20] perf report: Add --group option
From: Namhyung Kim namhyung@lge.com Add --group option to enable event grouping. When enabled, all the group members information will be shown together with the leader. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e9c9687e021a..9ed3a64315da 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -664,6 +664,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) 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_BOOLEAN(0, group, symbol_conf.event_group, + Show event group information together), OPT_CALLBACK_NOOPT('b', branch-stack, sort__branch_mode, , use branch records for histogram filling, parse_branch_mode), OPT_STRING(0, objdump, objdump_path, path, -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 18/20] perf report: Bypass non-leader events when event group is enabled
From: Namhyung Kim namhyung@lge.com Since we have all necessary information in the leader events and other members don't, bypass members. Member events will be shown along with the leaders if event group is enabled. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Cc: Pekka Enberg penb...@kernel.org Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-report.c|4 tools/perf/ui/browsers/hists.c | 39 +-- tools/perf/ui/gtk/browser.c|4 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b7e250d63892..ba5cfb40818d 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -319,6 +319,10 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist, struct hists *hists = pos-hists; const char *evname = perf_evsel__name(pos); + if (symbol_conf.event_group + !perf_evsel__is_group_leader(pos)) + continue; + hists__fprintf_nr_sample_events(hists, evname, stdout); hists__fprintf(hists, true, 0, 0, stdout); fprintf(stdout, \n\n); diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index df0ddeeeb860..43eb90969799 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -1578,8 +1578,19 @@ out: return key; } +static bool filter_group_entries(struct ui_browser *self __maybe_unused, +void *entry) +{ + struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); + + if (symbol_conf.event_group !perf_evsel__is_group_leader(evsel)) + return true; + + return false; +} + static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, - const char *help, + int nr_entries, const char *help, void(*timer)(void *arg), void *arg, int delay_secs) { @@ -1590,7 +1601,8 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, .refresh= ui_browser__list_head_refresh, .seek = ui_browser__list_head_seek, .write = perf_evsel_menu__write, - .nr_entries = evlist-nr_entries, + .filter = filter_group_entries, + .nr_entries = nr_entries, .priv = evlist, }, }; @@ -1605,7 +1617,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist, menu.b.width = line_len; } - return perf_evsel_menu__run(menu, evlist-nr_entries, help, timer, + return perf_evsel_menu__run(menu, nr_entries, help, timer, arg, delay_secs); } @@ -1613,15 +1625,30 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help, void(*timer)(void *arg), void *arg, int delay_secs) { - if (evlist-nr_entries == 1) { + int nr_entries = evlist-nr_entries; + +single_entry: + if (nr_entries == 1) { struct perf_evsel *first = list_entry(evlist-entries.next, struct perf_evsel, node); const char *ev_name = perf_evsel__name(first); - return perf_evsel__hists_browse(first, evlist-nr_entries, help, + return perf_evsel__hists_browse(first, nr_entries, help, ev_name, false, timer, arg, delay_secs); } - return __perf_evlist__tui_browse_hists(evlist, help, + if (symbol_conf.event_group) { + struct perf_evsel *pos; + + nr_entries = 0; + list_for_each_entry(pos, evlist-entries, node) + if (perf_evsel__is_group_leader(pos)) + nr_entries++; + + if (nr_entries == 1) + goto single_entry; + } + + return __perf_evlist__tui_browse_hists(evlist, nr_entries, help, timer, arg, delay_secs); } diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index b2c8b8e69e4d..ae6b941ef3d4 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -306,6 +306,10 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist, GtkWidget *scrolled_window; GtkWidget *tab_label; + if (symbol_conf.event_group
[PATCH 15/20] perf ui/hist: Add support for event group view
From: Namhyung Kim namhyung@lge.com Show group members' overhead also when showing the leader's if event group is enabled. At this time, only implemented overhead part in order to ease review and other parts can be added later once this patch settled down. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/hist.c | 66 tools/perf/ui/stdio/hist.c |2 ++ 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index f5a1e4f65263..ad4efb772796 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -3,34 +3,90 @@ #include ../util/hist.h #include ../util/util.h #include ../util/sort.h +#include ../util/evsel.h /* hist period print (hpp) functions */ static int hpp__header_overhead(struct perf_hpp *hpp) { - return scnprintf(hpp-buf, hpp-size, Overhead); + int len = 8; + + if (symbol_conf.event_group) { + struct perf_evsel *evsel = hpp-ptr; + + BUG_ON(!perf_evsel__is_group_leader(evsel)); + + len += evsel-nr_members * 8; + } + return scnprintf(hpp-buf, hpp-size, %*s, len, Overhead); } -static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) +static int hpp__width_overhead(struct perf_hpp *hpp) { - return 8; + int len = 8; + + if (symbol_conf.event_group) { + struct perf_evsel *evsel = hpp-ptr; + + len += evsel-nr_members * 8; + } + return len; } static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) { + int ret; struct hists *hists = he-hists; double percent = 100.0 * he-stat.period / hists-stats.total_period; - return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); + ret = percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hists); + + for (i = 0; i evsel-nr_members; i++) { + u64 period = he-group_stats[i].period; + u64 total = hists-group_stats[i].total_period; + + percent = 100.0 * period / total; + ret += percent_color_snprintf(hpp-buf + ret, + hpp-size - ret, + %6.2f%%, percent); + } + + } + return ret; } static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) { + int ret; struct hists *hists = he-hists; double percent = 100.0 * he-stat.period / hists-stats.total_period; const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; - return scnprintf(hpp-buf, hpp-size, fmt, percent); + ret = scnprintf(hpp-buf, hpp-size, fmt, percent); + + if (symbol_conf.event_group) { + int i; + struct perf_evsel *evsel = hists_2_evsel(hists); + + for (i = 0; i evsel-nr_members; i++) { + u64 period = he-group_stats[i].period; + u64 total = hists-group_stats[i].total_period; + + if (symbol_conf.field_sep) { + ret += scnprintf(hpp-buf + ret, +hpp-size - ret, ); + } + percent = 100.0 * period / total; + ret += scnprintf(hpp-buf + ret, hpp-size - ret, +fmt, percent); + } + + } + return ret; } static int hpp__header_overhead_sys(struct perf_hpp *hpp) diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c index fbd4e32d0743..1d4f1ddc8bf8 100644 --- a/tools/perf/ui/stdio/hist.c +++ b/tools/perf/ui/stdio/hist.c @@ -3,6 +3,7 @@ #include ../../util/util.h #include ../../util/hist.h #include ../../util/sort.h +#include ../../util/evsel.h static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) @@ -346,6 +347,7 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, struct perf_hpp dummy_hpp = { .buf= bf, .size = sizeof(bf), + .ptr= hists_2_evsel(hists), }; bool first = true; -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 13/20] perf hists: Maintain total periods of group members in the leader
From: Namhyung Kim namhyung@lge.com Like group_stats in hist_entry, total periods information also need to be known to the leader. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c | 25 + tools/perf/util/hist.h |1 + 2 files changed, 26 insertions(+) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 95415716c708..48488057c3da 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -194,6 +194,28 @@ static void hist_entry__add_group_stat(struct hist_entry *he_dest, he_stat__add_stat(he_dest-group_stats[evsel-group_idx], src); } +static void hists__add_group_stat(struct hists *hists) +{ + struct perf_evsel *evsel = hists_2_evsel(hists); + struct perf_evsel *leader = evsel-leader; + struct hists *leader_hists; + + if (perf_evsel__is_group_leader(evsel)) + return; + + leader_hists = leader-hists; + + if (!leader_hists-group_stats) { + leader_hists-group_stats = calloc(leader-nr_members, + sizeof(struct events_stats)); + if (!leader_hists-group_stats) + return; + } + + memcpy(leader_hists-group_stats[evsel-group_idx], + hists-stats, sizeof(struct events_stats)); +} + static void hist_entry__decay(struct hist_entry *he) { he-stat.period = (he-stat.period * 7) / 8; @@ -561,6 +583,9 @@ static void __hists__collapse_resort(struct hists *hists, bool threaded) hists__apply_filters(hists, n); } } + + if (symbol_conf.event_group) + hists__add_group_stat(hists); } void hists__collapse_resort(struct hists *hists) diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 66cb31fe81d2..e150cf86b94a 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h @@ -66,6 +66,7 @@ struct hists { const char *symbol_filter_str; pthread_mutex_t lock; struct events_stats stats; + struct events_stats *group_stats; u64 event_stream; u16 col_len[HISTC_NR_COLS]; }; -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 11/20] perf header: Add HEADER_GROUP_DESC feature
From: Namhyung Kim namhyung@lge.com Save group relationship information so that it can be restored when perf report is running. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/builtin-record.c |3 + tools/perf/util/header.c| 152 +++ tools/perf/util/header.h|2 + 3 files changed, 157 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8c029fe2e22c..7940f0dd3db9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -558,6 +558,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) goto out_delete_session; } + if (!evsel_list-nr_groups) + perf_header__clear_feat(session-header, HEADER_GROUP_DESC); + /* * perf_session__delete(session) will be called at perf_record__exit() */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 7daad237dea5..caceb33d8d1b 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1072,6 +1072,41 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, } /* + * File format: + * + * struct group_descs { + * u32 nr_groups; + * struct group_desc { + * charname[]; + * u32 leader_idx; + * u32 nr_members; + * }[nr_groups]; + * }; + */ +static int write_group_desc(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist) +{ + u32 nr_groups = evlist-nr_groups; + struct perf_evsel *evsel; + + do_write(fd, nr_groups, sizeof(nr_groups)); + + list_for_each_entry(evsel, evlist-entries, node) { + if (perf_evsel__is_group_leader(evsel) + evsel-nr_members 0) { + const char *name = evsel-group_name ?: {anon_group}; + u32 leader_idx = evsel-idx; + u32 nr_members = evsel-nr_members; + + do_write_string(fd, name); + do_write(fd, leader_idx, sizeof(leader_idx)); + do_write(fd, nr_members, sizeof(nr_members)); + } + } + return 0; +} + +/* * default get_cpuid(): nothing gets recorded * actual implementation must be in arch/$(ARCH)/util/header.c */ @@ -1432,6 +1467,31 @@ error: fprintf(fp, # pmu mappings: unable to read\n); } +static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, +FILE *fp) +{ + struct perf_session *session; + struct perf_evsel *evsel; + u32 nr = 0; + + session = container_of(ph, struct perf_session, header); + + list_for_each_entry(evsel, session-evlist-entries, node) { + if (perf_evsel__is_group_leader(evsel) + evsel-nr_members 0) { + fprintf(fp, # group: %s{%s, evsel-group_name ?: , + perf_evsel__name(evsel)); + + nr = evsel-nr_members; + } else if (nr) { + fprintf(fp, ,%s, perf_evsel__name(evsel)); + + if (--nr == 0) + fprintf(fp, }\n); + } + } +} + static int __event_process_build_id(struct build_id_event *bev, char *filename, struct perf_session *session) @@ -1946,6 +2006,97 @@ error: return -1; } +static int process_group_desc(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int fd, + void *data __maybe_unused) +{ + size_t ret = -1; + u32 i, nr, nr_groups; + struct perf_session *session; + struct perf_evsel *evsel, *leader; + struct group_desc { + char *name; + u32 leader_idx; + u32 nr_members; + } *desc; + + ret = read(fd, nr_groups, sizeof(nr_groups)); + if (ret != sizeof(nr_groups)) + return -1; + + if (ph-needs_swap) + nr_groups = bswap_32(nr_groups); + + ph-env.nr_groups = nr_groups; + if (!nr_groups) { + pr_debug(group desc not available\n); + return 0; + } + + desc = calloc(nr_groups, sizeof(*desc)); + if (!desc) + return -1; + + for (i = 0; i nr_groups; i++) { + desc[i].name = do_read_string(fd, ph); + if (!desc[i].name) + goto out_free; + + ret = read(fd, desc[i].leader_idx, sizeof(u32)); + if (ret != sizeof(u32)) + goto out_free; + + ret = read(fd, desc[i].nr_members, sizeof(u32
[PATCH 06/20] perf diff: Removing the total_period argument from output code
From: Jiri Olsa jo...@redhat.com The total_period is available in struct hists data via the 'struct hist_entry::hists' pointer. There's no need to carry it through the output code path. Removing 'struct perf_hpp::total_period' pointer, because it's no longer needed. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/browsers/hists.c |4 ++-- tools/perf/ui/gtk/browser.c|4 ++-- tools/perf/ui/hist.c | 37 ++--- tools/perf/ui/stdio/hist.c | 15 +-- tools/perf/util/hist.h |1 - 5 files changed, 35 insertions(+), 26 deletions(-) diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c index bbd11c2f69db..d359795454d0 100644 --- a/tools/perf/ui/browsers/hists.c +++ b/tools/perf/ui/browsers/hists.c @@ -569,7 +569,8 @@ static int hist_browser__show_callchain(struct hist_browser *browser, static int hist_browser__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ - double percent = 100.0 * he-_field / hpp-total_period;\ + struct hists *hists = he-hists;\ + double percent = 100.0 * he-_field / hists-stats.total_period;\ *(double *)hpp-ptr = percent; \ return scnprintf(hpp-buf, hpp-size, %6.2f%%, percent); \ } @@ -624,7 +625,6 @@ static int hist_browser__show_entry(struct hist_browser *browser, struct perf_hpp hpp = { .buf= s, .size = sizeof(s), - .total_period = browser-hists-stats.total_period, }; ui_browser__gotorc(browser-b, row, 0); diff --git a/tools/perf/ui/gtk/browser.c b/tools/perf/ui/gtk/browser.c index 2bc08f6af714..3cbb1d622ed2 100644 --- a/tools/perf/ui/gtk/browser.c +++ b/tools/perf/ui/gtk/browser.c @@ -49,7 +49,8 @@ static const char *perf_gtk__get_percent_color(double percent) static int perf_gtk__hpp_color_ ## _name(struct perf_hpp *hpp, \ struct hist_entry *he) \ { \ - double percent = 100.0 * he-_field / hpp-total_period; \ + struct hists *hists = he-hists; \ + double percent = 100.0 * he-_field / hists-stats.total_period; \ const char *markup; \ int ret = 0; \ \ @@ -102,7 +103,6 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists) struct perf_hpp hpp = { .buf= s, .size = sizeof(s), - .total_period = hists-stats.total_period, }; nr_cols = 0; diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index e8853f7780a3..7f043394bef1 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -18,14 +18,16 @@ static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) { - double percent = 100.0 * he-period / hpp-total_period; + struct hists *hists = he-hists; + double percent = 100.0 * he-period / hists-stats.total_period; return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); } static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) { - double percent = 100.0 * he-period / hpp-total_period; + struct hists *hists = he-hists; + double percent = 100.0 * he-period / hists-stats.total_period; const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; return scnprintf(hpp-buf, hpp-size, fmt, percent); @@ -45,13 +47,16 @@ static int hpp__width_overhead_sys(struct perf_hpp *hpp __maybe_unused) static int hpp__color_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he) { - double percent = 100.0 * he-period_sys / hpp-total_period; + struct hists *hists = he-hists; + double percent = 100.0 * he-period_sys / hists-stats.total_period; + return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); } static int hpp__entry_overhead_sys(struct perf_hpp *hpp, struct hist_entry *he
[PATCH 08/20] perf hists: Move he-stat.nr_events initialization to a template
From: Namhyung Kim namhyung@lge.com Since it is set to 1 for a new hist entry, no need to set to separately. Move it to a template entry. Cc: Jiri Olsa jo...@redhat.com Cc: Arun Sharma asha...@fb.com Cc: Stephane Eranian eran...@google.com Cc: Frederic Weisbecker fweis...@gmail.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/util/hist.c |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index 3197f3f50018..02476cb3167d 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c @@ -223,7 +223,7 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) if (he != NULL) { *he = *template; - he-stat.nr_events = 1; + if (he-ms.map) he-ms.map-referenced = true; if (symbol_conf.use_callchain) @@ -323,6 +323,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, .level = al-level, .stat = { .period = period, + .nr_events = 1, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), @@ -348,6 +349,7 @@ struct hist_entry *__hists__add_entry(struct hists *self, .level = al-level, .stat = { .period = period, + .nr_events = 1, }, .parent = sym_parent, .filtered = symbol__parent_filter(sym_parent), -- 1.7.9.2 -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 03/20] perf hists: Separate overhead and baseline columns
From: Jiri Olsa jo...@redhat.com Currently the overhead and baseline columns are handled within single function and the distinction is made by 'baseline hists' pointer passed by 'struct perf_hpp::ptr'. Since hists pointer is now part of each hist_entry, it's possible to locate paired hists pointer directly from the passed struct hist_entry pointer. Also separating those 2 columns makes the code more obvious. Cc: Arnaldo Carvalho de Melo a...@ghostprotocols.net Cc: Peter Zijlstra a.p.zijls...@chello.nl Cc: Ingo Molnar mi...@elte.hu Cc: Paul Mackerras pau...@samba.org Cc: Corey Ashford cjash...@linux.vnet.ibm.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Namhyung Kim namhy...@kernel.org Signed-off-by: Jiri Olsa jo...@redhat.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- tools/perf/ui/hist.c | 74 tools/perf/ui/stdio/hist.c | 11 +-- tools/perf/util/hist.h |1 + 3 files changed, 58 insertions(+), 28 deletions(-) diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 55b9ca8f084c..532a60177c32 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c @@ -8,9 +8,7 @@ /* hist period print (hpp) functions */ static int hpp__header_overhead(struct perf_hpp *hpp) { - const char *fmt = hpp-ptr ? Baseline : Overhead; - - return scnprintf(hpp-buf, hpp-size, fmt); + return scnprintf(hpp-buf, hpp-size, Overhead); } static int hpp__width_overhead(struct perf_hpp *hpp __maybe_unused) @@ -22,17 +20,6 @@ static int hpp__color_overhead(struct perf_hpp *hpp, struct hist_entry *he) { double percent = 100.0 * he-period / hpp-total_period; - if (hpp-ptr) { - struct hists *old_hists = hpp-ptr; - u64 total_period = old_hists-stats.total_period; - u64 base_period = he-pair ? he-pair-period : 0; - - if (total_period) - percent = 100.0 * base_period / total_period; - else - percent = 0.0; - } - return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); } @@ -41,17 +28,6 @@ static int hpp__entry_overhead(struct perf_hpp *hpp, struct hist_entry *he) double percent = 100.0 * he-period / hpp-total_period; const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; - if (hpp-ptr) { - struct hists *old_hists = hpp-ptr; - u64 total_period = old_hists-stats.total_period; - u64 base_period = he-pair ? he-pair-period : 0; - - if (total_period) - percent = 100.0 * base_period / total_period; - else - percent = 0.0; - } - return scnprintf(hpp-buf, hpp-size, fmt, percent); } @@ -159,6 +135,47 @@ static int hpp__entry_overhead_guest_us(struct perf_hpp *hpp, return scnprintf(hpp-buf, hpp-size, fmt, percent); } +static int hpp__header_baseline(struct perf_hpp *hpp) +{ + return scnprintf(hpp-buf, hpp-size, Baseline); +} + +static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused) +{ + return 8; +} + +static double baseline_percent(struct hist_entry *he) +{ + struct hist_entry *pair = he-pair; + struct hists *pair_hists = pair ? pair-hists : NULL; + double percent = 0.0; + + if (pair) { + u64 total_period = pair_hists-stats.total_period; + u64 base_period = pair-period; + + percent = 100.0 * base_period / total_period; + } + + return percent; +} + +static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = baseline_percent(he); + + return percent_color_snprintf(hpp-buf, hpp-size, %6.2f%%, percent); +} + +static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) +{ + double percent = baseline_percent(he); + const char *fmt = symbol_conf.field_sep ? %.2f : %6.2f%%; + + return scnprintf(hpp-buf, hpp-size, fmt, percent); +} + static int hpp__header_samples(struct perf_hpp *hpp) { const char *fmt = symbol_conf.field_sep ? %s : %11s; @@ -269,6 +286,7 @@ static int hpp__entry_displ(struct perf_hpp *hpp, .entry = hpp__entry_ ## _name struct perf_hpp_fmt perf_hpp__format[] = { + { .cond = false, HPP__COLOR_PRINT_FNS(baseline) }, { .cond = true, HPP__COLOR_PRINT_FNS(overhead) }, { .cond = false, HPP__COLOR_PRINT_FNS(overhead_sys) }, { .cond = false, HPP__COLOR_PRINT_FNS(overhead_us) }, @@ -302,6 +320,8 @@ void perf_hpp__init(bool need_pair, bool show_displacement) perf_hpp__format[PERF_HPP__PERIOD].cond = true; if (need_pair) { + perf_hpp__format[PERF_HPP__OVERHEAD].cond = false; + perf_hpp__format[PERF_HPP__BASELINE].cond = true; perf_hpp__format[PERF_HPP__DELTA].cond = true
[PATCH UPDATED 11/20] perf header: Add HEADER_GROUP_DESC feature
From: Namhyung Kim namhyung@lge.com Save group relationship information so that it can be restored when perf report is running. Cc: Jiri Olsa jo...@redhat.com Cc: Stephane Eranian eran...@google.com Signed-off-by: Namhyung Kim namhy...@kernel.org --- Initialize leader to NULL in order to avoid 'may be used uninitialized' warning from gcc (gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1)) tools/perf/builtin-record.c |3 + tools/perf/util/header.c| 152 +++ tools/perf/util/header.h|2 + 3 files changed, 157 insertions(+) diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 8c029fe2e22c..7940f0dd3db9 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c @@ -558,6 +558,9 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) goto out_delete_session; } + if (!evsel_list-nr_groups) + perf_header__clear_feat(session-header, HEADER_GROUP_DESC); + /* * perf_session__delete(session) will be called at perf_record__exit() */ diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 7daad237dea5..8969c20986c2 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -1072,6 +1072,41 @@ static int write_pmu_mappings(int fd, struct perf_header *h __maybe_unused, } /* + * File format: + * + * struct group_descs { + * u32 nr_groups; + * struct group_desc { + * charname[]; + * u32 leader_idx; + * u32 nr_members; + * }[nr_groups]; + * }; + */ +static int write_group_desc(int fd, struct perf_header *h __maybe_unused, + struct perf_evlist *evlist) +{ + u32 nr_groups = evlist-nr_groups; + struct perf_evsel *evsel; + + do_write(fd, nr_groups, sizeof(nr_groups)); + + list_for_each_entry(evsel, evlist-entries, node) { + if (perf_evsel__is_group_leader(evsel) + evsel-nr_members 0) { + const char *name = evsel-group_name ?: {anon_group}; + u32 leader_idx = evsel-idx; + u32 nr_members = evsel-nr_members; + + do_write_string(fd, name); + do_write(fd, leader_idx, sizeof(leader_idx)); + do_write(fd, nr_members, sizeof(nr_members)); + } + } + return 0; +} + +/* * default get_cpuid(): nothing gets recorded * actual implementation must be in arch/$(ARCH)/util/header.c */ @@ -1432,6 +1467,31 @@ error: fprintf(fp, # pmu mappings: unable to read\n); } +static void print_group_desc(struct perf_header *ph, int fd __maybe_unused, +FILE *fp) +{ + struct perf_session *session; + struct perf_evsel *evsel; + u32 nr = 0; + + session = container_of(ph, struct perf_session, header); + + list_for_each_entry(evsel, session-evlist-entries, node) { + if (perf_evsel__is_group_leader(evsel) + evsel-nr_members 0) { + fprintf(fp, # group: %s{%s, evsel-group_name ?: , + perf_evsel__name(evsel)); + + nr = evsel-nr_members; + } else if (nr) { + fprintf(fp, ,%s, perf_evsel__name(evsel)); + + if (--nr == 0) + fprintf(fp, }\n); + } + } +} + static int __event_process_build_id(struct build_id_event *bev, char *filename, struct perf_session *session) @@ -1946,6 +2006,97 @@ error: return -1; } +static int process_group_desc(struct perf_file_section *section __maybe_unused, + struct perf_header *ph, int fd, + void *data __maybe_unused) +{ + size_t ret = -1; + u32 i, nr, nr_groups; + struct perf_session *session; + struct perf_evsel *evsel, *leader = NULL; + struct group_desc { + char *name; + u32 leader_idx; + u32 nr_members; + } *desc; + + ret = read(fd, nr_groups, sizeof(nr_groups)); + if (ret != sizeof(nr_groups)) + return -1; + + if (ph-needs_swap) + nr_groups = bswap_32(nr_groups); + + ph-env.nr_groups = nr_groups; + if (!nr_groups) { + pr_debug(group desc not available\n); + return 0; + } + + desc = calloc(nr_groups, sizeof(*desc)); + if (!desc) + return -1; + + for (i = 0; i nr_groups; i++) { + desc[i].name = do_read_string(fd, ph); + if (!desc[i].name) + goto out_free; + + ret = read(fd, desc[i].leader_idx, sizeof(u32)); + if (ret