All of lore.kernel.org
 help / color / mirror / Atom feed
From: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>,
	Peter Zijlstra <peterz@infradead.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	LKML <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH 4/4] perf/timer: 'perf timer' core code
Date: Wed, 16 Dec 2009 13:56:32 +0800	[thread overview]
Message-ID: <4B287690.4000305@cn.fujitsu.com> (raw)
In-Reply-To: <alpine.LFD.2.00.0912151539420.2755@localhost.localdomain>

Hi Thomas,

Sorry for many mistakes(typos and bad ideas) in this patch, i'll cook it
more and be careful later. Thanks very much.

Thomas Gleixner wrote:
> The output is confusing in several aspects:
> 
>   1) Different time units:
> 
>      Please use consistent time units for everything. micro seconds
>      are fine and we definitely do not care about nanosecond
>      fractions.

OK, i'll change ns to ms, and for timer, the unit is HZ, do we have the
way to read kernel HZ in userspace? if not, i'll export HZ by proc/debugfs
or other way

> 
>   2) Timer description:
>      
>      Why do we have hex addresses and process names intermingled ? Why
>      don't we print the process/thread name which owns the timer
>      always ? [PROF/VIRTUAL] is not a property of the Timer, it
>      belongs into type.

Um, but not every timer has it's owner task, for example, if we start
a timer in interrupt handle function, this timer in not owns any tasks.
And itimer is started by userspace task so we can get it's owner, that
why i print hex address for timer/hrtimer, and print task name for itimer.

>
>   3) Max-lat-at-Task:
> 
>      What does this field tell ?

It means that which task in running when the maximum latency occurs.
but, as you noticed, this is useless, i'll remove it in next version
patch.

>    
>   4) *handle:
> 
>      That should be a more descriptive name, e.g. function runtime
> 

OK, will fix

>   5) Max-lat-at-func:
> 
>      Is this the callback function which ran the longest time ? Why
>      is it named latency ? Why is it not decoded into a symbol ?

it's my typo, i'll export it using right/better way

> 
> Btw, fitting the output into 80chars allows to use the tool on a non
> graphical terminal as well.
> 

OK, will fix

> Also there are other metrics of timers which are interesting and
> should be retrieved by such a tool:
> 
>      number of activated timers
>      number of canceled timers
>      number of expired timers
> 
> in the form of simple statistics.
> 

OK. will support it

> The canceled timers are interesting also in a list, so we can see
> which timers are canceled after which time and how long before the
> expiry.
> 

Um, i'll cook timer tracepoints to get the time when timer canceled,
and support this function.

>> +static const char * const timer_usage[] = {
>> +	"perf timer [<options>] {record|latency}",
>> +	NULL
>> +};
> 
> Your example above uses "perf timer lat". What's correct ?
> 

Actually, we only compare frontal 3 characters:
	strncmp(argv[0], "lat", 3)

And 'perf sched' and other commands also use this way.

>> +static const struct option latency_options[] = {
>> +	OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
>> +		   "sort by key(s): "SORT_KEY),
> 
> Do we really need a sort order ? A single sort key should be
> sufficient.
> 

i think it's necessary.

for example, if we interest in timer's max latency, then we can
use '-s max-timer-latency' to sort it.

And, if it has many timer with the some max latency, then we can
use '-s max-timer-latency,avg-timer-latency' to sort

> I'd prefer to have a selector instead which lets me filter timer
> types. If I debug hrtimers then I have no interest in itimers or timer
> list timers.
> 

OK, will support this filter

>> +static LIST_HEAD(sort_list);
>> +
>> +static void setup_sorting(void)
>> +{
>> +	char *tmp, *tok, *str = strdup(sort_order);
> 
>   Please hand sort_order in as an argument.
> 

Sorry for my stupid question:
'sort_order' is a global variable and setup_sorting() only called
one time, why need hand sort_order in as an argument?

>> +static struct timer_info *
>> +__timer_search(struct rb_root *root, struct timer_info *timer,
>> +	       struct list_head *_sort_list)
>> +{
>> +	struct rb_node *node = root->rb_node;
>> +
>> +	while (node) {
>> +		struct timer_info *timer_info;
>> +		int cmp;
>> +
>> +		timer_info = container_of(node, struct timer_info, node);
>> +
>> +		cmp = timer_key_cmp(_sort_list, timer, timer_info);
>> +		if (cmp > 0)
>> +			node = node->rb_left;
>> +		else if (cmp < 0)
>> +			node = node->rb_right;
>> +		else
>> +			return timer_info;
> 
>   This looks more than odd. You search for a timer in the list by
>   using the compare functions which are used for sorting ?
> 
>   How should that work ?
> 

We put/get timer in a rb-tree base on the specify order, for example:
we default use this order:

sort_dimension__add("timer", &default_cmp);
sort_dimension__add("itimer-type", &default_cmp);

if timer_info->timer is bigger, we put it to left child, littler to right
child, if the timer_info->timer is the same, then we compare
timer_info->itimer_type.

>> +{
>> +	struct timer_info *find = NULL;
>> +	struct timer_info timer_info = {
>> +			.timer = timer,
>> +			.itimer_type = itimer_type,
>> +		};
>> +
>> +	find = timer_search(&timer_info);
>> +	if (find && find->type != type) {
>> +
>> +		dprintf("find timer[%p], but type[%s] is not we expect[%s],"
>> +			"set to initializtion state.\n", find->timer,
>> +			timer_type_string[find->type], timer_type_string[type]);
>> +
>> +		find->type = type;
>> +		find->bug++;
>> +		find->state = TIMER_INIT;
> 
>   Why does a timer_search fail ? And why is fixing up the type if it
>   is not matching a good idea ?
> 

We search timer base on timer_info->timer and timer_info->itimer_type(not timer_info->type),
if we find the timer's type is changed(for example, the timer is "ITIMER" before, and change
to "HRTIMER" later), is should a bug. this case is hardly to happen but should catch it.

>> +static void *get_timer(enum timer_type type, struct event *event, void *data)
>> +{
>> +	if (type == HRTIMER) {
>> +		void *hrtimer = NULL;
>> +
>> +		FILL_RAM_FIELD_PTR(event, hrtimer, data);
>> +		return hrtimer;
> 
>   Shudder.
> 
> 	return raw_field_ptr(event, "hrtimer", data);
> 

Yeah, it's a clear way.

>> +static void
>> +itimer_state_handler(void *data, struct event *event, int this_cpu __used,
>> +		     u64 timestamp __used, struct thread *thread)
>> +{
>> +	u64 value_sec, value_usec, expires;
>> +	struct timer_info *timer_info;
>> +	void *timer = NULL;
>> +	int which;
>> +
>> +	FILLL_RAW_FIELD_VALUE(event, value_sec, data);
>> +	FILLL_RAW_FIELD_VALUE(event, value_usec, data);
>> +	FILLL_RAW_FIELD_VALUE(event, expires, data);
>> +	FILLL_RAW_FIELD_VALUE(event, which, data);
>> +	FILL_RAM_FIELD_PTR(event, timer, data);
> 
>   This is complete obfuscated, while
> 
>   value_sec = get_value(data, event, "value_sec");
> 
>   is obvious.
> 

Sorry, i cannot get this. As i understand:

#define FILL_RAW_FIELD_VALUE(event, field, data)		\
	field = (typeof(field))raw_field_value(event, #field, data)

After FILL_RAW_FIELD_VALUE(event, value_sec, data) expanded, it's:
  value_sec = raw_field_value(event, "value_sec", data)

Why it's wrong? :-(

>> +	timer_info = timer_findnew(thread, ITIMER, which);
>> +
>> +	/* itimer canceled, we skip this event */
>> +	if (!value_sec && !value_usec)
>> +		return ;
> 
>   You throw away valuable information here about canceled timers.
> 

We are not catch *_cancel event in this patch, i'll catch it to support
'number of canceled timers' in the next version.

Thanks,
Xiao

  reply	other threads:[~2009-12-16  5:58 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-15 11:17 [PATCH 0/4] perf_event: introduce 'perf timer' to analyze timer's behavior Xiao Guangrong
2009-12-15 11:19 ` [PATCH 1/4] trace_event: record task' real_timer in itimer_state tracepoint Xiao Guangrong
2009-12-15 11:20   ` [PATCH 2/4] perf_event: fix getting point Xiao Guangrong
2009-12-15 11:21     ` [PATCH 3/4] perf/timer: add document Xiao Guangrong
2009-12-15 11:22       ` [PATCH 4/4] perf/timer: 'perf timer' core code Xiao Guangrong
2009-12-15 17:44         ` Thomas Gleixner
2009-12-16  5:56           ` Xiao Guangrong [this message]
2009-12-16 15:59             ` Thomas Gleixner
2009-12-17  7:26               ` Xiao Guangrong
2009-12-15 13:58     ` [PATCH 2/4] perf_event: fix getting point Frederic Weisbecker
2009-12-16  1:03       ` Xiao Guangrong
2009-12-16  1:22         ` Frederic Weisbecker
2009-12-16  1:32           ` Xiao Guangrong
2009-12-15 14:15 ` [PATCH 0/4] perf_event: introduce 'perf timer' to analyze timer's behavior Frederic Weisbecker
2009-12-16  1:19   ` Xiao Guangrong
2009-12-16  7:32     ` Ingo Molnar
2009-12-16  7:40       ` Xiao Guangrong
2009-12-16  7:46         ` Ingo Molnar
2009-12-15 14:23 ` Frederic Weisbecker
2009-12-22 13:00   ` [PATCH v2 0/5] " Xiao Guangrong
2009-12-22 13:01     ` [PATCH v2 1/5] perf_event: fix getting point Xiao Guangrong
2009-12-22 13:03     ` [PATCH v2 2/5]: trace_event: export HZ in timer's tracepoint format Xiao Guangrong
2009-12-22 13:20       ` Xiao Guangrong
2009-12-28  7:54       ` Ingo Molnar
2009-12-28 10:40         ` Xiao Guangrong
2009-12-29  5:20         ` [PATCH v3 0/5] perf tools: introduce 'perf timer' to analyze timer's behavior Xiao Guangrong
2009-12-29  5:21         ` [PATCH v3 1/5] perf_event: introduce 'inject' event and get HZ Xiao Guangrong
2009-12-30  9:19           ` Peter Zijlstra
2009-12-30  9:28             ` Ingo Molnar
2009-12-30  9:36               ` Peter Zijlstra
2009-12-30  9:44                 ` Ingo Molnar
2009-12-30 10:06                 ` Peter Zijlstra
2009-12-30 11:30                   ` Ingo Molnar
2009-12-30  9:37             ` Xiao Guangrong
2009-12-30  9:45               ` Peter Zijlstra
2009-12-29  5:21         ` [PATCH v3 2/5] trace_event: record task' real_timer in itimer_state tracepoint Xiao Guangrong
2009-12-29  5:21         ` [PATCH v3 3/5] perf tools: fix getting point Xiao Guangrong
2009-12-29  5:21         ` [PATCH v3 4/5] perf timer: add document for 'perf timer' Xiao Guangrong
2009-12-29  5:22         ` [PATCH v3 5/5] perf timer: add 'perf timer' core code Xiao Guangrong
2009-12-22 13:04     ` [PATCH v2 3/5] trace_event: record task' real_timer in itimer_state tracepoint Xiao Guangrong
2009-12-22 13:06       ` [PATCH v2 4/5] perf/timer: add document for 'perf timer' Xiao Guangrong
2009-12-22 13:08         ` [PATCH v2 5/5] perf/timer: add 'perf timer' core code Xiao Guangrong

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=4B287690.4000305@cn.fujitsu.com \
    --to=xiaoguangrong@cn.fujitsu.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.