Skip to content
  • Steven Rostedt's avatar
    tracing: add raw trace point recording infrastructure · c32e827b
    Steven Rostedt authored
    
    
    Impact: lower overhead tracing
    
    The current event tracer can automatically pick up trace points
    that are registered with the TRACE_FORMAT macro. But it required
    a printf format string and parsing. Although, this adds the ability
    to get guaranteed information like task names and such, it took
    a hit in overhead processing. This processing can add about 500-1000
    nanoseconds overhead, but in some cases that too is considered
    too much and we want to shave off as much from this overhead as
    possible.
    
    Tom Zanussi recently posted tracing patches to lkml that are based
    on a nice idea about capturing the data via C structs using
    STRUCT_ENTER, STRUCT_EXIT type of macros.
    
    I liked that method very much, but did not like the implementation
    that required a developer to add data/code in several disjoint
    locations.
    
    This patch extends the event_tracer macros to do a similar "raw C"
    approach that Tom Zanussi did. But instead of having the developers
    needing to tweak a bunch of code all over the place, they can do it
    all in one macro - preferably placed near the code that it is
    tracing. That makes it much more likely that tracepoints will be
    maintained on an ongoing basis by the code they modify.
    
    The new macro TRACE_EVENT_FORMAT is created for this approach. (Note,
    a developer may still utilize the more low level DECLARE_TRACE macros
    if they don't care about getting their traces automatically in the event
    tracer.)
    
    They can also use the existing TRACE_FORMAT if they don't need to code
    the tracepoint in C, but just want to use the convenience of printf.
    
    So if the developer wants to "hardwire" a tracepoint in the fastest
    possible way, and wants to acquire their data via a user space utility
    in a raw binary format, or wants to see it in the trace output but not
    sacrifice any performance, then they can implement the faster but
    more complex TRACE_EVENT_FORMAT macro.
    
    Here's what usage looks like:
    
      TRACE_EVENT_FORMAT(name,
    	TPPROTO(proto),
    	TPARGS(args),
    	TPFMT(fmt, fmt_args),
    	TRACE_STUCT(
    		TRACE_FIELD(type1, item1, assign1)
    		TRACE_FIELD(type2, item2, assign2)
    			[...]
    	),
    	TPRAWFMT(raw_fmt)
    	);
    
    Note name, proto, args, and fmt, are all identical to what TRACE_FORMAT
    uses.
    
     name: is the unique identifier of the trace point
     proto: The proto type that the trace point uses
     args: the args in the proto type
     fmt: printf format to use with the event printf tracer
     fmt_args: the printf argments to match fmt
    
     TRACE_STRUCT starts the ability to create a structure.
     Each item in the structure is defined with a TRACE_FIELD
    
      TRACE_FIELD(type, item, assign)
    
     type: the C type of item.
     item: the name of the item in the stucture
     assign: what to assign the item in the trace point callback
    
     raw_fmt is a way to pretty print the struct. It must match
      the order of the items are added in TRACE_STUCT
    
     An example of this would be:
    
     TRACE_EVENT_FORMAT(sched_wakeup,
    	TPPROTO(struct rq *rq, struct task_struct *p, int success),
    	TPARGS(rq, p, success),
    	TPFMT("task %s:%d %s",
    	      p->comm, p->pid, success?"succeeded":"failed"),
    	TRACE_STRUCT(
    		TRACE_FIELD(pid_t, pid, p->pid)
    		TRACE_FIELD(int, success, success)
    	),
    	TPRAWFMT("task %d success=%d")
    	);
    
     This creates us a unique struct of:
    
     struct {
    	pid_t		pid;
    	int		success;
     };
    
     And the way the call back would assign these values would be:
    
    	entry->pid = p->pid;
    	entry->success = success;
    
    The nice part about this is that the creation of the assignent is done
    via macro magic in the event tracer.  Once the TRACE_EVENT_FORMAT is
    created, the developer will then have a faster method to record
    into the ring buffer. They do not need to worry about the tracer itself.
    
    The developer would only need to touch the files in include/trace/*.h
    
    Again, I would like to give special thanks to Tom Zanussi for this
    nice idea.
    
    Idea-from: Tom Zanussi <tzanussi@gmail.com>
    Signed-off-by: default avatarSteven Rostedt <srostedt@redhat.com>
    c32e827b