perf script: Add script orientation output support for monitored events
PATCH 1/1 perf script: Add script orientation output support for monitored events
Introduce a new option to print trace output to files named by the monitored events and update perf-script documentation accordingly.
Shown below is output of perf script command with the newly introduced option.
$perf record -e cycles -e context-switches -ag -- sleep 10 $perf script -O
$ls /
cycles.stacks context-switches.stacks
Without the orientation option, drawing flamegraphs for different events is really hard. You can only monitor one event at a time for perf record. Using this option, we can get the trace output files named by the monitored events, and could draw flamegraphs according to the event's name.
Signed-off-by Wind Yu <[email protected]>
Cc Peter Zijlstra <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Arnaldo Carvalho de Melo <[email protected]>
Cc Alexander Shishkin <[email protected]>
--- tools/perf/builtin-script.c | 469 +++++++++++++++++++++++++------------------- tools/perf/util/tool.h | 1 + 2 files changed, 269 insertions(+), 201 deletions(-)
tools/perf/builtin-script.c +268 -201
@@ -57,6 +57,7 @@ static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);static struct perf_stat_config stat_config;static int max_blocks; +static FILE *orientation_file;unsigned int scripting_max_stack =PERF_MAX_STACK_DEPTH ;
@@ -485,8 +486,8 @@ static int perf_session__check_output_opt(struct perf_session *session)return 0 ; } -static void print_sample_iregs (struct perf_sample *sample, -struct perf_event_attr *attr) +static void fprint_sample_iregs (struct perf_sample *sample, +struct perf_event_attr *attr,FILE *fp) {struct regs_dump *regs = &sample->intr_regs;uint64_t mask = attr->sample_regs_intr;
@@ -497,13 +498,13 @@ static void print_sample_iregs(struct perf_sample *sample,for_each_set_bit (r, (unsigned long *) &mask,sizeof (mask) *8 ) {u64 val = regs->regs[i++]; -printf ("%5s:0x%" PRIx64" " ,perf_reg_name (r), val); +fprintf (fp,"%5s:0x%" PRIx64" " ,perf_reg_name (r), val); } } -static void print_sample_start (struct perf_sample *sample, +static void fprint_sample_start (struct perf_sample *sample,struct thread *thread, -struct perf_evsel *evsel) +struct perf_evsel *evsel,FILE *fp) {struct perf_event_attr *attr = &evsel->attr;unsigned long secs;
@@ -511,25 +512,25 @@ static void print_sample_start(struct perf_sample *sample,if (PRINT_FIELD (COMM )) {if (latency_format) -printf ("%8.8s " ,thread__comm_str (thread)); +fprintf (fp,"%8.8s " ,thread__comm_str (thread));else if (PRINT_FIELD (IP ) && symbol_conf.use_callchain) -printf ("%s " ,thread__comm_str (thread)); +fprintf (fp,"%s " ,thread__comm_str (thread));else -printf ("%16s " ,thread__comm_str (thread)); +fprintf (fp,"%16s " ,thread__comm_str (thread)); }if (PRINT_FIELD (PID ) &&PRINT_FIELD (TID )) -printf ("%5d/%-5d " , sample->pid, sample->tid); +fprintf (fp,"%5d/%-5d " , sample->pid, sample->tid);else if (PRINT_FIELD (PID )) -printf ("%5d " , sample->pid); +fprintf (fp,"%5d " , sample->pid);else if (PRINT_FIELD (TID )) -printf ("%5d " , sample->tid); +fprintf (fp,"%5d " , sample->tid);if (PRINT_FIELD (CPU )) {if (latency_format) -printf ("%3d " , sample->cpu); +fprintf (fp,"%3d " , sample->cpu);else -printf ("[%03d] " , sample->cpu); +fprintf (fp,"[%03d] " , sample->cpu); }if (PRINT_FIELD (TIME )) {
@@ -538,11 +539,11 @@ static void print_sample_start(struct perf_sample *sample, nsecs -= secs *NSEC_PER_SEC ;if (nanosecs) -printf ("%5lu.%09llu: " , secs, nsecs); +fprintf (fp,"%5lu.%09llu: " , secs, nsecs);else {char sample_time[32 ];timestamp__scnprintf_usec (sample->time, sample_time,sizeof (sample_time)); -printf ("%12s: " , sample_time); +fprintf (fp,"%12s: " , sample_time); } } }
@@ -556,9 +557,10 @@ static void print_sample_start(struct perf_sample *sample,return br->flags.predicted ?'P' :'M' ; } -static void print_sample_brstack (struct perf_sample *sample, +static void fprint_sample_brstack (struct perf_sample *sample,struct thread *thread, -struct perf_event_attr *attr) +struct perf_event_attr *attr, +FILE *fp) {struct branch_stack *br = sample->branch_stack;struct addr_location alf, alt;
@@ -578,21 +580,21 @@ static void print_sample_brstack(struct perf_sample *sample,thread__find_addr_map (thread, sample->cpumode,MAP__FUNCTION , to, &alt); } -printf ("0x%" PRIx64, from); +fprintf (fp,"0x%" PRIx64, from);if (PRINT_FIELD (DSO )) { -printf ("(" ); -map__fprintf_dsoname (alf.map, stdout); -printf (")" ); +fprintf (fp,"(" ); +map__fprintf_dsoname (alf.map, fp); +fprintf (fp,")" ); } -printf ("/0x%" PRIx64, to); +fprintf (fp,"/0x%" PRIx64, to);if (PRINT_FIELD (DSO )) { -printf ("(" ); -map__fprintf_dsoname (alt.map, stdout); -printf (")" ); +fprintf (fp,"(" ); +map__fprintf_dsoname (alt.map, fp); +fprintf (fp,")" ); } - printf("/%c/%c/%c/%d ", + fprintf(fp, "/%c/%c/%c/%d ", mispred_str( br->entries + i), br->entries[i].flags.in_tx? 'X' : '-', br->entries[i].flags.abort? 'A' : '-',
@@ -600,9 +602,10 @@ static void print_sample_brstack(struct perf_sample *sample, } } -static void print_sample_brstacksym (struct perf_sample *sample, +static void fprint_sample_brstacksym (struct perf_sample *sample,struct thread *thread, -struct perf_event_attr *attr) +struct perf_event_attr *attr, +FILE *fp) {struct branch_stack *br = sample->branch_stack;struct addr_location alf, alt;
@@ -626,20 +629,20 @@ static void print_sample_brstacksym(struct perf_sample *sample,if (alt.map) alt.sym =map__find_symbol (alt.map, alt.addr); -symbol__fprintf_symname_offs (alf.sym, &alf, stdout); +symbol__fprintf_symname_offs (alf.sym, &alf, fp);if (PRINT_FIELD (DSO )) { -printf ("(" ); -map__fprintf_dsoname (alf.map, stdout); -printf (")" ); +fprintf (fp,"(" ); +map__fprintf_dsoname (alf.map, fp); +fprintf (fp,")" ); } -putchar ('/' ); -symbol__fprintf_symname_offs (alt.sym, &alt, stdout); +fputc ('/' , fp); +symbol__fprintf_symname_offs (alt.sym, &alt, fp);if (PRINT_FIELD (DSO )) { -printf ("(" ); -map__fprintf_dsoname (alt.map, stdout); -printf (")" ); +fprintf (fp,"(" ); +map__fprintf_dsoname (alt.map, fp); +fprintf (fp,")" ); } - printf("/%c/%c/%c/%d ", + fprintf(fp, "/%c/%c/%c/%d ", mispred_str( br->entries + i), br->entries[i].flags.in_tx? 'X' : '-', br->entries[i].flags.abort? 'A' : '-',
@@ -647,9 +650,10 @@ static void print_sample_brstacksym(struct perf_sample *sample, } } -static void print_sample_brstackoff (struct perf_sample *sample, +static void fprint_sample_brstackoff (struct perf_sample *sample,struct thread *thread, -struct perf_event_attr *attr) +struct perf_event_attr *attr, +FILE *fp) {struct branch_stack *br = sample->branch_stack;struct addr_location alf, alt;
@@ -673,19 +677,19 @@ static void print_sample_brstackoff(struct perf_sample *sample,if (alt.map && !alt.map->dso->adjust_symbols) to =map__map_ip (alt.map, to); -printf ("0x%" PRIx64, from); +fprintf (fp,"0x%" PRIx64, from);if (PRINT_FIELD (DSO )) { -printf ("(" ); -map__fprintf_dsoname (alf.map, stdout); -printf (")" ); +fprintf (fp,"(" ); +map__fprintf_dsoname (alf.map, fp); +fprintf (fp,")" ); } -printf ("/0x%" PRIx64, to); +fprintf (fp,"/0x%" PRIx64, to);if (PRINT_FIELD (DSO )) { -printf ("(" ); -map__fprintf_dsoname (alt.map, stdout); -printf (")" ); +fprintf (fp,"(" ); +map__fprintf_dsoname (alt.map, fp); +fprintf (fp,")" ); } - printf("/%c/%c/%c/%d ", + fprintf(fp, "/%c/%c/%c/%d ", mispred_str(br->entries + i), br->entries[i].flags.in_tx ? 'X' : '-', br->entries[i].flags.abort ? 'A' : '-',
@@ -756,11 +760,11 @@ static int grab_bb(u8 *buffer, u64 start, u64 end,return len; } -static void print_jump (uint64_t ip,struct branch_entry *en, +static void fprint_jump (uint64_t ip,struct branch_entry *en,struct perf_insn *x,u8 *inbuf,int len, -int insn) +int insn,FILE *fp) { - printf("\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", + fprintf(fp, "\t%016" PRIx64 "\t%-30s\t#%s%s%s%s", ip, dump_insn(x, ip, inbuf, len, NULL), en->flags.predicted ? " PRED" : "",
@@ -768,16 +772,16 @@ static void print_jump(uint64_t ip, struct branch_entry *en, en->flags.in_tx ?" INTX" :"" , en->flags.abort ? " ABORT" : "");if (en->flags.cycles) { -printf (" %d cycles" , en->flags.cycles); +fprintf (fp," %d cycles" , en->flags.cycles);if (insn) -printf (" %.2f IPC" , (float )insn / en->flags.cycles); +fprintf (fp," %.2f IPC" , (float )insn / en->flags.cycles); } -putchar ('\n' ); +fputc ('\n' , fp); } -static void print_ip_sym (struct thread *thread,u8 cpumode,int cpu, +static void fprint_ip_sym (struct thread *thread,u8 cpumode,int cpu,uint64_t addr,struct symbol **lastsym, -struct perf_event_attr *attr) +struct perf_event_attr *attr,FILE *fp) {struct addr_location al;int off;
@@ -803,20 +807,21 @@ static void print_ip_sym(struct thread *thread, u8 cpumode, int cpu, off = al.addr - al.sym->start; else off = al.addr - al.map->start - al.sym->start; -printf ("\t%s" , al.sym->name); +fprintf (fp,"\t%s" , al.sym->name);if (off) -printf ("%+d" , off); -putchar (':' ); +fprintf (fp,"%+d" , off); +fputc (':' , fp);if (PRINT_FIELD (SRCLINE )) -map__fprintf_srcline (al.map, al.addr,"\t" , stdout); -putchar ('\n' ); +map__fprintf_srcline (al.map, al.addr,"\t" , fp); +fputc ('\n' , fp); *lastsym = al.sym; } -static void print_sample_brstackinsn (struct perf_sample *sample, +static void fprint_sample_brstackinsn (struct perf_sample *sample,struct thread *thread,struct perf_event_attr *attr, -struct machine *machine) +struct machine *machine, +FILE *fp) {struct branch_stack *br = sample->branch_stack;u64 start, end;
@@ -835,23 +840,23 @@ static void print_sample_brstackinsn(struct perf_sample *sample, x.thread = thread; x.cpu = sample->cpu; -putchar ('\n' ); +fputc ('\n' , fp);/* Handle first from jump, of which we don't know the entry. */ len =grab_bb (buffer, br->entries[nr-1 ].from, br->entries[nr-1 ].from, machine, thread, &x.is64bit, &x.cpumode, false);if (len >0 ) { -print_ip_sym (thread, x.cpumode, x.cpu, - br->entries[nr -1 ].from, &lastsym, attr); -print_jump (br->entries[nr -1 ].from, &br->entries[nr -1 ], - &x, buffer, len,0 ); +fprint_ip_sym (thread, x.cpumode, x.cpu, + br->entries[nr -1 ].from, &lastsym, attr, fp); +fprint_jump (br->entries[nr -1 ].from, &br->entries[nr -1 ], + &x, buffer, len,0 , fp); }/* Print all blocks */ for (i = nr -2 ; i >=0 ; i--) {if (br->entries[i].from || br->entries[i].to) -pr_debug ("%d: %" PRIx64"-%" PRIx64"\n" , i, +fprintf (fp,"%d: %" PRIx64"-%" PRIx64"\n" , i, br->entries[i].from, br->entries[i].to); start = br->entries[i +1 ].to;
@@ -861,7 +866,7 @@ static void print_sample_brstackinsn(struct perf_sample *sample,/* Patch up missing kernel transfers due to ring filters */ if (len == -ENXIO && i >0 ) { end = br->entries[--i].from; -pr_debug ("\tpatching up to %" PRIx64"-%" PRIx64"\n" , start, end); +fprintf (fp,"\tpatching up to %" PRIx64"-%" PRIx64"\n" , start, end); len =grab_bb (buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, false); }if (len <=0 )
@@ -871,13 +876,12 @@ static void print_sample_brstackinsn(struct perf_sample *sample,for (off =0 ;; off += ilen) {uint64_t ip = start + off; -print_ip_sym (thread, x.cpumode, x.cpu, ip, &lastsym, attr); +fprint_ip_sym (thread, x.cpumode, x.cpu, ip, &lastsym, attr, fp);if (ip == end) { -print_jump (ip, &br->entries[i], &x, buffer + off, len - off, insn); +fprint_jump (ip, &br->entries[i], &x, buffer + off, len - off, insn, fp);break ; }else { -printf ("\t%016" PRIx64"\t%s\n" , ip, -dump_insn (&x, ip, buffer + off, len - off, &ilen)); +fprintf (fp,"\t%016" PRIx64"\t%s\n" , ip,dump_insn (&x, ip, buffer + off, len - off, &ilen));if (ilen ==0 )break ; insn++;
@@ -900,7 +904,7 @@ static void print_sample_brstackinsn(struct perf_sample *sample, start = br->entries[0 ].to; end = sample->ip; len =grab_bb (buffer, start, end, machine, thread, &x.is64bit, &x.cpumode, true); -print_ip_sym (thread, x.cpumode, x.cpu, start, &lastsym, attr); +fprint_ip_sym (thread, x.cpumode, x.cpu, start, &lastsym, attr, fp);if (len <=0 ) {/* Print at least last IP if basic block did not work */ len = grab_bb(buffer, sample->ip, sample->ip,
@@ -908,25 +912,25 @@ static void print_sample_brstackinsn(struct perf_sample *sample,if (len <=0 )return ; -printf ("\t%016" PRIx64"\t%s\n" , sample->ip, +fprintf (fp,"\t%016" PRIx64"\t%s\n" , sample->ip,dump_insn (&x, sample->ip, buffer, len,NULL ));return ; }for (off =0 ; off <= end - start; off += ilen) { -printf ("\t%016" PRIx64"\t%s\n" , start + off, +fprintf (fp,"\t%016" PRIx64"\t%s\n" , start + off,dump_insn (&x, start + off, buffer + off, len - off, &ilen));if (ilen ==0 )break ; } } -static void print_sample_addr (struct perf_sample *sample, +static void fprint_sample_addr (struct perf_sample *sample,struct thread *thread, -struct perf_event_attr *attr) +struct perf_event_attr *attr,FILE *fp) {struct addr_location al; -printf ("%16" PRIx64, sample->addr); +fprintf (fp,"%16" PRIx64, sample->addr);if (!sample_addr_correlates_sym (attr))return ;
@@ -934,24 +938,25 @@ static void print_sample_addr(struct perf_sample *sample,thread__resolve (thread, &al, sample);if (PRINT_FIELD (SYM )) { -printf (" " ); +fprintf (fp," " );if (PRINT_FIELD (SYMOFFSET )) -symbol__fprintf_symname_offs (al.sym, &al, stdout); +symbol__fprintf_symname_offs (al.sym, &al, fp);else -symbol__fprintf_symname (al.sym, stdout); +symbol__fprintf_symname (al.sym, fp); }if (PRINT_FIELD (DSO )) { -printf (" (" ); -map__fprintf_dsoname (al.map, stdout); -printf (")" ); +fprintf (fp," (" ); +map__fprintf_dsoname (al.map, fp); +fprintf (fp,")" ); } } -static void print_sample_callindent (struct perf_sample *sample, +static void fprint_sample_callindent (struct perf_sample *sample,struct perf_evsel *evsel,struct thread *thread, -struct addr_location *al) +struct addr_location *al, +FILE *fp) {struct perf_event_attr *attr = &evsel->attr;size_t depth =thread_stack__depth (thread);
@@ -986,9 +991,9 @@ static void print_sample_callindent(struct perf_sample *sample, }if (name) - len =printf ("%*s%s" , (int )depth *4 ,"" , name); + len =fprintf (fp,"%*s%s" , (int )depth *4 ,"" , name);else if (ip) - len =printf ("%*s%16" PRIx64, (int )depth *4 ,"" , ip); + len =fprintf (fp,"%*s%16" PRIx64, (int )depth *4 ,"" , ip);if (len <0 )return ;
@@ -1001,39 +1006,40 @@ static void print_sample_callindent(struct perf_sample *sample, spacing =round_up (len +4 ,32 );if (len < spacing) -printf ("%*s" , spacing - len,"" ); +fprintf (fp,"%*s" , spacing - len,"" ); } -static void print_insn (struct perf_sample *sample, +static void fprint_insn (struct perf_sample *sample,struct perf_event_attr *attr,struct thread *thread, -struct machine *machine) +struct machine *machine,FILE *fp) {if (PRINT_FIELD (INSNLEN )) -printf (" ilen: %d" , sample->insn_len); +fprintf (fp," ilen: %d" , sample->insn_len);if (PRINT_FIELD (INSN )) {int i; -printf (" insn:" ); +fprintf (fp," insn:" );for (i =0 ; i < sample->insn_len; i++) -printf (" %02x" , (unsigned char )sample->insn[i]); +fprintf (fp," %02x" , (unsigned char )sample->insn[i]); }if (PRINT_FIELD (BRSTACKINSN )) -print_sample_brstackinsn (sample, thread, attr, machine); +fprint_sample_brstackinsn (sample, thread, attr, machine, fp); } -static void print_sample_bts (struct perf_sample *sample, +static void fprint_sample_bts (struct perf_sample *sample,struct perf_evsel *evsel,struct thread *thread,struct addr_location *al, -struct machine *machine) +struct machine *machine, +FILE *fp) {struct perf_event_attr *attr = &evsel->attr;unsigned int type =output_type (attr->type);bool print_srcline_last = false;if (PRINT_FIELD (CALLINDENT )) -print_sample_callindent (sample, evsel, thread, al); +fprint_sample_callindent (sample, evsel, thread, al, fp);/* print branch_from information */ if (PRINT_FIELD (IP )) {
@@ -1046,31 +1052,31 @@ static void print_sample_bts(struct perf_sample *sample, cursor = &callchain_cursor;if (cursor ==NULL ) { -putchar (' ' ); +fputc (' ' , fp);if (print_opts &EVSEL__PRINT_SRCLINE ) { print_srcline_last = true; print_opts &= ~EVSEL__PRINT_SRCLINE ; } }else -putchar ('\n' ); +fputc ('\n' , fp); -sample__fprintf_sym (sample, al,0 , print_opts, cursor, stdout); +sample__fprintf_sym (sample, al,0 , print_opts, cursor, fp); }/* print branch_to information */ if (PRINT_FIELD (ADDR ) || ((evsel->attr.sample_type &PERF_SAMPLE_ADDR ) && !output[type].user_set)) { -printf (" => " ); -print_sample_addr (sample, thread, attr); +fprintf (fp," => " ); +fprint_sample_addr (sample, thread, attr, fp); }if (print_srcline_last) -map__fprintf_srcline (al->map, al->addr,"\n " , stdout); +map__fprintf_srcline (al->map, al->addr,"\n " , fp); -print_insn (sample, attr, thread, machine); +fprint_insn (sample, attr, thread, machine, fp); -printf ("\n" ); +fprintf (fp,"\n" ); } static struct {
@@ -1093,7 +1099,7 @@ static void print_sample_bts(struct perf_sample *sample, {0, NULL} }; -static void print_sample_flags (u32 flags) +static void fprint_sample_flags (u32 flags,FILE *fp) {const char *chars =PERF_IP_FLAG_CHARS ;const int n =strlen (PERF_IP_FLAG_CHARS );
@@ -1120,51 +1126,53 @@ static void print_sample_flags(u32 flags) str[pos] =0 ;if (name) -printf (" %-7s%4s " , name, in_tx ?"(x)" :"" ); +fprintf (fp," %-7s%4s " , name, in_tx ?"(x)" :"" );else -printf (" %-11s " , str); +fprintf (fp," %-11s " , str); }struct printer_data {int line_no;bool hit_nul;bool is_printable; +FILE *fp; };static void -print_sample_bpf_output_printer (enum binary_printer_ops op, +fprint_sample_bpf_output_printer (enum binary_printer_ops op,unsigned int val,void *extra) {unsigned char ch = (unsigned char )val;struct printer_data *printer_data = extra; +FILE *fp = printer_data->fp;switch (op) {case BINARY_PRINT_DATA_BEGIN : -printf ("\n" ); +fprintf (fp,"\n" );break ;case BINARY_PRINT_LINE_BEGIN : -printf ("%17s" , !printer_data->line_no ?"BPF output:" : +fprintf (fp,"%17s" , !printer_data->line_no ?"BPF output:" :" " );break ;case BINARY_PRINT_ADDR : -printf (" %04x:" , val); +fprintf (fp," %04x:" , val);break ;case BINARY_PRINT_NUM_DATA : -printf (" %02x" , val); +fprintf (fp," %02x" , val);break ;case BINARY_PRINT_NUM_PAD : -printf (" " ); +fprintf (fp," " );break ;case BINARY_PRINT_SEP : -printf (" " ); +fprintf (fp," " );break ;case BINARY_PRINT_CHAR_DATA :if (printer_data->hit_nul && ch) printer_data->is_printable = false;if (!isprint (ch)) { -printf ("%c" ,'.' ); +fprintf (fp,"%c" ,'.' );if (!printer_data->is_printable)break ;
@@ -1174,14 +1182,14 @@ struct printer_data {else printer_data->is_printable = false; }else { -printf ("%c" , ch); +fprintf (fp,"%c" , ch); }break ;case BINARY_PRINT_CHAR_PAD : -printf (" " ); +fprintf (fp," " );break ;case BINARY_PRINT_LINE_END : -printf ("\n" ); +fprintf (fp,"\n" ); printer_data->line_no++;break ;case BINARY_PRINT_DATA_END :
@@ -1190,31 +1198,31 @@ struct printer_data { } } -static void print_sample_bpf_output (struct perf_sample *sample) +static void fprint_sample_bpf_output (struct perf_sample *sample,FILE *fp) {unsigned int nr_bytes = sample->raw_size; -struct printer_data printer_data = {0 , false, true}; +struct printer_data printer_data = {0 , false, true, fp};print_binary (sample->raw_data, nr_bytes,8 , - print_sample_bpf_output_printer, &printer_data); + fprint_sample_bpf_output_printer, &printer_data);if (printer_data.is_printable && printer_data.hit_nul) -printf ("%17s \"%s\"\n" ,"BPF string:" , +fprintf (fp,"%17s \"%s\"\n" ,"BPF string:" , (char *)(sample->raw_data)); } -static void print_sample_spacing (int len,int spacing) +static void fprint_sample_spacing (int len,int spacing,FILE *fp) {if (len >0 && len < spacing) -printf ("%*s" , spacing - len,"" ); +fprintf (fp,"%*s" , spacing - len,"" ); } -static void print_sample_pt_spacing (int len) +static void fprint_sample_pt_spacing (int len,FILE *fp) { -print_sample_spacing (len,34 ); +fprint_sample_spacing (len,34 , fp); } -static void print_sample_synth_ptwrite (struct perf_sample *sample) +static void fprint_sample_synth_ptwrite (struct perf_sample *sample,FILE *fp) {struct perf_synth_intel_ptwrite *data =perf_sample__synth_ptr (sample);int len;
@@ -1222,12 +1230,12 @@ static void print_sample_synth_ptwrite(struct perf_sample *sample)if (perf_sample__bad_synth_size (sample, *data))return ; - len =printf (" IP: %u payload: %#" PRIx64" " , + len =fprintf (fp," IP: %u payload: %#" PRIx64" " , data->ip,le64_to_cpu (data->payload)); -print_sample_pt_spacing (len); +fprint_sample_pt_spacing (len, fp); } -static void print_sample_synth_mwait (struct perf_sample *sample) +static void fprint_sample_synth_mwait (struct perf_sample *sample,FILE *fp) {struct perf_synth_intel_mwait *data =perf_sample__synth_ptr (sample);int len;
@@ -1235,12 +1243,12 @@ static void print_sample_synth_mwait(struct perf_sample *sample)if (perf_sample__bad_synth_size (sample, *data))return ; - len =printf (" hints: %#x extensions: %#x " , + len =fprintf (fp," hints: %#x extensions: %#x " , data->hints, data->extensions); -print_sample_pt_spacing (len); +fprint_sample_pt_spacing (len, fp); } -static void print_sample_synth_pwre (struct perf_sample *sample) +static void fprint_sample_synth_pwre (struct perf_sample *sample,FILE *fp) {struct perf_synth_intel_pwre *data =perf_sample__synth_ptr (sample);int len;
@@ -1248,12 +1256,12 @@ static void print_sample_synth_pwre(struct perf_sample *sample)if (perf_sample__bad_synth_size (sample, *data))return ; - len =printf (" hw: %u cstate: %u sub-cstate: %u " , + len =fprintf (fp," hw: %u cstate: %u sub-cstate: %u " , data->hw, data->cstate, data->subcstate); -print_sample_pt_spacing (len); +fprint_sample_pt_spacing (len, fp); } -static void print_sample_synth_exstop (struct perf_sample *sample) +static void fprint_sample_synth_exstop (struct perf_sample *sample,FILE *fp) {struct perf_synth_intel_exstop *data =perf_sample__synth_ptr (sample);int len;
@@ -1261,11 +1269,11 @@ static void print_sample_synth_exstop(struct perf_sample *sample)if (perf_sample__bad_synth_size (sample, *data))return ; - len =printf (" IP: %u " , data->ip); -print_sample_pt_spacing (len); + len =fprintf (fp," IP: %u " , data->ip); +fprint_sample_pt_spacing (len, fp); } -static void print_sample_synth_pwrx (struct perf_sample *sample) +static void fprint_sample_synth_pwrx (struct perf_sample *sample,FILE *fp) {struct perf_synth_intel_pwrx *data =perf_sample__synth_ptr (sample);int len;
@@ -1273,13 +1281,13 @@ static void print_sample_synth_pwrx(struct perf_sample *sample)if (perf_sample__bad_synth_size (sample, *data))return ; - len =printf (" deepest cstate: %u last cstate: %u wake reason: %#x " , + len =fprintf (fp," deepest cstate: %u last cstate: %u wake reason: %#x " , data->deepest_cstate, data->last_cstate, data->wake_reason); -print_sample_pt_spacing (len); +fprint_sample_pt_spacing (len, fp); } -static void print_sample_synth_cbr (struct perf_sample *sample) +static void fprint_sample_synth_cbr (struct perf_sample *sample,FILE *fp) {struct perf_synth_intel_cbr *data =perf_sample__synth_ptr (sample);unsigned int percent, freq;
@@ -1289,35 +1297,35 @@ static void print_sample_synth_cbr(struct perf_sample *sample)return ; freq = (le32_to_cpu (data->freq) +500 ) /1000 ; - len =printf (" cbr: %2u freq: %4u MHz " , data->cbr, freq); + len =fprintf (fp," cbr: %2u freq: %4u MHz " , data->cbr, freq);if (data->max_nonturbo) { percent = (5 + (1000 * data->cbr) / data->max_nonturbo) /10 ; - len +=printf ("(%3u%%) " , percent); + len +=fprintf (fp,"(%3u%%) " , percent); } -print_sample_pt_spacing (len); +fprint_sample_pt_spacing (len, fp); } -static void print_sample_synth (struct perf_sample *sample, -struct perf_evsel *evsel) +static void fprint_sample_synth (struct perf_sample *sample, +struct perf_evsel *evsel,FILE *fp) {switch (evsel->attr.config) {case PERF_SYNTH_INTEL_PTWRITE : -print_sample_synth_ptwrite (sample); +fprint_sample_synth_ptwrite (sample, fp);break ;case PERF_SYNTH_INTEL_MWAIT : -print_sample_synth_mwait (sample); +fprint_sample_synth_mwait (sample, fp);break ;case PERF_SYNTH_INTEL_PWRE : -print_sample_synth_pwre (sample); +fprint_sample_synth_pwre (sample, fp);break ;case PERF_SYNTH_INTEL_EXSTOP : -print_sample_synth_exstop (sample); +fprint_sample_synth_exstop (sample, fp);break ;case PERF_SYNTH_INTEL_PWRX : -print_sample_synth_pwrx (sample); +fprint_sample_synth_pwrx (sample, fp);break ;case PERF_SYNTH_INTEL_CBR : -print_sample_synth_cbr (sample); +fprint_sample_synth_cbr (sample, fp);break ;default :break ;
@@ -1353,7 +1361,7 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)return max; } -static size_t data_src__printf (u64 data_src) +static size_t data_src__fprintf (u64 data_src,FILE *fp) {struct mem_info mi = { .data_src.val = data_src };char decode[100 ];
@@ -1367,59 +1375,69 @@ static size_t data_src__printf(u64 data_src)if (maxlen < len) maxlen = len; -return printf ("%-*s" , maxlen, out); +return fprintf (fp,"%-*s" , maxlen, out); } +#define FILE_LEN 100static void process_event (struct perf_script *script,struct perf_sample *sample,struct perf_evsel *evsel,struct addr_location *al, -struct machine *machine) +struct machine *machine,FILE *fp) {struct thread *thread = al->thread;struct perf_event_attr *attr = &evsel->attr;unsigned int type =output_type (attr->type); - +const char *evname; +char *file_name;if (output[type].fields ==0 )return ; -print_sample_start (sample, thread, evsel); + evname =perf_evsel__name (evsel); +if (script->tool.orientation_output == true) { + file_name = (char *)malloc (sizeof (char ) *FILE_LEN ); +strcpy (file_name, evname); +strcat (file_name,".stacks" ); + fp =fopen (file_name,"a+" ); +if (!fp) +return ; +free (file_name); + } +fprint_sample_start (sample, thread, evsel, fp);if (PRINT_FIELD (PERIOD )) -printf ("%10" PRIu64" " , sample->period); +fprintf (fp,"%10" PRIu64" " , sample->period);if (PRINT_FIELD (EVNAME )) { -const char *evname =perf_evsel__name (evsel); -if (!script->name_width) script->name_width =perf_evlist__max_name_len (script->session->evlist); -printf ("%*s: " , script->name_width, +fprintf (fp,"%*s: " , script->name_width, evname ? evname :"[unknown]" ); }if (print_flags) -print_sample_flags (sample->flags); +fprint_sample_flags (sample->flags, fp);if (is_bts_event (attr)) { -print_sample_bts (sample, evsel, thread, al, machine); +fprint_sample_bts (sample, evsel, thread, al, machine, fp);return ; }if (PRINT_FIELD (TRACE )) -event_format__print (evsel->tp_format, sample->cpu, - sample->raw_data, sample->raw_size); +event_format__fprintf (evsel->tp_format, sample->cpu, + sample->raw_data, sample->raw_size, fp);if (attr->type ==PERF_TYPE_SYNTH &&PRINT_FIELD (SYNTH )) -print_sample_synth (sample, evsel); +fprint_sample_synth (sample, evsel, fp);if (PRINT_FIELD (ADDR )) -print_sample_addr (sample, thread, attr); +fprint_sample_addr (sample, thread, attr, fp);if (PRINT_FIELD (DATA_SRC )) -data_src__printf (sample->data_src); +data_src__fprintf (sample->data_src, fp);if (PRINT_FIELD (WEIGHT )) -printf ("%16" PRIu64, sample->weight); +fprintf (fp,"%16" PRIu64, sample->weight);if (PRINT_FIELD (IP )) {struct callchain_cursor *cursor =NULL ;
@@ -1429,24 +1447,26 @@ static void process_event(struct perf_script *script, sample, NULL, NULL, scripting_max_stack) == 0) cursor = &callchain_cursor; -putchar (cursor ?'\n' :' ' ); -sample__fprintf_sym (sample, al,0 , output[type].print_ip_opts, cursor, stdout); +fputc (cursor ?'\n' :' ' , fp); +sample__fprintf_sym (sample, al,0 , output[type].print_ip_opts, cursor, fp); }if (PRINT_FIELD (IREGS )) -print_sample_iregs (sample, attr); +fprint_sample_iregs (sample, attr, fp);if (PRINT_FIELD (BRSTACK )) -print_sample_brstack (sample, thread, attr); +fprint_sample_brstack (sample, thread, attr, fp);else if (PRINT_FIELD (BRSTACKSYM )) -print_sample_brstacksym (sample, thread, attr); +fprint_sample_brstacksym (sample, thread, attr, fp);else if (PRINT_FIELD (BRSTACKOFF )) -print_sample_brstackoff (sample, thread, attr); +fprint_sample_brstackoff (sample, thread, attr, fp);if (perf_evsel__is_bpf_output (evsel) &&PRINT_FIELD (BPF_OUTPUT )) -print_sample_bpf_output (sample); -print_insn (sample, attr, thread, machine); -printf ("\n" ); +fprint_sample_bpf_output (sample, fp); +fprint_insn (sample, attr, thread, machine, fp); +fprintf (fp,"\n" ); +if (script->tool.orientation_output == true) +fclose (fp); }static struct scripting_ops *scripting_ops;
@@ -1554,9 +1574,12 @@ static int process_sample_event(struct perf_tool *tool,if (scripting_ops) scripting_ops->process_event (event, sample, evsel, &al); -else -process_event (scr, sample, evsel, &al, machine); - +else { +if (tool->orientation_output == false) +process_event (scr, sample, evsel, &al, machine, stdout); +else +process_event (scr, sample, evsel, &al, machine, orientation_file); + } out_put:addr_location__put (&al);return 0 ;
@@ -1620,8 +1643,13 @@ static int process_comm_event(struct perf_tool *tool, sample->tid = event->comm.tid; sample->pid = event->comm.pid; } -print_sample_start (sample, thread, evsel); -perf_event__fprintf (event, stdout); +if (tool->orientation_output == false) { +fprint_sample_start (sample, thread, evsel, stdout); +perf_event__fprintf (event, stdout); + }else { +fprint_sample_start (sample, thread, evsel, orientation_file); +perf_event__fprintf (event, orientation_file); + } ret =0 ; out:thread__put (thread);
@@ -1655,8 +1683,13 @@ static int process_namespaces_event(struct perf_tool *tool, sample->tid = event->namespaces.tid; sample->pid = event->namespaces.pid; } -print_sample_start (sample, thread, evsel); -perf_event__fprintf (event, stdout); +if (tool->orientation_output == false) { +fprint_sample_start (sample, thread, evsel, stdout); +perf_event__fprintf (event, stdout); + }else { +fprint_sample_start (sample, thread, evsel, orientation_file); +perf_event__fprintf (event, orientation_file); + } ret =0 ; out:thread__put (thread);
@@ -1688,8 +1721,13 @@ static int process_fork_event(struct perf_tool *tool, sample->tid = event->fork.tid; sample->pid = event->fork.pid; } -print_sample_start (sample, thread, evsel); -perf_event__fprintf (event, stdout); +if (tool->orientation_output == false) { +fprint_sample_start (sample, thread, evsel, stdout); +perf_event__fprintf (event, stdout); + }else { +fprint_sample_start (sample, thread, evsel, orientation_file); +perf_event__fprintf (event, orientation_file); + }thread__put (thread);return 0 ;
@@ -1717,8 +1755,13 @@ static int process_exit_event(struct perf_tool *tool, sample->tid = event->fork.tid; sample->pid = event->fork.pid; } -print_sample_start (sample, thread, evsel); -perf_event__fprintf (event, stdout); +if (tool->orientation_output == false) { +fprint_sample_start (sample, thread, evsel, stdout); +perf_event__fprintf (event, stdout); + }else { +fprint_sample_start (sample, thread, evsel, orientation_file); +perf_event__fprintf (event, orientation_file); + }if (perf_event__process_exit (tool, event, sample, machine) <0 ) err =-1 ;
@@ -1752,8 +1795,13 @@ static int process_mmap_event(struct perf_tool *tool, sample->tid = event->mmap.tid; sample->pid = event->mmap.pid; } -print_sample_start (sample, thread, evsel); -perf_event__fprintf (event, stdout); +if (tool->orientation_output == false) { +fprint_sample_start (sample, thread, evsel, stdout); +perf_event__fprintf (event, stdout); + }else { +fprint_sample_start (sample, thread, evsel, orientation_file); +perf_event__fprintf (event, orientation_file); + }thread__put (thread);return 0 ; }
@@ -1783,8 +1831,13 @@ static int process_mmap2_event(struct perf_tool *tool, sample->tid = event->mmap2.tid; sample->pid = event->mmap2.pid; } -print_sample_start (sample, thread, evsel); -perf_event__fprintf (event, stdout); +if (tool->orientation_output == false) { +fprint_sample_start (sample, thread, evsel, stdout); +perf_event__fprintf (event, stdout); + }else { +fprint_sample_start (sample, thread, evsel, orientation_file); +perf_event__fprintf (event, orientation_file); + }thread__put (thread);return 0 ; }
@@ -1809,8 +1862,13 @@ static int process_switch_event(struct perf_tool *tool,return -1 ; } -print_sample_start (sample, thread, evsel); -perf_event__fprintf (event, stdout); +if (tool->orientation_output == false) { +fprint_sample_start (sample, thread, evsel, stdout); +perf_event__fprintf (event, stdout); + }else { +fprint_sample_start (sample, thread, evsel, orientation_file); +perf_event__fprintf (event, orientation_file); + }thread__put (thread);return 0 ; }
@@ -2690,6 +2748,7 @@ int cmd_script(int argc, const char **argv) .cpu_map = process_cpu_map_event, .ordered_events = true, .ordering_requires_timestamps = true, + .orientation_output = false, }, }; struct perf_data_file file = {
@@ -2761,6 +2820,8 @@ int cmd_script(int argc, const char **argv)OPT_BOOLEAN ('\0' ,"show-namespace-events" , &script.show_namespace_events,"Show namespace events (if recorded)" ),OPT_BOOLEAN ('f' ,"force" , &symbol_conf.force,"don't complain, do it" ), +OPT_BOOLEAN ('O' ,"orientation" , &script.tool.orientation_output, +"print trace output to files named by the monitored events" ),OPT_INTEGER (0 ,"max-blocks" , &max_blocks,"Maximum number of code blocks to dump with brstackinsn" ), OPT_BOOLEAN(0, "ns", &nanosecs,
@@ -2797,6 +2858,12 @@ int cmd_script(int argc, const char **argv) file.path = input_name; file.force = symbol_conf.force; +for (i =1 ; argv[i] !=NULL ; i++) { +if (strcmp (argv[i],"-O" ) ==0 ) { + script.tool.orientation_output = true; +break ; + } + }if (argc >1 && !strncmp (argv[0 ],"rec" ,strlen ("rec" ))) { rec_script_path =get_script_path (argv[1 ],RECORD_SUFFIX );
tools/perf/util/tool.h +1 -0
@@ -75,6 +75,7 @@ struct perf_tool {bool ordered_events;bool ordering_requires_timestamps;bool namespace_events; +bool orientation_output;enum show_feature_header show_feat_hdr; };
Signature · 1 line
1.8.3.1