linux/include
Steven Rostedt (Red Hat) 9d3c752c06 tracing: Optimize trace_printk() with one arg to use trace_puts()
Although trace_printk() is extremely fast, especially when it uses
trace_bprintk() (writes args straight to buffer instead of inserting
into string), it still has the overhead of calling one of the printf
sprintf() functions, that need to scan the fmt string to determine
what, if any args it has.

This is a waste of precious CPU cycles if the printk format has no
args but a single constant string. It is better to use trace_puts()
which does not have the overhead of the fmt scanning.

But wouldn't it be nice if the developer didn't have to think about
such things, and the compile would just do it for them?

  trace_printk("this string has no args\n");
  [...]
  trace_printk("this sting does %p %d\n", foo, bar);

As tracing is critical to have the least amount of overhead,
especially when dealing with race conditions, and you want to
eliminate any "Heisenbugs", you want the trace_printk() to use the
fastest possible means of tracing.

Currently the macro magic determines if it will use trace_bprintk()
or if the fmt is a dynamic string (a variable), it will fall
back to the slow trace_printk() method that does a full snprintf()
before copying it into the buffer, where as trace_bprintk() only
copys the pointer to the fmt and the args into the buffer.

Well, now there's a way to spend some more Hogwarts cash and come
up with new fancy macro magic.

  #define trace_printk(fmt, ...)			\
  do {							\
	char _______STR[] = __stringify((__VA_ARGS__));	\
	if (sizeof(_______STR) > 3)			\
		do_trace_printk(fmt, ##__VA_ARGS__);	\
	else						\
		trace_puts(fmt);			\
  } while (0)

The above needs a bit of explaining (both here and in the comments).

By stringifying the __VA_ARGS__, we can, at compile time, determine
the number of args that are being passed to trace_printk(). The extra
parenthesis are required, otherwise the compiler complains about
too many parameters for __stringify if there is more than one arg.

When there are no args, the __stringify((__VA_ARGS__)) converts into
"()\0", a string of 3 characters. Anything else, will be a string
containing more than 3 characters. Now we assign that string to a
dynamic char array, and then take the sizeof() of that array.
If it is greater than 3 characters, we know trace_printk() has args
and we need to do the full "do_trace_printk()" on them, otherwise
it was only passed a single arg and we can optimize to use trace_puts().

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Steven "The King of Nasty Macros!" Rostedt <rostedt@goodmis.org>
2013-03-15 00:35:56 -04:00
..
acpi PCI changes for the v3.8 merge window: 2012-12-13 12:14:47 -08:00
asm-generic This implements the cputime accounting on full dynticks CPUs. 2013-02-05 13:10:33 +01:00
clocksource
crypto
drm Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel 2013-01-11 07:52:48 +10:00
keys
linux tracing: Optimize trace_printk() with one arg to use trace_puts() 2013-03-15 00:35:56 -04:00
math-emu
media
memory
misc
net ipv6: rename datagram_send_ctl and datagram_recv_ctl 2013-01-31 13:53:08 -05:00
pcmcia
ras
rdma UAPI: Remove empty Kbuild files 2013-01-02 17:36:10 -08:00
rxrpc
scsi SCSI misc on 20121212 2012-12-13 19:20:31 -08:00
sound Merge remote-tracking branch 'asoc/fix/cs4271' into tmp 2013-01-10 12:22:11 +00:00
target target: Introduce TCM_NO_SENSE 2013-01-10 20:06:08 -08:00
trace tracing: Fix some section mismatch warnings 2013-03-15 00:34:54 -04:00
uapi Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2013-02-19 17:49:41 -08:00
video Merge branch 'omap-for-v3.8/fixes-for-merge-window' into omap-for-v3.8/fixes-for-merge-window-v2 2012-12-16 11:28:10 -08:00
xen Bugfixes: 2012-12-18 12:26:54 -08:00
Kbuild UAPI: Remove empty Kbuild files 2013-01-02 17:36:10 -08:00