linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Frederic Weisbecker <fweisbec@gmail.com>
To: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Zhaolei <zhaolei@cn.fujitsu.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Tom Zanussi <tzanussi@gmail.com>, Ingo Molnar <mingo@elte.hu>,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2 3/4] ftrace: add max execution time mesurement to workqueue tracer
Date: Mon, 13 Apr 2009 18:16:51 +0200	[thread overview]
Message-ID: <20090413161649.GH5977@nowhere> (raw)
In-Reply-To: <20090413145254.6E0D.A69D9226@jp.fujitsu.com>

On Mon, Apr 13, 2009 at 02:53:45PM +0900, KOSAKI Motohiro wrote:
> Subject: [PATCH] ftrace: add max execution time mesurement to workqueue tracer
> 
> Too slow workqueue handler often introduce some trouble to system.
> Then, administrator want to know may handler execution time.
> 
> 
> Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
> Cc: Zhaolei <zhaolei@cn.fujitsu.com>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> Cc: Frederic Weisbecker <fweisbec@gmail.com>
> Cc: Tom Zanussi <tzanussi@gmail.com>
> Cc: Ingo Molnar <mingo@elte.hu>
> ---
>  kernel/trace/trace_workqueue.c |   48 +++++++++++++++++++++++++++++++++++++----
>  1 file changed, 44 insertions(+), 4 deletions(-)
> 
> Index: b/kernel/trace/trace_workqueue.c
> ===================================================================
> --- a/kernel/trace/trace_workqueue.c	2009-04-13 13:23:59.000000000 +0900
> +++ b/kernel/trace/trace_workqueue.c	2009-04-13 13:59:51.000000000 +0900
> @@ -27,6 +27,10 @@ struct cpu_workqueue_stats {
>   *  on a single CPU.
>   */
>  	unsigned int		    executed;
> +
> +	/* store handler execution time */
> +	u64			    handler_start_time;
> +	u64			    max_executed_time;
>  };



Imho, this is the wrong place to instrument.
I explain my point of view below.



>  /* List of workqueue threads on one cpu */
> @@ -77,6 +81,7 @@ probe_workqueue_entry(struct task_struct
>  							list) {
>  		if (node->pid == wq_thread->pid) {
>  			node->executed++;
> +			node->handler_start_time = trace_clock_global();
>  			goto found;
>  		}
>  	}
> @@ -85,6 +90,29 @@ found:
>  	spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
>  }
>  
> +static void probe_workqueue_exit(struct task_struct *wq_thread,
> +				 struct work_struct *work)
> +{
> +	int cpu = cpumask_first(&wq_thread->cpus_allowed);
> +	struct cpu_workqueue_stats *node, *next;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
> +	list_for_each_entry_safe(node, next, &workqueue_cpu_stat(cpu)->list,
> +							list) {


Do you need the safe version here? You don't seem to remove any entry.

Sidenote: only the workqueue destruction handler might need it if I'm
not wrong.
I placed some of them in other places in this file because I misunderstood the
kernel list concepts in the past :)
(Heh, and probably still today).



> +		if (node->pid == wq_thread->pid) {
> +			u64 start = node->handler_start_time;
> +			u64 executed_time = trace_clock_global() - start;
> +
> +			if (node->max_executed_time < executed_time)
> +				node->max_executed_time = executed_time;
> +			goto found;
> +		}
> +	}
> +found:
> +	spin_unlock_irqrestore(&workqueue_cpu_stat(cpu)->lock, flags);
> +}
> +
>  /* Creation of a cpu workqueue thread */
>  static void probe_workqueue_creation(struct task_struct *wq_thread, int cpu)
>  {
> @@ -195,6 +223,9 @@ static int workqueue_stat_show(struct se
>  	int cpu = cws->cpu;
>  	struct pid *pid;
>  	struct task_struct *tsk;
> +	unsigned long long exec_time = ns2usecs(cws->max_executed_time);
> +	unsigned long exec_usec_rem = do_div(exec_time, USEC_PER_SEC);
> +	unsigned long exec_secs = (unsigned long)exec_time;
>  
>  	spin_lock_irqsave(&workqueue_cpu_stat(cpu)->lock, flags);
>  	if (&cws->list == workqueue_cpu_stat(cpu)->list.next)
> @@ -205,8 +236,11 @@ static int workqueue_stat_show(struct se
>  	if (pid) {
>  		tsk = get_pid_task(pid, PIDTYPE_PID);
>  		if (tsk) {
> -			seq_printf(s, "%3d %6d     %6u       %s\n", cws->cpu,
> +			seq_printf(s, "%3d %6d     %6u     %5lu.%06lu"
> +				   "  %s\n",
> +				   cws->cpu,
>  				   atomic_read(&cws->inserted), cws->executed,
> +				   exec_secs, exec_usec_rem,




You are measuring the latency from a workqueue thread point of view.
While I find the work latency measurement very interesting,
I think this patch does it in the wrong place. The _work_ latency point of view
seems to me much more rich as an information source.

There are several reasons for that.

Indeed this patch is useful for workqueues that receive always the same work
to perform so that you can find very easily the guilty worklet.
But the sense of this design is lost once we consider the workqueue threads
that receive random works. Of course the best example is events/%d
One will observe the max latency that happened on event/0 as an exemple but
he will only be able to feel a silent FUD because he has no way to find
which work caused this max latency.


Especially the events/%d latency measurement seems to me very important
because a single work from a random driver can propagate its latency
all over the system.

A single work that consumes too much cpu time, waits for long coming
events, sleeps too much, tries to take too often contended locks, or
whatever... such single work may delay all pending works in the queue
and the only max latency for a given workqueue is not helpful to find
these culprits.

Having this max latency snapshot per work and not per workqueue thread
would be useful for every kind of workqueue latency instrumentation:

- workqueues with single works
- workqueue with random works

A developer will also be able to measure its own worklet action and
find if it takes too much time, even if it isn't the worst worklet in
the workqueue to cause latencies.

The end result would be to have a descending latency sort of works
per cpu workqueue threads (or better: per workqueue group).

What do you think?

Frederic.



>  				   tsk->comm);
>  			put_task_struct(tsk);
>  		}
> @@ -218,8 +252,8 @@ static int workqueue_stat_show(struct se
>  
>  static int workqueue_stat_headers(struct seq_file *s)
>  {
> -	seq_printf(s, "# CPU  INSERTED  EXECUTED   NAME\n");
> -	seq_printf(s, "# |      |         |          |\n");
> +	seq_printf(s, "# CPU  INSERTED  EXECUTED     MAX_TIME  NAME\n");
> +	seq_printf(s, "# |      |         |           |         |\n");
>  	return 0;
>  }
>  
> @@ -259,10 +293,14 @@ int __init trace_workqueue_early_init(vo
>  	if (ret)
>  		goto no_insertion;
>  
> -	ret = register_trace_workqueue_creation(probe_workqueue_creation);
> +	ret = register_trace_workqueue_handler_exit(probe_workqueue_exit);
>  	if (ret)
>  		goto no_handler_entry;
>  
> +	ret = register_trace_workqueue_creation(probe_workqueue_creation);
> +	if (ret)
> +		goto no_handler_exit;
> +
>  	ret = register_trace_workqueue_destruction(probe_workqueue_destruction);
>  	if (ret)
>  		goto no_creation;
> @@ -276,6 +314,8 @@ int __init trace_workqueue_early_init(vo
>  
>  no_creation:
>  	unregister_trace_workqueue_creation(probe_workqueue_creation);
> +no_handler_exit:
> +	unregister_trace_workqueue_handler_exit(probe_workqueue_exit);
>  no_handler_entry:
>  	unregister_trace_workqueue_handler_entry(probe_workqueue_entry);
>  no_insertion:
> 
> 


  reply	other threads:[~2009-04-13 16:17 UTC|newest]

Thread overview: 94+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-13  0:53 [PATCH 0/1] tracing, workqueuetrace: Make workqueue tracepoints use TRACE_EVENT macro Zhaolei
2009-04-13  0:54 ` [PATCH 1/1] " Zhaolei
2009-04-13  1:44   ` KOSAKI Motohiro
2009-04-13  3:25     ` KOSAKI Motohiro
2009-04-13  3:49       ` Zhaolei
2009-04-13  3:57         ` Ingo Molnar
2009-04-13  4:07           ` Re: [PATCH 1/1] tracing, workqueuetrace: Make workqueuetracepoints " Zhaolei
2009-04-13  3:57         ` [PATCH 1/1] tracing, workqueuetrace: Make workqueue tracepoints " KOSAKI Motohiro
2009-04-13  5:52           ` [PATCH v2 1/4] ftrace, " KOSAKI Motohiro
2009-04-13  5:53             ` [PATCH v2 2/4] ftrace: introduce workqueue_handler_exit tracepoint and rename workqueue_execution to workqueue_handler_entry KOSAKI Motohiro
2009-04-13 16:25               ` Frederic Weisbecker
2009-04-15 10:22                 ` Oleg Nesterov
2009-04-15 11:09                   ` Ingo Molnar
2009-04-15 11:33                     ` Oleg Nesterov
2009-04-15 11:45                       ` Ingo Molnar
2009-04-15 12:05                         ` Oleg Nesterov
2009-04-13  5:53             ` [PATCH v2 3/4] ftrace: add max execution time mesurement to workqueue tracer KOSAKI Motohiro
2009-04-13 16:16               ` Frederic Weisbecker [this message]
2009-04-13 21:21                 ` Ingo Molnar
2009-04-14  1:43                 ` KOSAKI Motohiro
2009-04-14 11:40                   ` Frederic Weisbecker
2009-04-15  0:31                     ` KOSAKI Motohiro
2009-04-13  5:55             ` [PATCH v2 4/4] ftrace: add latecy mesurement feature " KOSAKI Motohiro
2009-04-14  2:50               ` KOSAKI Motohiro
2009-04-13 15:24             ` [PATCH v2 1/4] ftrace, workqueuetrace: Make workqueue tracepoints use TRACE_EVENT macro Frederic Weisbecker
2009-04-14  4:03             ` [PATCH v2 5/4] ftrace, workqueuetrace: display work name KOSAKI Motohiro
2009-04-14 21:16               ` Frederic Weisbecker
2009-04-14 23:55                 ` KOSAKI Motohiro
2009-04-15  1:15                   ` Frederic Weisbecker
2009-04-15  6:13                     ` KOSAKI Motohiro
2009-04-15  6:17                       ` Zhaolei
2009-04-15  9:44                       ` Ingo Molnar
2009-04-15 16:23                       ` Frederic Weisbecker
2009-04-17  6:56                       ` [PATCH v3 0/1] ftrace, workqueuetrace: Make workqueue tracepoints use TRACE_EVENT macro Zhaolei
2009-04-17  7:15                         ` [PATCH v3 1/1] " Zhaolei
2009-04-17 13:45                           ` Ingo Molnar
2009-04-20  1:30                             ` [PATCH v3 1/1] ftrace, workqueuetrace: Make workqueuetracepoints " Zhaolei
2009-04-20  1:38                               ` KOSAKI Motohiro
2009-04-20  1:43                                 ` Zhaolei
2009-04-20  1:49                                   ` KOSAKI Motohiro
2009-04-20  8:46                                     ` Ingo Molnar
2009-04-20 22:25                                       ` Oleg Nesterov
2009-04-20 23:48                                         ` Frederic Weisbecker
2009-04-21 15:28                                           ` Oleg Nesterov
2009-04-21 15:50                                             ` Oleg Nesterov
2009-04-21 18:33                                               ` Frederic Weisbecker
2009-04-21 18:28                                             ` Frederic Weisbecker
2009-04-21 19:37                                               ` Oleg Nesterov
2009-04-24 11:42                             ` [PATCH 0/4] workqueue_tracepoint: Add worklet tracepoints for worklet lifecycle tracing Zhaolei
2009-04-24 11:43                               ` [PATCH 1/4] workqueue_tracepoint: introduce workqueue_handler_exit tracepoint and rename workqueue_execution to workqueue_handler_entry Zhaolei
2009-04-24 11:45                               ` [PATCH 2/4] workqueue_tracepoint: Add workqueue_flush and worklet_cancel tracepoint Zhaolei
2009-04-24 11:45                               ` [PATCH 3/4] workqueue_tracepoint: Change tracepoint name to fit worklet and workqueue lifecycle Zhaolei
2009-04-24 11:46                               ` [PATCH 4/4] workqueue_trace: Separate worklet_insertion into worklet_enqueue and worklet_enqueue_delayed Zhaolei
2009-04-24 20:06                               ` [PATCH 0/4] workqueue_tracepoint: Add worklet tracepoints for worklet lifecycle tracing Andrew Morton
2009-04-24 22:59                                 ` Frederic Weisbecker
2009-04-24 23:20                                   ` Andrew Morton
2009-04-25  0:37                                     ` Frederic Weisbecker
2009-04-25  1:28                                       ` Andrew Morton
2009-04-25  2:00                                         ` Steven Rostedt
2009-04-25  2:24                                           ` Andrew Morton
2009-04-25  2:51                                             ` Steven Rostedt
2009-04-25  3:10                                               ` Andrew Morton
2009-04-25  3:32                                                 ` Steven Rostedt
2009-04-26 10:47                                         ` Ingo Molnar
2009-04-27  5:44                                           ` Andrew Morton
2009-04-27 15:02                                             ` Oleg Nesterov
2009-04-27 15:43                                               ` Ingo Molnar
2009-04-27 19:09                                                 ` Oleg Nesterov
2009-04-28 13:42                                               ` Frederic Weisbecker
2009-04-28 16:43                                                 ` Oleg Nesterov
2009-04-28 17:49                                                   ` Frederic Weisbecker
2009-04-24 23:27                                   ` Frederic Weisbecker
2009-04-28 17:24                                 ` Frank Ch. Eigler
2009-04-28 18:48                                   ` Andrew Morton
2009-04-28 20:51                                     ` Frank Ch. Eigler
2009-04-29  4:03                                     ` KOSAKI Motohiro
2009-04-29  4:29                                       ` Andrew Morton
2009-04-29  5:21                                         ` KOSAKI Motohiro
2009-04-20 17:11                           ` [PATCH v3 1/1] ftrace, workqueuetrace: Make workqueue tracepoints use TRACE_EVENT macro Frederic Weisbecker
2009-04-21  1:20                             ` KOSAKI Motohiro
2009-04-20  6:42                       ` [PATCH 0/4] ftrace, workqueuetrace: Add worklet informationame Zhaolei
2009-04-20  6:58                         ` [PATCH 1/4] trace_workqueue: use list_for_each_entry() instead of list_for_each_entry_safe() Zhaolei
2009-04-20  7:26                           ` Frederic Weisbecker
2009-04-20  6:59                         ` [PATCH 2/4] trace_workqueue: Remove cpu_workqueue_stats->first_entry Zhaolei
2009-04-20  7:02                         ` [PATCH 3/4] trace_workqueue: Remove blank line between each cpu Zhaolei
2009-04-20  7:09                         ` [PATCH 4/4] trace_workqueue: Add worklet information Zhaolei
2009-04-20 11:36                           ` Frederic Weisbecker
2009-04-21  1:57                             ` Zhaolei
2009-04-21 23:39                               ` Frederic Weisbecker
2009-04-20  7:23                         ` [PATCH 0/4] ftrace, workqueuetrace: Add worklet informationame Frederic Weisbecker
2009-04-13 14:34     ` [PATCH 1/1] tracing, workqueuetrace: Make workqueue tracepoints use TRACE_EVENT macro Frederic Weisbecker
2009-04-13 14:13   ` Frederic Weisbecker
2009-04-15  6:47     ` KOSAKI Motohiro
2009-04-13 13:57 ` [PATCH 0/1] " Frederic Weisbecker

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090413161649.GH5977@nowhere \
    --to=fweisbec@gmail.com \
    --cc=kosaki.motohiro@jp.fujitsu.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=rostedt@goodmis.org \
    --cc=tzanussi@gmail.com \
    --cc=zhaolei@cn.fujitsu.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).