| # Copyright 2015-2017 ARM Limited |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| import re |
| |
| class BareTrace(object): |
| """A wrapper class that holds dataframes for all the events in a trace. |
| |
| BareTrace doesn't parse any file so it's a class that should |
| either be (a) subclassed to parse a particular trace (like FTrace) |
| or (b) be instantiated and the events added with add_parsed_event() |
| |
| :param name: is a string describing the trace. |
| :type name: str |
| |
| """ |
| |
| def __init__(self, name=""): |
| self.name = name |
| self.normalized_time = False |
| self.class_definitions = {} |
| self.trace_classes = [] |
| self.basetime = 0 |
| |
| def get_duration(self): |
| """Returns the largest time value of all classes, |
| returns 0 if the data frames of all classes are empty""" |
| max_durations = [] |
| min_durations = [] |
| |
| for trace_class in self.trace_classes: |
| try: |
| max_durations.append(trace_class.data_frame.index[-1]) |
| min_durations.append(trace_class.data_frame.index[0]) |
| except IndexError: |
| pass |
| |
| if len(min_durations) == 0 or len(max_durations) == 0: |
| return 0 |
| |
| return max(max_durations) - min(min_durations) |
| |
| def get_filters(self, key=""): |
| """Returns an array with the available filters. |
| |
| :param key: If specified, returns a subset of the available filters |
| that contain 'key' in their name (e.g., :code:`key="sched"` returns |
| only the :code:`"sched"` related filters).""" |
| filters = [] |
| |
| for cls in self.class_definitions: |
| if re.search(key, cls): |
| filters.append(cls) |
| |
| return filters |
| |
| def _normalize_time(self, basetime=None): |
| """Normalize the time of all the trace classes |
| |
| :param basetime: The offset which needs to be subtracted from |
| the time index |
| :type basetime: float |
| """ |
| |
| if basetime is not None: |
| self.basetime = basetime |
| |
| for trace_class in self.trace_classes: |
| trace_class.normalize_time(self.basetime) |
| |
| self.normalized_time = True |
| |
| def add_parsed_event(self, name, dfr, pivot=None): |
| """Add a dataframe to the events in this trace |
| |
| This function lets you add other events that have been parsed |
| by other tools to the collection of events in this instance. For |
| example, assuming you have some events in a csv, you could add |
| them to a trace instance like this: |
| |
| >>> trace = trappy.BareTrace() |
| >>> counters_dfr = pd.DataFrame.from_csv("counters.csv") |
| >>> trace.add_parsed_event("pmu_counters", counters_dfr) |
| |
| Now you can access :code:`trace.pmu_counters` as you would with any |
| other trace event and other trappy classes can interact with |
| them. |
| |
| :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`. |
| :type name: str |
| |
| :param dfr: :mod:`pandas.DataFrame` containing the events. Its index should be time in seconds. Its columns are the events. |
| :type dfr: :mod:`pandas.DataFrame` |
| |
| :param pivot: The data column about which the data can be grouped |
| :type pivot: str |
| |
| """ |
| from trappy.base import Base |
| from trappy.dynamic import DynamicTypeFactory, default_init |
| |
| if hasattr(self, name): |
| raise ValueError("event {} already present".format(name)) |
| |
| kwords = { |
| "__init__": default_init, |
| "unique_word": name + ":", |
| "name": name, |
| } |
| |
| trace_class = DynamicTypeFactory(name, (Base,), kwords) |
| self.class_definitions[name] = trace_class |
| |
| event = trace_class() |
| self.trace_classes.append(event) |
| event.data_frame = dfr |
| if pivot: |
| event.pivot = pivot |
| |
| setattr(self, name, event) |
| |
| def finalize_objects(self): |
| for trace_class in self.trace_classes: |
| # If cached, don't need to do any other DF operation |
| if trace_class.cached: |
| continue |
| trace_class.tracer = self |
| trace_class.create_dataframe() |
| trace_class.finalize_object() |
| |
| def generate_data_dict(self, data_str): |
| return None |