tracing: updates
Steven Rostedt
maintainerIngo,
Please pull the latest tip/perf/core tree, which can be found at:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git
tip/perf/core
Head SHA1: 39eaf7ef884dcc44f7ff1bac803ca2a1dcf43544
Steven Rostedt (2):
tracing: Add irq, preempt-count and need resched info to default trace output
tracing: Add entries in buffer and total entries to default output header
----
kernel/trace/trace.c | 90 ++++++++++++++++++++++++++++++------------ kernel/trace/trace.h | 1 + kernel/trace/trace_output.c | 16 +++++++- 3 files changed, 79 insertions(+), 28 deletions(-)
Steven Rostedt
maintainerPATCH 1/2 tracing: Add irq, preempt-count and need resched info to default trace output
From: Steven Rostedt <[email protected]>
People keep asking how to get the preempt count, irq, and need resched info and we keep telling them to enable the latency format. Some developers think that traces without this info is completely useless, and for a lot of tasks it is useless.
The first option was to enable the latency trace as the default format, but the header for the latency format is pretty useless for most tracers and it also does the timestamp in straight microseconds from the time the trace started. This is sometimes more difficult to read as the default trace is seconds from the start of boot up.
Latency format:
# tracer: nop
#
# nop latency trace v1.1.5 on 3.2.0-rc1-test+ # -------------------------------------------------------------------- # latency: 0 us, #159771/64234230, CPU#1 | (M:preempt VP:0, KP:0, SP:0 HP:0 #P:4) # ----------------- # | task: -0 (uid:0 nice:0 policy:0 rt_prio:0) # ----------------- # # _------=> CPU# # / _-----=> irqs-off # | / _----=> need-resched # || / _---=> hardirq/softirq # ||| / _--=> preempt-depth # |||| / delay # cmd pid ||||| time | caller # \ / ||||| \ | / migratio-6 0...2 41778231us+: rcu_note_context_switch <-__schedule migratio-6 0...2 41778233us : trace_rcu_utilization <-rcu_note_context_switch migratio-6 0...2 41778235us+: rcu_sched_qs <-rcu_note_context_switch migratio-6 0d..2 41778236us+: rcu_preempt_qs <-rcu_note_context_switch migratio-6 0...2 41778238us : trace_rcu_utilization <-rcu_note_context_switch migratio-6 0...2 41778239us+: debug_lockdep_rcu_enabled <-__schedule
default format:
# tracer: nop
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
migration/0-6 [000] 50.025810: rcu_note_context_switch <-__schedule
migration/0-6 [000] 50.025812: trace_rcu_utilization <-rcu_note_context_switch
migration/0-6 [000] 50.025813: rcu_sched_qs <-rcu_note_context_switch
migration/0-6 [000] 50.025815: rcu_preempt_qs <-rcu_note_context_switch
migration/0-6 [000] 50.025817: trace_rcu_utilization <-rcu_note_context_switch
migration/0-6 [000] 50.025818: debug_lockdep_rcu_enabled <-__schedule
migration/0-6 [000] 50.025820: debug_lockdep_rcu_enabled <-__scheduleThe latency format header has latency information that is pretty meaningless for most tracers. Although some of the header is useful, and we can add that later to the default format as well.
What is really useful with the latency format is the irqs-off, need-resched hard/softirq context and the preempt count.
This commit adds the option irq-info which is on by default that adds this information:
# tracer: nop
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
<idle>-0 [000] d..2 49.309305: cpuidle_get_driver <-cpuidle_idle_call
<idle>-0 [000] d..2 49.309307: mwait_idle <-cpu_idle
<idle>-0 [000] d..2 49.309309: need_resched <-mwait_idle
<idle>-0 [000] d..2 49.309310: test_ti_thread_flag <-need_resched
<idle>-0 [000] d..2 49.309312: trace_power_start.constprop.13 <-mwait_idle
<idle>-0 [000] d..2 49.309313: trace_cpu_idle <-mwait_idle
<idle>-0 [000] d..2 49.309315: need_resched <-mwait_idleIf a user wants the old format, they can disable the 'irq-info' option:
# tracer: nop
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
<idle>-0 [000] 49.309305: cpuidle_get_driver <-cpuidle_idle_call
<idle>-0 [000] 49.309307: mwait_idle <-cpu_idle
<idle>-0 [000] 49.309309: need_resched <-mwait_idle
<idle>-0 [000] 49.309310: test_ti_thread_flag <-need_resched
<idle>-0 [000] 49.309312: trace_power_start.constprop.13 <-mwait_idle
<idle>-0 [000] 49.309313: trace_cpu_idle <-mwait_idle
<idle>-0 [000] 49.309315: need_resched <-mwait_idle--- kernel/trace/trace.c | 24 ++++++++++++++++++++---- kernel/trace/trace.h | 1 + kernel/trace/trace_output.c | 16 ++++++++++++++-- 3 files changed, 35 insertions(+), 6 deletions(-)
kernel/trace/trace.c +20 -4
@@ -338,7 +338,8 @@ static DECLARE_WAIT_QUEUE_HEAD(trace_wait);/* trace_flags holds trace_options default values */ unsigned long trace_flags =TRACE_ITER_PRINT_PARENT |TRACE_ITER_PRINTK |TRACE_ITER_ANNOTATE |TRACE_ITER_CONTEXT_INFO |TRACE_ITER_SLEEP_TIME | -TRACE_ITER_GRAPH_TIME |TRACE_ITER_RECORD_CMD |TRACE_ITER_OVERWRITE ; +TRACE_ITER_GRAPH_TIME |TRACE_ITER_RECORD_CMD |TRACE_ITER_OVERWRITE | +TRACE_ITER_IRQ_INFO ;static int trace_stop_count;static DEFINE_RAW_SPINLOCK (tracing_start_lock);
@@ -426,6 +427,7 @@ static const char *trace_options[] = {"record-cmd" ,"overwrite" ,"disable_on_free" , +"irq-info" , NULL };
@@ -1857,10 +1859,20 @@ static void print_lat_help_header(struct seq_file *m)static void print_func_help_header (struct seq_file *m) { -seq_puts (m,"# TASK-PID CPU# TIMESTAMP FUNCTION\n" ); +seq_puts (m,"# TASK-PID CPU# TIMESTAMP FUNCTION\n" );seq_puts (m,"# | | | | |\n" ); } +static void print_func_help_header_irq (struct seq_file *m) +{ +seq_puts (m,"# _-----=> irqs-off\n" ); +seq_puts (m,"# / _----=> need-resched\n" ); +seq_puts (m,"# | / _---=> hardirq/softirq\n" ); +seq_puts (m,"# || / _--=> preempt-depth\n" ); +seq_puts (m,"# ||| / delay\n" ); +seq_puts (m,"# TASK-PID CPU# |||| TIMESTAMP FUNCTION\n" ); +seq_puts (m,"# | | | |||| | |\n" ); +}void print_trace_header (struct seq_file *m,struct trace_iterator *iter)
@@ -2170,8 +2182,12 @@ void trace_default_header(struct seq_file *m)if (!(trace_flags &TRACE_ITER_VERBOSE ))print_lat_help_header (m); }else { -if (!(trace_flags &TRACE_ITER_VERBOSE )) -print_func_help_header (m); +if (!(trace_flags &TRACE_ITER_VERBOSE )) { +if (trace_flags &TRACE_ITER_IRQ_INFO ) +print_func_help_header_irq (m); +else +print_func_help_header (m); + } } }
kernel/trace/trace.h +1 -0
@@ -655,6 +655,7 @@ enum trace_iterator_flags {TRACE_ITER_RECORD_CMD =0x100000 ,TRACE_ITER_OVERWRITE =0x200000 ,TRACE_ITER_STOP_ON_FREE =0x400000 , + TRACE_ITER_IRQ_INFO = 0x800000, };/*
kernel/trace/trace_output.c +14 -2
@@ -627,11 +627,23 @@ int trace_print_context(struct trace_iterator *iter)unsigned long usec_rem =do_div (t,USEC_PER_SEC );unsigned long secs = (unsigned long )t;char comm[TASK_COMM_LEN ]; +int ret;trace_find_cmdline (entry->pid, comm); -return trace_seq_printf (s,"%16s-%-5d [%03d] %5lu.%06lu: " , - comm, entry->pid, iter->cpu, secs, usec_rem); + ret =trace_seq_printf (s,"%16s-%-5d [%03d] " , + comm, entry->pid, iter->cpu); +if (!ret) +return 0 ; + +if (trace_flags &TRACE_ITER_IRQ_INFO ) { + ret =trace_print_lat_fmt (s, entry); +if (!ret) +return 0 ; + } + +return trace_seq_printf (s," %5lu.%06lu: " , + secs, usec_rem); }int trace_print_lat_context (struct trace_iterator *iter)
Signature · 1 line
1.7.7.3
Steven Rostedt
maintainerPATCH 2/2 tracing: Add entries in buffer and total entries to default output header
In reply to Steven RostedtFrom: Steven Rostedt <[email protected]>
Knowing the number of event entries in the ring buffer compared to the total number that were written is useful information. The latency format gives this information and there's no reason that the default format does not.
This information is now added to the default header, along with the number of online CPUs:
# tracer: nop
#
# entries-in-buffer/entries-written: 159836/64690869 #P:4
#
# _-----=> irqs-off
# / _----=> need-resched
# | / _---=> hardirq/softirq
# || / _--=> preempt-depth
# ||| / delay
# TASK-PID CPU# |||| TIMESTAMP FUNCTION
# | | | |||| | |
<idle>-0 [000] ...2 49.442971: local_touch_nmi <-cpu_idle
<idle>-0 [000] d..2 49.442973: enter_idle <-cpu_idle
<idle>-0 [000] d..2 49.442974: atomic_notifier_call_chain <-enter_idle
<idle>-0 [000] d..2 49.442976: __atomic_notifier_call_chain <-atomic_notifierThe above shows that the trace contains 159836 entries, but 64690869 were written. One could figure out that there were 64531033 entries that were dropped.
--- kernel/trace/trace.c | 72 ++++++++++++++++++++++++++++++++----------------- 1 files changed, 47 insertions(+), 25 deletions(-)
kernel/trace/trace.c +47 -25
@@ -1845,6 +1845,33 @@ static void s_stop(struct seq_file *m, void *p)trace_event_read_unlock (); } +static void +get_total_entries (struct trace_array *tr,unsigned long *total,unsigned long *entries) +{ +unsigned long count; +int cpu; + + *total =0 ; + *entries =0 ; + +for_each_tracing_cpu (cpu) { + count =ring_buffer_entries_cpu (tr->buffer, cpu); +/* +* If this buffer has skipped entries, then we hold all +* entries for the trace and we need to ignore the +* ones before the time stamp. +*/ +if (tr->data[cpu]->skipped_entries) { + count -= tr->data[cpu]->skipped_entries; +/* total is the same as the entries */ + *total += count; + }else + *total += count + +ring_buffer_overrun_cpu (tr->buffer, cpu); + *entries += count; + } +} +static void print_lat_help_header (struct seq_file *m) {seq_puts (m,"# _------=> CPU# \n" );
@@ -1857,14 +1884,27 @@ static void print_lat_help_header(struct seq_file *m)seq_puts (m,"# \\ / ||||| \\ | / \n" ); } -static void print_func_help_header (struct seq_file *m) +static void print_event_info (struct trace_array *tr,struct seq_file *m) { +unsigned long total; +unsigned long entries; + +get_total_entries (tr, &total, &entries); +seq_printf (m,"# entries-in-buffer/entries-written: %lu/%lu #P:%d\n" , + entries, total,num_online_cpus ()); +seq_puts (m,"#\n" ); +} + +static void print_func_help_header (struct trace_array *tr,struct seq_file *m) +{ +print_event_info (tr, m);seq_puts (m,"# TASK-PID CPU# TIMESTAMP FUNCTION\n" );seq_puts (m,"# | | | | |\n" ); } -static void print_func_help_header_irq (struct seq_file *m) +static void print_func_help_header_irq (struct trace_array *tr,struct seq_file *m) { +print_event_info (tr, m);seq_puts (m,"# _-----=> irqs-off\n" );seq_puts (m,"# / _----=> need-resched\n" );seq_puts (m,"# | / _---=> hardirq/softirq\n" );
@@ -1881,32 +1921,14 @@ print_trace_header(struct seq_file *m, struct trace_iterator *iter)struct trace_array *tr = iter->tr;struct trace_array_cpu *data = tr->data[tr->cpu];struct tracer *type = current_trace; -unsigned long entries =0 ; -unsigned long total =0 ; -unsigned long count; +unsigned long entries; +unsigned long total;const char *name ="preemption" ; -int cpu;if (type) name = type->name; - -for_each_tracing_cpu (cpu) { - count =ring_buffer_entries_cpu (tr->buffer, cpu); -/* -* If this buffer has skipped entries, then we hold all -* entries for the trace and we need to ignore the -* ones before the time stamp. -*/ -if (tr->data[cpu]->skipped_entries) { - count -= tr->data[cpu]->skipped_entries; -/* total is the same as the entries */ - total += count; - }else - total += count + -ring_buffer_overrun_cpu (tr->buffer, cpu); - entries += count; - } +get_total_entries (tr, &total, &entries);seq_printf (m,"# %s latency trace v1.1.5 on %s\n" , name,UTS_RELEASE );
@@ -2184,9 +2206,9 @@ void trace_default_header(struct seq_file *m) }else {if (!(trace_flags &TRACE_ITER_VERBOSE )) {if (trace_flags &TRACE_ITER_IRQ_INFO ) -print_func_help_header_irq (m); +print_func_help_header_irq (iter->tr, m);else -print_func_help_header (m); +print_func_help_header (iter->tr, m); } } }
Signature · 1 line
1.7.7.3