bare_trace.py revision 101592273c8bdf29d95d321a86189666d88a9ddb
1#    Copyright 2015-2017 ARM Limited
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
15
16import re
17
18class BareTrace(object):
19    """A wrapper class that holds dataframes for all the events in a trace.
20
21    BareTrace doesn't parse any file so it's a class that should
22    either be (a) subclassed to parse a particular trace (like FTrace)
23    or (b) be instantiated and the events added with add_parsed_event()
24
25    :param name: is a string describing the trace.
26    :type name: str
27
28    """
29
30    def __init__(self, name=""):
31        self.name = name
32        self.normalized_time = False
33        self.class_definitions = {}
34        self.trace_classes = []
35        self.basetime = 0
36
37    def get_duration(self):
38        """Returns the largest time value of all classes,
39        returns 0 if the data frames of all classes are empty"""
40        max_durations = []
41        min_durations = []
42
43        for trace_class in self.trace_classes:
44            try:
45                max_durations.append(trace_class.data_frame.index[-1])
46                min_durations.append(trace_class.data_frame.index[0])
47            except IndexError:
48                pass
49
50        if len(min_durations) == 0 or len(max_durations) == 0:
51            return 0
52
53        return max(max_durations) - min(min_durations)
54
55    def get_filters(self, key=""):
56        """Returns an array with the available filters.
57
58        :param key: If specified, returns a subset of the available filters
59            that contain 'key' in their name (e.g., :code:`key="sched"` returns
60            only the :code:`"sched"` related filters)."""
61        filters = []
62
63        for cls in self.class_definitions:
64            if re.search(key, cls):
65                filters.append(cls)
66
67        return filters
68
69    def _normalize_time(self, basetime=None):
70        """Normalize the time of all the trace classes
71
72        :param basetime: The offset which needs to be subtracted from
73            the time index
74        :type basetime: float
75        """
76
77        if basetime is not None:
78            self.basetime = basetime
79
80        for trace_class in self.trace_classes:
81            trace_class.normalize_time(self.basetime)
82
83        self.normalized_time = True
84
85    def add_parsed_event(self, name, dfr, pivot=None):
86        """Add a dataframe to the events in this trace
87
88        This function lets you add other events that have been parsed
89        by other tools to the collection of events in this instance.  For
90        example, assuming you have some events in a csv, you could add
91        them to a trace instance like this:
92
93        >>> trace = trappy.BareTrace()
94        >>> counters_dfr = pd.DataFrame.from_csv("counters.csv")
95        >>> trace.add_parsed_event("pmu_counters", counters_dfr)
96
97        Now you can access :code:`trace.pmu_counters` as you would with any
98        other trace event and other trappy classes can interact with
99        them.
100
101        :param name: The attribute name in this trace instance.  As in the example above, if :code:`name` is "pmu_counters", the parsed event will be accessible using :code:`trace.pmu_counters`.
102        :type name: str
103
104        :param dfr: :mod:`pandas.DataFrame` containing the events.  Its index should be time in seconds.  Its columns are the events.
105        :type dfr: :mod:`pandas.DataFrame`
106
107        :param pivot: The data column about which the data can be grouped
108        :type pivot: str
109
110        """
111        from trappy.base import Base
112        from trappy.dynamic import DynamicTypeFactory, default_init
113
114        if hasattr(self, name):
115            raise ValueError("event {} already present".format(name))
116
117        kwords = {
118            "__init__": default_init,
119            "unique_word": name + ":",
120            "name": name,
121        }
122
123        trace_class = DynamicTypeFactory(name, (Base,), kwords)
124        self.class_definitions[name] = trace_class
125
126        event = trace_class()
127        self.trace_classes.append(event)
128        event.data_frame = dfr
129        if pivot:
130            event.pivot = pivot
131
132        setattr(self, name, event)
133
134    def finalize_objects(self):
135        for trace_class in self.trace_classes:
136            # If cached, don't need to do any other DF operation
137            if trace_class.cached:
138                continue
139            trace_class.tracer = self
140            trace_class.create_dataframe()
141            trace_class.finalize_object()
142
143    def generate_data_dict(self, data_str):
144        return None
145