Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [linuxtools-dev] TMF: pluggable state provider contribution(s)

On 13-04-23 12:40 PM, Aaron Spear wrote:
> Hi Alexandre,
>
> replies below:
>
> ----- Original Message -----
>> - I think what you call "context" in the stateflow plugin is pretty much
>> the same thing we call "attribute" in the TMF state system. You've
>> probably seen o.e.l.internal.tmf.core.statesystem.Attribute. We already
>> use the notion of "context" to represent a specific location in a trace,
>> so it could lead to confusion. Perhaps we could tweak Attribute a bit
>> and make it public, or maybe have them share a common interface.
> I am trying to use context in the same sense that we intended it while
> developing the CTF spec, that is that it is a value that indicates 
> information about the environment of a given event.  So that typically means
> board/core/process/thread or the like.  Of course this information *can* and
> in this case is an attribute of an event, but it is not necessarily an 
> attribute as it could be implied for a given trace too.  I think that the 
> important point is that for a given trace with this "state flow" view, the 
> context value is something that is completely trace specific and is a 
> hierarchical Y axis value

Ah ok I see, you call "context" the rows that will be shown in the view.

But the state system's attributes are not directly linked to events
(it's not like an event field), it's just an organization of items for
which we want to track the state of, over the duration of the trace.

>
> If I understand you correctly you are saying that you use "context" to 
> refer to an events position in time? 

Yes we use "context" to represent a specific position in a trace, since
timestamps is not always precise enough (there can be more than one
event at a given timestamp). See TmfContext and co. But it's not like we
don't have plenty of name clashes already, so it's not that bad.

> How do you differentiate between an 
> attribute of an event that is say the count of a semaphore vs. an attribute
> that is the thread that it occurred in?  They are both "attributes" no?

Yes both would be different attributes. For example in the LTTng-kernel
state provider, we have attributes like:

|_ threads
  |_ 1
  |  |_ PPID
  |  |_ Status
  |  |_ Exec_name
  |
  |_ 2
  |   |_ PPID
 ... ...

So "PPID", "Status" and "Exec_name" are all attributes related to the
thread with TID 1. They can all change independently, depending on the
events.


And for the "statistics state system", which we use for anything that
extends TmfTrace, we have attributes like:

|_ Event_totals
|_ Event_types
    |_ sched_switch
    |_ sched_fork
    |_ exit_syscall
   ...

The value in "Event_totals" gets incremented every event, and the
attribute corresponding to the event type gets incremented too (the
attribute names come from the event types that are seen). So we have,
for any point in the trace, the total of events seen so far, and the
totals per event type.


Also, I'd like to note, attributes can all have values and
sub-attributes. It's not like a usual filesystem where you have both
files and directories, here each attribute can be both a file and a
directory.

>
>> - In the XML files to define the state changes, you separate the actions
>> of "switching context" and "applying state change to the current
>> context". Is there any reason for this? This can make sense / be easier
>> when dealing with single-threaded applications, but in multi-threaded
>> applications or systems, a series of events in the trace could relate to
>> completely different attributes.
> I realize that is a little odd to get your brain wrapped around it.  It is like
> this because it was the most simple way that I could, in the same data driven 
> implementation, be able to support the notion of a call stack on a given thread.
> The events that come across for the function tracer that I did basically have a 
> thread id in every event, and then a function/entry or exit as the event type.  
> Because it is multi-threaded you have no idea what order any events will come in, 
> and this means that you must, in the viewer, track the call stack for each thread
> individually. So I FIRST check to see if we should "switch context" for the given
> event, and then switch to a data structure that tracks the call stack for that 
> context/thread.  Then if that same event is setup for any "push state change" or
> "pop state change" I apply those.  I did want to keep this information (of the 
> call stack for the thread) in the state system, but could not really figure out
> an efficient way to do this.  I would certainly be open to better ideas here.

Oh yes, I definitely see the need of wanting to track all the values in
a stack. In fact, we already have something in place for exactly that ;)

If you look at ITmfStateSystemBuilder#pushAttribute and #popAttribute
(implemented in StateSystem.java), it allows pushing and popping
attributes in a stack, while tracking
- the current depth of the stack
- the state value of each element in the stack.

It works by using one attribute as the "stack attribute", whose value
indicates the current stack depth. It then uses sub-attributes of this
one, called "1", "2", "3", etc (representing the positions in the stack,
starting at the bottom), and the values of these attributes represent
the values that were pushed to the stack.
There is also a convenience ITmfStateSystem#querySingleStackTop that can
be used to directly query the value of the "top" of the stack, instead
of doing 2 queries every time.

If you are curious about how it can be used, you can look at its unit
tests in StateSystemPushPopTest.java. It goes over all the possible use
cases.

This is probably something you can re-use for your push/popping of
contexts. Or we can see if it could be improved so that it can be re-used.

>> Would it be more generic to have only one entry per state change, which
>> would define both the attribute/context to modify and the value that is
>> being given?
> Well, it is trickier than that though.  Consider the use case of this function
> tracer.  In that case, you have only have the following two different events 
> -thread id
> -event type: function entry
> -new function name
>
> -thread id
> -event type: function exit
> -name of function you are EXITING
>
> There are two reasons then why you must have the "push", "pop" in addition to a
> switch:
>
> -You want to be able to indicate functions for a given thread mutually 
> exclusively so that it is clear what functions are running and what functions
> are up stack at any point. 
> -If you didn't care about showing what was up stack in a different color you
> could do a switch for the function entry, since you have all the information
> you need in the event.  However, for function exit, you only have that you are
> exiting a function, and thus you do not know what you need to switch to.  You
> must track this outside.
>
> Yes, you could have a single entry that can do all of this, but it ends up being
> "6 of one, half dozen of the other".  If you do this, then to support my 
> "call stack" use case you must indicate that this particular event is either a 
> "switch only" in which case the new value in the event is the complete value, 
> or a "push" (in which case the new value is pushed on to a stack for the given
> context) or a "pop".

Indeed, we would definitely need "modify" but also the "push" and "pop"
operations. As mentioned before, there are already push/pop operations
in ITmfStateSystemBuilder. We'd just have to see if they cover your use
case, and if it's easy enough to hook the XML parser into using those.

Side-note, there is also a 4th operation called "incrementAttribute",
which simply increments the value of the attribute by one (has to be an
integer value of course). This is what we use for statistics for example.

>
> Note that doing this does open up some interesting visualization possibilities
> for state machines in addition to function calls.
>
>> Very crude and unoriginal example, let's suppose I have an event
>> "sched_switch", and I want to update the value of the attribute
>> "Thread/[thread tid]/Status" to the value "running":
>>
>> <eventHandler eventName="sched_switch">
>>   <stateChange>
>>     # Define the path to the attribute to be affected
>>     <attribute name="Threads" /> # hard-coded value
>>     <attribute fieldvalue="tid" /> # a field in sched_switch
>>     <attribute name="Status" />
>>     # Apply the state change
>>     <modify valueType="string" value="Running" />

Going back to this example, here we could also support let's say
<push valueType="string" value="running" />
or simply
<pop />

to indicate that we want to call pushAttribute() or popAttribute(),
instead of modifyAttribute().

>>   </stateChange>
>> </eventHandler>
>>
>> I put a String value, but of course we'd probably want an integer value
>> here instead. I also put the <stateChange> under the event name itself,
>> since sometimes one event can cause more than one state change. Any
>> thoughts?
> One thing that does occur to me is that there is probably some value in
> decoupling the logic used to populate the state system with what you want
> to display.  What you have above is good in that it outlines clearly what
> event information is going into the state system, but of course you don't
> know from this alone what is supposed to be displayed on the Y axis at all.
> You would need something else to tell the view what the hierarchy is, how
> to get the values from the state system, and the display information for those
> states (and of course my xml file does all of this in one file at the moment)

True that, we don't necessarily want to display everything that is
stored in one state system (unless it's for the State System Explorer of
course!)

There's already some ways to get specific attributes, like
ITmfStateSystem#getQuarks(). We can do getQuarks("Threads", "*",
"Status"), and it will return the quarks for the "Status" attributes for
all the threads found in the state system. A view can then iterate over
those and query only these attributes. It could be improved, for example
supporting more than one wildcard, or eventually maybe having DB-like
queries. But for our use cases so far this was sufficient, since we
control both the attribute tree creation, and the contents of the Y-axis
of the view.

I'm not sure yet if this "list of attributes to display" should be
explicitely defined in the XML file, or if this should be defined in the
view itself (like we could build a state history from the XML file
first, then tweak what we want to display in the view).



Cheers,
Alexandre


Back to the top