Registering arbitrary trace events

trappy knows about some trace events. You can add your own in the notebook without having to change any code in trappy. After the trace is registered, the next time you parse a trace file that information will be part of the run object as a pandas DataFrame and can be analyzed like the other DataFrames in the Run class.

The trace event must follow the following format:

title: key0=value0 key1=value1 key2=value2 ...

The title should be something that's unique in the trace. For example, you can generate trace with the following trace_printk():

trace_printk("thermal_gpu_power_get: frequency=%u load=%d\n", freq, load);

which will appear in the trace.txt as:

kworker/6:1-457   [006]   144.439566: bprint:               0xc042f8a0f: thermal_gpu_power_get: frequency=177 load=0

You can add this event to the run instance using register_dynamic()

First import trappy


In [1]:
import sys
sys.path.append("..")
%pylab inline
import trappy


Populating the interactive namespace from numpy and matplotlib

Register the trace. The first argument is the name under which you will find it in the run instance. It will be changed to lower_case_with_underscores_to_separate_words. The second argument is some unique text in the trace, usually the title:


In [2]:
trappy.register_dynamic("gpu_power_in", "thermal_gpu_power_get")


Out[2]:
trappy.dynamic.gpu_power_in

Now we can parse the trace


In [3]:
run = trappy.Run("/path/to/trace")

run now has a gpu_power_in member that contains the information. We can see the first few lines of the generated dataframe:


In [5]:
run.gpu_power_in.data_frame.head()


Out[5]:
frequency load
Time
109.999957 480 96
110.099925 480 100
110.199930 480 100
110.299938 480 100
110.399924 480 100

We can now plot it or manipulate it as any other DataFrame in pandas


In [8]:
figsize(18, 7)
run.gpu_power_in.data_frame["frequency"].plot()


Out[8]:
<matplotlib.axes.AxesSubplot at 0x7f7766c67f50>

Advanced usage

register_dynamic() is useful for simple traces in which you don't need to do any post-processing. If you need to register a full-featured trace class you can use trappy.register_class() for this. For example, a class that parses trace for capacity_per_group: and wants to limit the cpumasks to 8-digit could declare it like this:


In [8]:
from trappy.base import Base
class GroupCapacity(Base):

    unique_word = "capacity_per_group:"
    name = "group_capacity"
    _cpus_column = "cpus"

    def __init__(self):
        super(GroupCapacity, self).__init__(
            unique_word=self.unique_word,
        )

    def finalize_object(self):
        if self._cpus_column in self.data_frame.columns:
            self.data_frame[self._cpus_column] = self.data_frame[self._cpus_column].apply('{:0>8}'.format)

trappy.register_class(GroupCapacity)

Now after parsing your trace using trappy.Run() you can access it's group_capacity member. For example:

trappy.LinePlot(run, GroupCapacity, column="group_capacity", pivot="cpus", marker='.', linestyle='none', per_line=2).view()