The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 1/2] tracing/function-graph-tracer: various fixes and features
@ 2009-01-22  1:24 Frederic Weisbecker
  2009-01-22  1:43 ` Steven Rostedt
  0 siblings, 1 reply; 4+ messages in thread
From: Frederic Weisbecker @ 2009-01-22  1:24 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Ingo Molnar, Linux Kernel Mailing List, Frederic Weisbecker

I thought I would have the time to implement the callbacks in trace_event too but I
really have to sleep :-(
That will be for later.
--

This patch brings various bugfixes:

_ Drop the first irrelevant task switch on the very beginning of a trace.
  But actually that only solves the first time one does print the trace file.
  I have to fix the others cases too.
_ Drop the OVERHEAD word from the headers, the DURATION word is sufficient and will not
  overlap other columns.
_ Make the headers fit well their respective columns whatever the selected options.

Ie, default options:

# tracer: function_graph
#
# CPU  DURATION                  FUNCTION CALLS
# |     |   |                     |   |   |   |

 1)   0.646 us    |                    }
 1)               |                    mem_cgroup_del_lru_list() {
 1)   0.624 us    |                      lookup_page_cgroup();
 1)   1.970 us    |                    }

echo funcgraph-proc > trace_options

# tracer: function_graph
#
# CPU  TASK/PID        DURATION                  FUNCTION CALLS
# |    |    |           |   |                     |   |   |   |

 0)   bash-2937    |   0.895 us    |                }
 0)   bash-2937    |   0.888 us    |                __rcu_read_unlock();
 0)   bash-2937    |   0.864 us    |                conv_uni_to_pc();
 0)   bash-2937    |   1.015 us    |                __rcu_read_lock();

echo nofuncgraph-cpu > trace_options
echo nofuncgraph-proc > trace_options

# tracer: function_graph
#
#   DURATION                  FUNCTION CALLS
#    |   |                     |   |   |   |

  3.752 us    |                  native_pud_val();
  0.616 us    |                  native_pud_val();
  0.624 us    |                  native_pmd_val();


About features, one can now disable the duration (this will hide the overhead too
for convenient reasons and because on  doesn't need overhead if it hasn't the duration

echo nofuncgraph-duration > trace_options

# tracer: function_graph
#
#                FUNCTION CALLS
#                |   |   |   |

          cap_vm_enough_memory() {
            __vm_enough_memory() {
              vm_acct_memory();
            }
          }
        }

And at last, an option to print the absolute time:

//Restart from default options
echo funcgraph-abstime > trace_options

# tracer: function_graph
#
#      TIME       CPU  DURATION                  FUNCTION CALLS
#       |         |     |   |                     |   |   |   |

  261.339774 |   1) + 42.823 us   |    }
  261.339775 |   1)   1.045 us    |    _spin_lock_irq();
  261.339777 |   1)   0.940 us    |    _spin_lock_irqsave();
  261.339778 |   1)   0.752 us    |    _spin_unlock_irqrestore();
  261.339780 |   1)   0.857 us    |    _spin_unlock_irq();
  261.339782 |   1)               |    flush_to_ldisc() {
  261.339783 |   1)               |      tty_ldisc_ref() {
  261.339783 |   1)               |        tty_ldisc_try() {
  261.339784 |   1)   1.075 us    |          _spin_lock_irqsave();
  261.339786 |   1)   0.842 us    |          _spin_unlock_irqrestore();
  261.339788 |   1)   4.211 us    |        }
  261.339788 |   1)   5.662 us    |      }

The format is seconds.usecs
I guess no one needs the nanosec precision here, the main goal is to find when happened
the events on a cpu when the trace switches from one cpu to another.

ie:

  274.874760 |   1)   0.676 us    |      _spin_unlock();
  274.874762 |   1)   0.609 us    |      native_load_sp0();
  274.874763 |   1)   0.602 us    |      native_load_tls();
  274.878739 |   0)   0.722 us    |                  }
  274.878740 |   0)   0.714 us    |                  native_pmd_val();
  274.878741 |   0)   0.730 us    |                  native_pmd_val();

Here there is a 4000 usecs difference when we switch the cpu.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
---
 kernel/trace/trace_functions_graph.c |  245 +++++++++++++++++++++-------------
 1 files changed, 151 insertions(+), 94 deletions(-)

diff --git a/kernel/trace/trace_functions_graph.c b/kernel/trace/trace_functions_graph.c
index 3c54598..a65947c 100644
--- a/kernel/trace/trace_functions_graph.c
+++ b/kernel/trace/trace_functions_graph.c
@@ -1,7 +1,7 @@
 /*
  *
  * Function graph tracer.
- * Copyright (c) 2008 Frederic Weisbecker <fweisbec@gmail.com>
+ * Copyright (c) 2008-2009 Frederic Weisbecker <fweisbec@gmail.com>
  * Mostly borrowed from function tracer which
  * is Copyright (c) Steven Rostedt <srostedt@redhat.com>
  *
@@ -21,9 +21,11 @@
 #define TRACE_GRAPH_PRINT_CPU		0x2
 #define TRACE_GRAPH_PRINT_OVERHEAD	0x4
 #define TRACE_GRAPH_PRINT_PROC		0x8
+#define TRACE_GRAPH_PRINT_DURATION	0x10
+#define TRACE_GRAPH_PRINT_ABS_TIME	0X20
 
 static struct tracer_opt trace_opts[] = {
-	/* Display overruns ? */
+	/* Display overruns? (for self-debug purpose) */
 	{ TRACER_OPT(funcgraph-overrun, TRACE_GRAPH_PRINT_OVERRUN) },
 	/* Display CPU ? */
 	{ TRACER_OPT(funcgraph-cpu, TRACE_GRAPH_PRINT_CPU) },
@@ -31,12 +33,17 @@ static struct tracer_opt trace_opts[] = {
 	{ TRACER_OPT(funcgraph-overhead, TRACE_GRAPH_PRINT_OVERHEAD) },
 	/* Display proc name/pid */
 	{ TRACER_OPT(funcgraph-proc, TRACE_GRAPH_PRINT_PROC) },
+	/* Display duration of execution */
+	{ TRACER_OPT(funcgraph-duration, TRACE_GRAPH_PRINT_DURATION) },
+	/* Display absolute time of an entry */
+	{ TRACER_OPT(funcgraph-abstime, TRACE_GRAPH_PRINT_ABS_TIME) },
 	{ } /* Empty entry */
 };
 
 static struct tracer_flags tracer_flags = {
 	/* Don't display overruns and proc by default */
-	.val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD,
+	.val = TRACE_GRAPH_PRINT_CPU | TRACE_GRAPH_PRINT_OVERHEAD |
+	       TRACE_GRAPH_PRINT_DURATION,
 	.opts = trace_opts
 };
 
@@ -165,6 +172,8 @@ verif_pid(struct trace_seq *s, pid_t pid, int cpu)
 	prev_pid = last_pid[cpu];
 	last_pid[cpu] = pid;
 
+	if (prev_pid == -1)
+		return TRACE_TYPE_HANDLED;
 /*
  * Context-switch trace line:
 
@@ -232,9 +241,34 @@ trace_branch_is_leaf(struct trace_iterator *iter,
 	return true;
 }
 
+/* Signal a overhead of time execution to the output */
+static int
+print_graph_overhead(unsigned long long duration, struct trace_seq *s)
+{
+	/* If duration disappear, we don't need anything */
+	if (!(tracer_flags.val & TRACE_GRAPH_PRINT_DURATION))
+		return 1;
+
+	/* Non nested entry or return */
+	if (duration == -1)
+		return trace_seq_printf(s, "  ");
+
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
+		/* Duration exceeded 100 msecs */
+		if (duration > 100000ULL)
+			return trace_seq_printf(s, "! ");
+
+		/* Duration exceeded 10 msecs */
+		if (duration > 10000ULL)
+			return trace_seq_printf(s, "+ ");
+	}
+
+	return trace_seq_printf(s, "  ");
+}
+
 static enum print_line_t
 print_graph_irq(struct trace_seq *s, unsigned long addr,
-				enum trace_type type, int cpu, pid_t pid)
+		enum trace_type type, int cpu, pid_t pid)
 {
 	int ret;
 
@@ -242,35 +276,40 @@ print_graph_irq(struct trace_seq *s, unsigned long addr,
 		addr >= (unsigned long)__irqentry_text_end)
 		return TRACE_TYPE_UNHANDLED;
 
-	if (type == TRACE_GRAPH_ENT) {
-		ret = trace_seq_printf(s, "==========> |  ");
-	} else {
-		/* Cpu */
-		if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
-			ret = print_graph_cpu(s, cpu);
-			if (ret == TRACE_TYPE_PARTIAL_LINE)
-				return TRACE_TYPE_PARTIAL_LINE;
-		}
-		/* Proc */
-		if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) {
-			ret = print_graph_proc(s, pid);
-			if (ret == TRACE_TYPE_PARTIAL_LINE)
-				return TRACE_TYPE_PARTIAL_LINE;
+	/* Cpu */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
+		ret = print_graph_cpu(s, cpu);
+		if (ret == TRACE_TYPE_PARTIAL_LINE)
+			return TRACE_TYPE_PARTIAL_LINE;
+	}
+	/* Proc */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC) {
+		ret = print_graph_proc(s, pid);
+		if (ret == TRACE_TYPE_PARTIAL_LINE)
+			return TRACE_TYPE_PARTIAL_LINE;
+		ret = trace_seq_printf(s, " | ");
+		if (!ret)
+			return TRACE_TYPE_PARTIAL_LINE;
+	}
 
-			ret = trace_seq_printf(s, " | ");
-			if (!ret)
-				return TRACE_TYPE_PARTIAL_LINE;
-		}
+	/* No overhead */
+	ret = print_graph_overhead(-1, s);
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
 
-		/* No overhead */
-		if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
-			ret = trace_seq_printf(s, "  ");
-			if (!ret)
-				return TRACE_TYPE_PARTIAL_LINE;
-		}
+	if (type == TRACE_GRAPH_ENT)
+		ret = trace_seq_printf(s, "==========>");
+	else
+		ret = trace_seq_printf(s, "<==========");
+
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
+
+	/* Don't close the duration column if haven't one */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)
+		trace_seq_printf(s, " |");
+	ret = trace_seq_printf(s, "\n");
 
-		ret = trace_seq_printf(s, "<========== |\n");
-	}
 	if (!ret)
 		return TRACE_TYPE_PARTIAL_LINE;
 	return TRACE_TYPE_HANDLED;
@@ -289,7 +328,7 @@ print_graph_duration(unsigned long long duration, struct trace_seq *s)
 	sprintf(msecs_str, "%lu", (unsigned long) duration);
 
 	/* Print msecs */
-	ret = trace_seq_printf(s, msecs_str);
+	ret = trace_seq_printf(s, "%s", msecs_str);
 	if (!ret)
 		return TRACE_TYPE_PARTIAL_LINE;
 
@@ -322,19 +361,15 @@ print_graph_duration(unsigned long long duration, struct trace_seq *s)
 
 }
 
-/* Signal a overhead of time execution to the output */
-static int
-print_graph_overhead(unsigned long long duration, struct trace_seq *s)
+static int print_graph_abs_time(u64 t, struct trace_seq *s)
 {
-	/* Duration exceeded 100 msecs */
-	if (duration > 100000ULL)
-		return trace_seq_printf(s, "! ");
+	unsigned long usecs_rem;
 
-	/* Duration exceeded 10 msecs */
-	if (duration > 10000ULL)
-		return trace_seq_printf(s, "+ ");
+	usecs_rem = do_div(t, 1000000000);
+	usecs_rem /= 1000;
 
-	return trace_seq_printf(s, "  ");
+	return trace_seq_printf(s, "%5lu.%06lu |  ",
+			(unsigned long)t, usecs_rem);
 }
 
 /* Case of a leaf function on its call entry */
@@ -357,16 +392,16 @@ print_graph_entry_leaf(struct trace_iterator *iter,
 	duration = graph_ret->rettime - graph_ret->calltime;
 
 	/* Overhead */
-	if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
-		ret = print_graph_overhead(duration, s);
-		if (!ret)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
+	ret = print_graph_overhead(duration, s);
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
 
 	/* Duration */
-	ret = print_graph_duration(duration, s);
-	if (ret == TRACE_TYPE_PARTIAL_LINE)
-		return TRACE_TYPE_PARTIAL_LINE;
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
+		ret = print_graph_duration(duration, s);
+		if (ret == TRACE_TYPE_PARTIAL_LINE)
+			return TRACE_TYPE_PARTIAL_LINE;
+	}
 
 	/* Function */
 	for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
@@ -395,25 +430,17 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry,
 	struct ftrace_graph_ent *call = &entry->graph_ent;
 
 	/* No overhead */
-	if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
-		ret = trace_seq_printf(s, "  ");
-		if (!ret)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
+	ret = print_graph_overhead(-1, s);
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
 
-	/* Interrupt */
-	ret = print_graph_irq(s, call->func, TRACE_GRAPH_ENT, cpu, pid);
-	if (ret == TRACE_TYPE_UNHANDLED) {
-		/* No time */
+	/* No time */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
 		ret = trace_seq_printf(s, "            |  ");
 		if (!ret)
 			return TRACE_TYPE_PARTIAL_LINE;
-	} else {
-		if (ret == TRACE_TYPE_PARTIAL_LINE)
-			return TRACE_TYPE_PARTIAL_LINE;
 	}
 
-
 	/* Function */
 	for (i = 0; i < call->depth * TRACE_GRAPH_INDENT; i++) {
 		ret = trace_seq_printf(s, " ");
@@ -434,15 +461,29 @@ print_graph_entry_nested(struct ftrace_graph_ent_entry *entry,
 
 static enum print_line_t
 print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
-			struct trace_iterator *iter, int cpu)
+			struct trace_iterator *iter)
 {
 	int ret;
+	int cpu = iter->cpu;
 	struct trace_entry *ent = iter->ent;
+	struct ftrace_graph_ent *call = &field->graph_ent;
 
 	/* Pid */
 	if (verif_pid(s, ent->pid, cpu) == TRACE_TYPE_PARTIAL_LINE)
 		return TRACE_TYPE_PARTIAL_LINE;
 
+	/* Interrupt */
+	ret = print_graph_irq(s, call->func, TRACE_GRAPH_ENT, cpu, ent->pid);
+	if (ret == TRACE_TYPE_PARTIAL_LINE)
+		return TRACE_TYPE_PARTIAL_LINE;
+
+	/* Absolute time */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) {
+		ret = print_graph_abs_time(iter->ts, s);
+		if (!ret)
+			return TRACE_TYPE_PARTIAL_LINE;
+	}
+
 	/* Cpu */
 	if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
 		ret = print_graph_cpu(s, cpu);
@@ -470,16 +511,24 @@ print_graph_entry(struct ftrace_graph_ent_entry *field, struct trace_seq *s,
 
 static enum print_line_t
 print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
-		   struct trace_entry *ent, int cpu)
+		   struct trace_entry *ent, struct trace_iterator *iter)
 {
 	int i;
 	int ret;
+	int cpu = iter->cpu;
 	unsigned long long duration = trace->rettime - trace->calltime;
 
 	/* Pid */
 	if (verif_pid(s, ent->pid, cpu) == TRACE_TYPE_PARTIAL_LINE)
 		return TRACE_TYPE_PARTIAL_LINE;
 
+	/* Absolute time */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) {
+		ret = print_graph_abs_time(iter->ts, s);
+		if (!ret)
+			return TRACE_TYPE_PARTIAL_LINE;
+	}
+
 	/* Cpu */
 	if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU) {
 		ret = print_graph_cpu(s, cpu);
@@ -499,16 +548,16 @@ print_graph_return(struct ftrace_graph_ret *trace, struct trace_seq *s,
 	}
 
 	/* Overhead */
-	if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
-		ret = print_graph_overhead(duration, s);
-		if (!ret)
-			return TRACE_TYPE_PARTIAL_LINE;
-	}
+	ret = print_graph_overhead(duration, s);
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
 
 	/* Duration */
-	ret = print_graph_duration(duration, s);
-	if (ret == TRACE_TYPE_PARTIAL_LINE)
-		return TRACE_TYPE_PARTIAL_LINE;
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
+		ret = print_graph_duration(duration, s);
+		if (ret == TRACE_TYPE_PARTIAL_LINE)
+			return TRACE_TYPE_PARTIAL_LINE;
+	}
 
 	/* Closing brace */
 	for (i = 0; i < trace->depth * TRACE_GRAPH_INDENT; i++) {
@@ -543,6 +592,13 @@ print_graph_comment(struct print_entry *trace, struct trace_seq *s,
 	int i;
 	int ret;
 
+	/* Absolute time */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME) {
+		ret = print_graph_abs_time(iter->ts, s);
+		if (!ret)
+			return TRACE_TYPE_PARTIAL_LINE;
+	}
+
 	/* Pid */
 	if (verif_pid(s, ent->pid, iter->cpu) == TRACE_TYPE_PARTIAL_LINE)
 		return TRACE_TYPE_PARTIAL_LINE;
@@ -566,17 +622,17 @@ print_graph_comment(struct print_entry *trace, struct trace_seq *s,
 	}
 
 	/* No overhead */
-	if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
-		ret = trace_seq_printf(s, "  ");
+	ret = print_graph_overhead(-1, s);
+	if (!ret)
+		return TRACE_TYPE_PARTIAL_LINE;
+
+	/* No time */
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION) {
+		ret = trace_seq_printf(s, "            |  ");
 		if (!ret)
 			return TRACE_TYPE_PARTIAL_LINE;
 	}
 
-	/* No time */
-	ret = trace_seq_printf(s, "            |  ");
-	if (!ret)
-		return TRACE_TYPE_PARTIAL_LINE;
-
 	/* Indentation */
 	if (trace->depth > 0)
 		for (i = 0; i < (trace->depth + 1) * TRACE_GRAPH_INDENT; i++) {
@@ -614,13 +670,12 @@ print_graph_function(struct trace_iterator *iter)
 	case TRACE_GRAPH_ENT: {
 		struct ftrace_graph_ent_entry *field;
 		trace_assign_type(field, entry);
-		return print_graph_entry(field, s, iter,
-					 iter->cpu);
+		return print_graph_entry(field, s, iter);
 	}
 	case TRACE_GRAPH_RET: {
 		struct ftrace_graph_ret_entry *field;
 		trace_assign_type(field, entry);
-		return print_graph_return(&field->ret, s, entry, iter->cpu);
+		return print_graph_return(&field->ret, s, entry, iter);
 	}
 	case TRACE_PRINT: {
 		struct print_entry *field;
@@ -636,25 +691,27 @@ static void print_graph_headers(struct seq_file *s)
 {
 	/* 1st line */
 	seq_printf(s, "# ");
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME)
+		seq_printf(s, "     TIME       ");
 	if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU)
-		seq_printf(s, "CPU ");
+		seq_printf(s, "CPU");
 	if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC)
-		seq_printf(s, "TASK/PID     ");
-	if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD)
-		seq_printf(s, "OVERHEAD/");
-	seq_printf(s, "DURATION            FUNCTION CALLS\n");
+		seq_printf(s, "  TASK/PID      ");
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)
+		seq_printf(s, "  DURATION   ");
+	seq_printf(s, "               FUNCTION CALLS\n");
 
 	/* 2nd line */
 	seq_printf(s, "# ");
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_ABS_TIME)
+		seq_printf(s, "      |         ");
 	if (tracer_flags.val & TRACE_GRAPH_PRINT_CPU)
-		seq_printf(s, "|   ");
+		seq_printf(s, "|  ");
 	if (tracer_flags.val & TRACE_GRAPH_PRINT_PROC)
-		seq_printf(s, "|      |     ");
-	if (tracer_flags.val & TRACE_GRAPH_PRINT_OVERHEAD) {
-		seq_printf(s, "|        ");
-		seq_printf(s, "|                   |   |   |   |\n");
-	} else
-		seq_printf(s, "    |               |   |   |   |\n");
+		seq_printf(s, "  |    |        ");
+	if (tracer_flags.val & TRACE_GRAPH_PRINT_DURATION)
+		seq_printf(s, "   |   |      ");
+	seq_printf(s, "               |   |   |   |\n");
 }
 static struct tracer graph_trace __read_mostly = {
 	.name	     	= "function_graph",
-- 
1.6.0.4



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] tracing/function-graph-tracer: various fixes and features
  2009-01-22  1:24 [PATCH 1/2] tracing/function-graph-tracer: various fixes and features Frederic Weisbecker
@ 2009-01-22  1:43 ` Steven Rostedt
  2009-01-22  9:02   ` Frederic Weisbecker
  2009-01-22  9:33   ` Ingo Molnar
  0 siblings, 2 replies; 4+ messages in thread
From: Steven Rostedt @ 2009-01-22  1:43 UTC (permalink / raw)
  To: Frederic Weisbecker; +Cc: Ingo Molnar, Linux Kernel Mailing List


On Wed, 21 Jan 2009, Frederic Weisbecker wrote:

> I thought I would have the time to implement the callbacks in trace_event too but I
> really have to sleep :-(
> That will be for later.

No need to rush. Get to sleep.

> --
> 
> This patch brings various bugfixes:
> 
> _ Drop the first irrelevant task switch on the very beginning of a trace.
>   But actually that only solves the first time one does print the trace file.
>   I have to fix the others cases too.

I'm not sure what you mean by the first time here. Can you explain it
a bit better.

> _ Drop the OVERHEAD word from the headers, the DURATION word is sufficient and will not
>   overlap other columns.
> _ Make the headers fit well their respective columns whatever the selected options.
> 
> Ie, default options:
> 
> # tracer: function_graph
> #
> # CPU  DURATION                  FUNCTION CALLS
> # |     |   |                     |   |   |   |
> 
>  1)   0.646 us    |                    }
>  1)               |                    mem_cgroup_del_lru_list() {
>  1)   0.624 us    |                      lookup_page_cgroup();
>  1)   1.970 us    |                    }
> 
> echo funcgraph-proc > trace_options
> 
> # tracer: function_graph
> #
> # CPU  TASK/PID        DURATION                  FUNCTION CALLS
> # |    |    |           |   |                     |   |   |   |
> 
>  0)   bash-2937    |   0.895 us    |                }
>  0)   bash-2937    |   0.888 us    |                __rcu_read_unlock();
>  0)   bash-2937    |   0.864 us    |                conv_uni_to_pc();
>  0)   bash-2937    |   1.015 us    |                __rcu_read_lock();
> 
> echo nofuncgraph-cpu > trace_options
> echo nofuncgraph-proc > trace_options
> 
> # tracer: function_graph
> #
> #   DURATION                  FUNCTION CALLS
> #    |   |                     |   |   |   |
> 
>   3.752 us    |                  native_pud_val();
>   0.616 us    |                  native_pud_val();
>   0.624 us    |                  native_pmd_val();
> 
> 
> About features, one can now disable the duration (this will hide the overhead too
> for convenient reasons and because on  doesn't need overhead if it hasn't the duration
> 
> echo nofuncgraph-duration > trace_options
> 
> # tracer: function_graph
> #
> #                FUNCTION CALLS
> #                |   |   |   |
> 
>           cap_vm_enough_memory() {
>             __vm_enough_memory() {
>               vm_acct_memory();
>             }
>           }
>         }
> 
> And at last, an option to print the absolute time:
> 
> //Restart from default options
> echo funcgraph-abstime > trace_options
> 
> # tracer: function_graph
> #
> #      TIME       CPU  DURATION                  FUNCTION CALLS
> #       |         |     |   |                     |   |   |   |
> 
>   261.339774 |   1) + 42.823 us   |    }
>   261.339775 |   1)   1.045 us    |    _spin_lock_irq();
>   261.339777 |   1)   0.940 us    |    _spin_lock_irqsave();
>   261.339778 |   1)   0.752 us    |    _spin_unlock_irqrestore();
>   261.339780 |   1)   0.857 us    |    _spin_unlock_irq();
>   261.339782 |   1)               |    flush_to_ldisc() {
>   261.339783 |   1)               |      tty_ldisc_ref() {
>   261.339783 |   1)               |        tty_ldisc_try() {
>   261.339784 |   1)   1.075 us    |          _spin_lock_irqsave();
>   261.339786 |   1)   0.842 us    |          _spin_unlock_irqrestore();
>   261.339788 |   1)   4.211 us    |        }
>   261.339788 |   1)   5.662 us    |      }
> 
> The format is seconds.usecs
> I guess no one needs the nanosec precision here, the main goal is to find when happened
> the events on a cpu when the trace switches from one cpu to another.
> 
> ie:
> 
>   274.874760 |   1)   0.676 us    |      _spin_unlock();
>   274.874762 |   1)   0.609 us    |      native_load_sp0();
>   274.874763 |   1)   0.602 us    |      native_load_tls();
>   274.878739 |   0)   0.722 us    |                  }
>   274.878740 |   0)   0.714 us    |                  native_pmd_val();
>   274.878741 |   0)   0.730 us    |                  native_pmd_val();
> 
> Here there is a 4000 usecs difference when we switch the cpu.

These examples will most likely be cut from the change log. Updating
ftrace.txt would be nice ;-)

> 
> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
> ---
>  kernel/trace/trace_functions_graph.c |  245 +++++++++++++++++++++-------------
>  1 files changed, 151 insertions(+), 94 deletions(-)
> 

-- Steve


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] tracing/function-graph-tracer: various fixes and features
  2009-01-22  1:43 ` Steven Rostedt
@ 2009-01-22  9:02   ` Frederic Weisbecker
  2009-01-22  9:33   ` Ingo Molnar
  1 sibling, 0 replies; 4+ messages in thread
From: Frederic Weisbecker @ 2009-01-22  9:02 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Ingo Molnar, Linux Kernel Mailing List

On Wed, Jan 21, 2009 at 08:43:24PM -0500, Steven Rostedt wrote:
> 
> On Wed, 21 Jan 2009, Frederic Weisbecker wrote:
> 
> > I thought I would have the time to implement the callbacks in trace_event too but I
> > really have to sleep :-(
> > That will be for later.
> 
> No need to rush. Get to sleep.
> 
> > --
> > 
> > This patch brings various bugfixes:
> > 
> > _ Drop the first irrelevant task switch on the very beginning of a trace.
> >   But actually that only solves the first time one does print the trace file.
> >   I have to fix the others cases too.
> 
> I'm not sure what you mean by the first time here. Can you explain it
> a bit better.


On the very first time one cat the trace file, the per cpu pid array is init to -1.
So the comparison between the current pid and the previous one (-1) is always false
and then a task switch is printed.
This one is fixed.

The other cases are when one cat the trace file after closing it.
The pid array is not anymore filled with -1 values but with old traced pid, and then
a task switch is printed here too.
I will have to hook on open and reset the pid table to -1 to fix that.

 
> > _ Drop the OVERHEAD word from the headers, the DURATION word is sufficient and will not
> >   overlap other columns.
> > _ Make the headers fit well their respective columns whatever the selected options.
> > 
> > Ie, default options:
> > 
> > # tracer: function_graph
> > #
> > # CPU  DURATION                  FUNCTION CALLS
> > # |     |   |                     |   |   |   |
> > 
> >  1)   0.646 us    |                    }
> >  1)               |                    mem_cgroup_del_lru_list() {
> >  1)   0.624 us    |                      lookup_page_cgroup();
> >  1)   1.970 us    |                    }
> > 
> > echo funcgraph-proc > trace_options
> > 
> > # tracer: function_graph
> > #
> > # CPU  TASK/PID        DURATION                  FUNCTION CALLS
> > # |    |    |           |   |                     |   |   |   |
> > 
> >  0)   bash-2937    |   0.895 us    |                }
> >  0)   bash-2937    |   0.888 us    |                __rcu_read_unlock();
> >  0)   bash-2937    |   0.864 us    |                conv_uni_to_pc();
> >  0)   bash-2937    |   1.015 us    |                __rcu_read_lock();
> > 
> > echo nofuncgraph-cpu > trace_options
> > echo nofuncgraph-proc > trace_options
> > 
> > # tracer: function_graph
> > #
> > #   DURATION                  FUNCTION CALLS
> > #    |   |                     |   |   |   |
> > 
> >   3.752 us    |                  native_pud_val();
> >   0.616 us    |                  native_pud_val();
> >   0.624 us    |                  native_pmd_val();
> > 
> > 
> > About features, one can now disable the duration (this will hide the overhead too
> > for convenient reasons and because on  doesn't need overhead if it hasn't the duration
> > 
> > echo nofuncgraph-duration > trace_options
> > 
> > # tracer: function_graph
> > #
> > #                FUNCTION CALLS
> > #                |   |   |   |
> > 
> >           cap_vm_enough_memory() {
> >             __vm_enough_memory() {
> >               vm_acct_memory();
> >             }
> >           }
> >         }
> > 
> > And at last, an option to print the absolute time:
> > 
> > //Restart from default options
> > echo funcgraph-abstime > trace_options
> > 
> > # tracer: function_graph
> > #
> > #      TIME       CPU  DURATION                  FUNCTION CALLS
> > #       |         |     |   |                     |   |   |   |
> > 
> >   261.339774 |   1) + 42.823 us   |    }
> >   261.339775 |   1)   1.045 us    |    _spin_lock_irq();
> >   261.339777 |   1)   0.940 us    |    _spin_lock_irqsave();
> >   261.339778 |   1)   0.752 us    |    _spin_unlock_irqrestore();
> >   261.339780 |   1)   0.857 us    |    _spin_unlock_irq();
> >   261.339782 |   1)               |    flush_to_ldisc() {
> >   261.339783 |   1)               |      tty_ldisc_ref() {
> >   261.339783 |   1)               |        tty_ldisc_try() {
> >   261.339784 |   1)   1.075 us    |          _spin_lock_irqsave();
> >   261.339786 |   1)   0.842 us    |          _spin_unlock_irqrestore();
> >   261.339788 |   1)   4.211 us    |        }
> >   261.339788 |   1)   5.662 us    |      }
> > 
> > The format is seconds.usecs
> > I guess no one needs the nanosec precision here, the main goal is to find when happened
> > the events on a cpu when the trace switches from one cpu to another.
> > 
> > ie:
> > 
> >   274.874760 |   1)   0.676 us    |      _spin_unlock();
> >   274.874762 |   1)   0.609 us    |      native_load_sp0();
> >   274.874763 |   1)   0.602 us    |      native_load_tls();
> >   274.878739 |   0)   0.722 us    |                  }
> >   274.878740 |   0)   0.714 us    |                  native_pmd_val();
> >   274.878741 |   0)   0.730 us    |                  native_pmd_val();
> > 
> > Here there is a 4000 usecs difference when we switch the cpu.
> 
> These examples will most likely be cut from the change log. Updating
> ftrace.txt would be nice ;-)


Yes, definetly. I didn't drop my hands into this yet because of my
messy english :-)
But I know some people who could review it :-)


> > 
> > Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
> > ---
> >  kernel/trace/trace_functions_graph.c |  245 +++++++++++++++++++++-------------
> >  1 files changed, 151 insertions(+), 94 deletions(-)
> > 
> 
> -- Steve
> 

Thanks.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 1/2] tracing/function-graph-tracer: various fixes and features
  2009-01-22  1:43 ` Steven Rostedt
  2009-01-22  9:02   ` Frederic Weisbecker
@ 2009-01-22  9:33   ` Ingo Molnar
  1 sibling, 0 replies; 4+ messages in thread
From: Ingo Molnar @ 2009-01-22  9:33 UTC (permalink / raw)
  To: Steven Rostedt; +Cc: Frederic Weisbecker, Linux Kernel Mailing List


* Steven Rostedt <rostedt@goodmis.org> wrote:

> 
> On Wed, 21 Jan 2009, Frederic Weisbecker wrote:
> 
> > I thought I would have the time to implement the callbacks in trace_event too but I
> > really have to sleep :-(
> > That will be for later.
> 
> No need to rush. Get to sleep.
> 
> > --
> > 
> > This patch brings various bugfixes:
> > 
> > _ Drop the first irrelevant task switch on the very beginning of a trace.
> >   But actually that only solves the first time one does print the trace file.
> >   I have to fix the others cases too.
> 
> I'm not sure what you mean by the first time here. Can you explain it
> a bit better.
> 
> > _ Drop the OVERHEAD word from the headers, the DURATION word is sufficient and will not
> >   overlap other columns.
> > _ Make the headers fit well their respective columns whatever the selected options.
> > 
> > Ie, default options:
> > 
> > # tracer: function_graph
> > #
> > # CPU  DURATION                  FUNCTION CALLS
> > # |     |   |                     |   |   |   |
> > 
> >  1)   0.646 us    |                    }
> >  1)               |                    mem_cgroup_del_lru_list() {
> >  1)   0.624 us    |                      lookup_page_cgroup();
> >  1)   1.970 us    |                    }
> > 
> > echo funcgraph-proc > trace_options
> > 
> > # tracer: function_graph
> > #
> > # CPU  TASK/PID        DURATION                  FUNCTION CALLS
> > # |    |    |           |   |                     |   |   |   |
> > 
> >  0)   bash-2937    |   0.895 us    |                }
> >  0)   bash-2937    |   0.888 us    |                __rcu_read_unlock();
> >  0)   bash-2937    |   0.864 us    |                conv_uni_to_pc();
> >  0)   bash-2937    |   1.015 us    |                __rcu_read_lock();
> > 
> > echo nofuncgraph-cpu > trace_options
> > echo nofuncgraph-proc > trace_options
> > 
> > # tracer: function_graph
> > #
> > #   DURATION                  FUNCTION CALLS
> > #    |   |                     |   |   |   |
> > 
> >   3.752 us    |                  native_pud_val();
> >   0.616 us    |                  native_pud_val();
> >   0.624 us    |                  native_pmd_val();
> > 
> > 
> > About features, one can now disable the duration (this will hide the overhead too
> > for convenient reasons and because on  doesn't need overhead if it hasn't the duration
> > 
> > echo nofuncgraph-duration > trace_options
> > 
> > # tracer: function_graph
> > #
> > #                FUNCTION CALLS
> > #                |   |   |   |
> > 
> >           cap_vm_enough_memory() {
> >             __vm_enough_memory() {
> >               vm_acct_memory();
> >             }
> >           }
> >         }
> > 
> > And at last, an option to print the absolute time:
> > 
> > //Restart from default options
> > echo funcgraph-abstime > trace_options
> > 
> > # tracer: function_graph
> > #
> > #      TIME       CPU  DURATION                  FUNCTION CALLS
> > #       |         |     |   |                     |   |   |   |
> > 
> >   261.339774 |   1) + 42.823 us   |    }
> >   261.339775 |   1)   1.045 us    |    _spin_lock_irq();
> >   261.339777 |   1)   0.940 us    |    _spin_lock_irqsave();
> >   261.339778 |   1)   0.752 us    |    _spin_unlock_irqrestore();
> >   261.339780 |   1)   0.857 us    |    _spin_unlock_irq();
> >   261.339782 |   1)               |    flush_to_ldisc() {
> >   261.339783 |   1)               |      tty_ldisc_ref() {
> >   261.339783 |   1)               |        tty_ldisc_try() {
> >   261.339784 |   1)   1.075 us    |          _spin_lock_irqsave();
> >   261.339786 |   1)   0.842 us    |          _spin_unlock_irqrestore();
> >   261.339788 |   1)   4.211 us    |        }
> >   261.339788 |   1)   5.662 us    |      }
> > 
> > The format is seconds.usecs
> > I guess no one needs the nanosec precision here, the main goal is to find when happened
> > the events on a cpu when the trace switches from one cpu to another.
> > 
> > ie:
> > 
> >   274.874760 |   1)   0.676 us    |      _spin_unlock();
> >   274.874762 |   1)   0.609 us    |      native_load_sp0();
> >   274.874763 |   1)   0.602 us    |      native_load_tls();
> >   274.878739 |   0)   0.722 us    |                  }
> >   274.878740 |   0)   0.714 us    |                  native_pmd_val();
> >   274.878741 |   0)   0.730 us    |                  native_pmd_val();
> > 
> > Here there is a 4000 usecs difference when we switch the cpu.
> 
> These examples will most likely be cut from the change log. Updating
> ftrace.txt would be nice ;-)

Updating ftrace.txt is definitely a good idea, but also, please dont cut 
such examples from changelogs ... i keep them most of the time, they are 
really useful.

	Ingo

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-01-22  9:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-22  1:24 [PATCH 1/2] tracing/function-graph-tracer: various fixes and features Frederic Weisbecker
2009-01-22  1:43 ` Steven Rostedt
2009-01-22  9:02   ` Frederic Weisbecker
2009-01-22  9:33   ` Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox