perf record: add meta-data support for pipe-mode
PATCH 1/1 perf record: add meta-data support for pipe-mode
This patch adds the meta-data header support for perf record when used in pipe mode: perf record -o -
Up until now, meta-data was only available when perf record was used in "regular" mode, i.e., generating a perf.data file. For users depending on pipe mode, neither host or event header information were gathered. This patch addresses this limitation.
The difficulty in pipe mode is that information needs to be written sequentially to the pipe. Meta data headers are usually generated (and also expected) at the beginning of the file (or piped output). To solve this problem, we introduce new synthetic record types, one for each meta-data type. The approach is similar to what is *ALREADY* used for BUILD_ID and TRACING_DATA.
We have modified util/header.c such that the same routines are used to generate and read the meta-data information regardless of pipe-mode vs. regular mode. To make this work, we added a new struct called feat_fd which encapsulates all the information necessary to read or write meta-data information to a file/pipe or from a file/pipe.
With this patch, it is possible to get:
$ perf record -o - noploop 5 | perf inject -b | perf report -i -
# ========
# captured on: Mon Sep 24 18:16:08 2012
# ========
#
# hostname : quad
# os release : 3.6.0-rc6
# perf version : 3.6.0-rc7
# arch : x86_64
# nrcpus online : 4
# nrcpus avail : 4
# cpudesc : Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz
# cpuid : GenuineIntel,6,15,11
# total memory : 8092412 kB
# cmdline : /usr/bin/perf record -o - noploop 5
# ...
# CPU_TOPOLOGY info available, use -I to display
# pmu mappings: cpu = 4, software = 1, tracepoint = 2, breakpoint = 5
noploop for 5 seconds
[ perf record: Woken up 4 times to write data ]
[ perf record: Captured and wrote 0.773 MB - (~33771 samples) ]
# Samples: 20K of event 'cycles'
# Event count (approx.): 11873977966
#
# Overhead Command Shared Object Symbol
# ........ ....... ................. ..........................................
#
98.89% noploop noploop [.] noploop
0.14% noploop [kernel.kallsyms] [k] lock_acquire ---
tools/perf/builtin-annotate.c +5 -0
@@ -247,6 +247,11 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) .mmap = perf_event__process_mmap, .comm = perf_event__process_comm, .fork = perf_event__process_task, + .attr = perf_event__process_attr, + .event_type = perf_event__process_event_type, + .tracing_data = perf_event__process_tracing_data, + .build_id = perf_event__process_build_id, + .feature = perf_event__process_feature, .ordered_samples = true, .ordering_requires_timestamps = true, },
tools/perf/builtin-inject.c +1 -0
@@ -222,6 +222,7 @@ struct perf_tool perf_inject = { .event_type = perf_event__repipe_event_type_synth, .tracing_data = perf_event__repipe_tracing_data_synth, .build_id = perf_event__repipe_op2_synth, + .feature = perf_event__repipe_op2_synth, };extern volatile int session_done;
tools/perf/builtin-record.c +7 -0
@@ -590,6 +590,13 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) }if (opts->pipe_output) { + err =perf_event__synthesize_features (tool, session, evsel_list, + process_synthesized_event); +if (err <0 ) { +pr_err ("Couldn't synthesize features.\n" ); +return err; + } + err =perf_event__synthesize_attrs (tool, session, process_synthesized_event);if (err <0 ) {
tools/perf/builtin-report.c +4 -3
@@ -43,7 +43,6 @@ struct perf_report {bool force, use_tui, use_gtk, use_stdio;bool hide_unresolved;bool dont_use_callchains; -bool show_full_info;bool show_threads;bool inverted_callchain;struct perf_read_values show_threads_values;
@@ -359,7 +358,8 @@ static int __cmd_report(struct perf_report *rep) }if (use_browser <=0 ) -perf_session__fprintf_info (session, stdout, rep->show_full_info); +perf_session__fprintf_info (session, stdout, + rep->tool.show_full_info);if (rep->show_threads)perf_read_values_init (&rep->show_threads_values);
@@ -564,6 +564,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) .event_type = perf_event__process_event_type, .tracing_data = perf_event__process_tracing_data, .build_id = perf_event__process_build_id, + .feature = perf_event__process_feature, .ordered_samples = true, .ordering_requires_timestamps = true, },
@@ -627,7 +628,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) "Look for files with symbols relative to this directory"),OPT_STRING ('C' ,"cpu" , &report.cpu_list,"cpu" ,"list of cpus to profile" ), -OPT_BOOLEAN ('I' ,"show-info" , &report.show_full_info, +OPT_BOOLEAN ('I' ,"show-info" , &report.tool.show_full_info,"Display extended information about perf.data file" ),OPT_BOOLEAN (0 ,"source" , &symbol_conf.annotate_src, "Interleave source code with assembly code (default)"),
tools/perf/util/event.c +13 -0
@@ -23,6 +23,19 @@ static const char *perf_event__names[] = { [PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA", [PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID", [PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND", + [PERF_RECORD_HEADER_HOSTNAME] = "HOSTNAME", + [PERF_RECORD_HEADER_OSRELEASE] = "OSRELEASE", + [PERF_RECORD_HEADER_VERSION] = "VERSION", + [PERF_RECORD_HEADER_ARCH] = "ARCH", + [PERF_RECORD_HEADER_NRCPUS] = "NRCPUS", + [PERF_RECORD_HEADER_CPUDESC] = "CPUDESC", + [PERF_RECORD_HEADER_CPUID] = "CPUID", + [PERF_RECORD_HEADER_TOTAL_MEM] = "TOTAL_MEM", + [PERF_RECORD_HEADER_CMDLINE] = "CMDLINE", + [PERF_RECORD_HEADER_EVENT_DESC] = "EVENT_DESC", + [PERF_RECORD_HEADER_CPU_TOPOLOGY] = "CPU_TOPOLOGY", + [PERF_RECORD_HEADER_NUMA_TOPOLOGY] = "NUMA_TOPOLOGY", + [PERF_RECORD_HEADER_PMU_MAPPINGS] = "PMU_MAPPINGS", };const char *perf_event__name (unsigned int id)
tools/perf/util/event.h +19 -0
@@ -112,6 +112,19 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_HEADER_TRACING_DATA =66 ,PERF_RECORD_HEADER_BUILD_ID =67 ,PERF_RECORD_FINISHED_ROUND =68 , +PERF_RECORD_HEADER_HOSTNAME =69 , +PERF_RECORD_HEADER_OSRELEASE =70 , +PERF_RECORD_HEADER_VERSION =71 , +PERF_RECORD_HEADER_ARCH =72 , +PERF_RECORD_HEADER_NRCPUS =73 , +PERF_RECORD_HEADER_CPUDESC =74 , +PERF_RECORD_HEADER_CPUID =75 , +PERF_RECORD_HEADER_TOTAL_MEM =76 , +PERF_RECORD_HEADER_CMDLINE =77 , +PERF_RECORD_HEADER_EVENT_DESC =78 , +PERF_RECORD_HEADER_CPU_TOPOLOGY =79 , +PERF_RECORD_HEADER_NUMA_TOPOLOGY =80 , +PERF_RECORD_HEADER_PMU_MAPPINGS =81 ,PERF_RECORD_HEADER_MAX };
@@ -138,6 +151,11 @@ struct tracing_data_event {u32 size; }; +struct feature_event { +struct perf_event_header header; +char data[];/* size bytes of raw data specific to the feature */ +}; +union perf_event {struct perf_event_header header;struct ip_event ip;
@@ -151,6 +169,7 @@ union perf_event {struct event_type_event event_type;struct tracing_data_event tracing_data;struct build_id_event build_id; +struct feature_event feat; };void perf_event__print_totals (void );
tools/perf/util/header.c +402 -178
1,189 lines not on this page · raw message
tools/perf/util/header.h +9 -0
@@ -99,6 +99,15 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir, const char *name, bool is_kallsyms, bool is_vdso);int build_id_cache__remove_s (const char *sbuild_id,const char *debugdir); +int perf_event__synthesize_features (struct perf_tool *tool, +struct perf_session *session, +struct perf_evlist *evlist, +perf_event__handler_t process); + +int perf_event__process_feature (struct perf_tool *tool, +union perf_event *event, +struct perf_session *session); +int perf_event__synthesize_attr (struct perf_tool *tool,struct perf_event_attr *attr,u32 ids,u64 *id,perf_event__handler_t process);
tools/perf/util/session.c +15 -2
@@ -453,6 +453,14 @@ static int process_event_type_stub(struct perf_tool *tool __maybe_unused,return 0 ; } +static int process_feature_stub (struct perf_tool *tool__maybe_unused , +union perf_event *event__maybe_unused , +struct perf_session *session__maybe_unused ) +{ +dump_printf (": unhandled!\n" ); +return 0 ; +} +static int process_finished_round (struct perf_tool *tool,union perf_event *event,struct perf_session *session);
@@ -491,6 +499,8 @@ static void perf_tool__fill_defaults(struct perf_tool *tool)else tool->finished_round = process_finished_round_stub; } +if (tool->feature ==NULL ) + tool->feature = process_feature_stub; }void mem_bswap_32 (void *src,int byte_size)
@@ -672,8 +682,8 @@ static perf_event__swap_op perf_event__swap_ops[] = { [PERF_RECORD_SAMPLE] = perf_event__all64_swap, [PERF_RECORD_HEADER_ATTR] = perf_event__hdr_attr_swap, [PERF_RECORD_HEADER_EVENT_TYPE] = perf_event__event_type_swap, - [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, [PERF_RECORD_HEADER_BUILD_ID] = NULL, + [PERF_RECORD_HEADER_TRACING_DATA] = perf_event__tracing_data_swap, [PERF_RECORD_HEADER_MAX] = NULL, };
@@ -1138,6 +1148,8 @@ static int perf_session__process_user_event(struct perf_session *session, unionreturn tool->build_id (tool, event, session);case PERF_RECORD_FINISHED_ROUND :return tool->finished_round (tool, event, session); + case PERF_RECORD_HEADER_HOSTNAME ... PERF_RECORD_HEADER_PMU_MAPPINGS: +return tool->feature (tool, event, session);default :return -EINVAL ; }
@@ -1709,8 +1721,9 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,fprintf (fp,"# ========\n" );fprintf (fp,"# captured on: %s" ,ctime (&st.st_ctime)); -perf_header__fprintf_info (session, fp, full);fprintf (fp,"# ========\n#\n" ); +if (!session->fd_pipe) +perf_header__fprintf_info (session, fp, full); }
tools/perf/util/tool.h +3 -1
@@ -42,9 +42,11 @@ struct perf_tool {event_synth_op tracing_data;event_simple_op event_type;event_op2 finished_round, - build_id; + build_id, + feature;bool ordered_samples;bool ordering_requires_timestamps; + bool show_full_info; };#endif /* __PERF_TOOL_H */
I like the idea, but can't checkout the patch - does not apply to Arnaldo's latest perf/core branch. mind rebasing?
David
Quoted 3 lines · David Ahern
I like the idea, but can't checkout the patch - does not apply to Arnaldo's latest perf/core branch. mind rebasing?
It's against tip-master.
Quoted 1 line
David