1e81fdcb135d0325e3bc22fae0583555d20aae280Brendan Jackman# Copyright 2015-2017 ARM Limited 208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# 308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# Licensed under the Apache License, Version 2.0 (the "License"); 408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# you may not use this file except in compliance with the License. 508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# You may obtain a copy of the License at 608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# 708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# http://www.apache.org/licenses/LICENSE-2.0 808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# 908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# Unless required by applicable law or agreed to in writing, software 1008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# distributed under the License is distributed on an "AS IS" BASIS, 1108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# See the License for the specific language governing permissions and 1308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# limitations under the License. 1408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino# 1508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 1608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merinoimport re 1708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 1808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merinoclass BareTrace(object): 1908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """A wrapper class that holds dataframes for all the events in a trace. 2008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 2108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino BareTrace doesn't parse any file so it's a class that should 2208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino either be (a) subclassed to parse a particular trace (like FTrace) 2308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino or (b) be instantiated and the events added with add_parsed_event() 2408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 2508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :param name: is a string describing the trace. 2608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :type name: str 2708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 2808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """ 2908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 3008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino def __init__(self, name=""): 3108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.name = name 3208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.normalized_time = False 3308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.class_definitions = {} 3408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.trace_classes = [] 3508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.basetime = 0 3608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 3708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino def get_duration(self): 3808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """Returns the largest time value of all classes, 3908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino returns 0 if the data frames of all classes are empty""" 4008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino durations = [] 4108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 4208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino for trace_class in self.trace_classes: 4308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino try: 4408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino durations.append(trace_class.data_frame.index[-1]) 4508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino except IndexError: 4608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino pass 4708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 4808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino if len(durations) == 0: 4908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino return 0 5008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 5108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino if self.normalized_time: 5208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino return max(durations) 5308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino else: 5408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino return max(durations) - self.basetime 5508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 5608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino def get_filters(self, key=""): 5708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """Returns an array with the available filters. 5808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 5908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :param key: If specified, returns a subset of the available filters 6008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino that contain 'key' in their name (e.g., :code:`key="sched"` returns 6108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino only the :code:`"sched"` related filters).""" 6208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino filters = [] 6308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 6408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino for cls in self.class_definitions: 6508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino if re.search(key, cls): 6608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino filters.append(cls) 6708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 6808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino return filters 6908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 70b01c848f3928dfcdf2f3d7dae1343bbe677847efChris Redpath def _normalize_time(self, basetime=None): 7108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """Normalize the time of all the trace classes 7208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 7308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :param basetime: The offset which needs to be subtracted from 7408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino the time index 7508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :type basetime: float 7608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """ 7708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 7808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino if basetime is not None: 7908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.basetime = basetime 8008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 8108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino for trace_class in self.trace_classes: 8208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino trace_class.normalize_time(self.basetime) 8308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 8408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.normalized_time = True 8508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 8608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino def add_parsed_event(self, name, dfr, pivot=None): 8708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """Add a dataframe to the events in this trace 8808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 8908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino This function lets you add other events that have been parsed 9008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino by other tools to the collection of events in this instance. For 9108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino example, assuming you have some events in a csv, you could add 9208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino them to a trace instance like this: 9308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 9408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino >>> trace = trappy.BareTrace() 9508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino >>> counters_dfr = pd.DataFrame.from_csv("counters.csv") 9608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino >>> trace.add_parsed_event("pmu_counters", counters_dfr) 9708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 9808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino Now you can access :code:`trace.pmu_counters` as you would with any 9908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino other trace event and other trappy classes can interact with 10008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino them. 10108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 10208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :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`. 10308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :type name: str 10408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 10508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :param dfr: :mod:`pandas.DataFrame` containing the events. Its index should be time in seconds. Its columns are the events. 10608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :type dfr: :mod:`pandas.DataFrame` 10708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 10808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :param pivot: The data column about which the data can be grouped 10908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino :type pivot: str 11008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 11108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino """ 11208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino from trappy.base import Base 11308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino from trappy.dynamic import DynamicTypeFactory, default_init 11408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 11508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino if hasattr(self, name): 11608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino raise ValueError("event {} already present".format(name)) 11708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 11808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino kwords = { 11908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino "__init__": default_init, 12008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino "unique_word": name + ":", 12108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino "name": name, 12208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino } 12308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 12408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino trace_class = DynamicTypeFactory(name, (Base,), kwords) 12508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.class_definitions[name] = trace_class 12608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 12708f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino event = trace_class() 12808f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino self.trace_classes.append(event) 12908f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino event.data_frame = dfr 13008f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino if pivot: 13108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino event.pivot = pivot 13208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 13308f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino setattr(self, name, event) 13408f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino 13508f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino def finalize_objects(self): 13608f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino for trace_class in self.trace_classes: 137a951463b87e0a17229d5fcd426b0b05a4ffb0764Joel Fernandes # If cached, don't need to do any other DF operation 138a951463b87e0a17229d5fcd426b0b05a4ffb0764Joel Fernandes if trace_class.cached: 139a951463b87e0a17229d5fcd426b0b05a4ffb0764Joel Fernandes continue 14002c452ef5bcfafe49450059f7927664a393e0235Joel Fernandes trace_class.tracer = self 14108f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino trace_class.create_dataframe() 14208f3c34d0a24e7ffeff543e302efc911306e7beaJavi Merino trace_class.finalize_object() 14302c452ef5bcfafe49450059f7927664a393e0235Joel Fernandes 14402c452ef5bcfafe49450059f7927664a393e0235Joel Fernandes def generate_data_dict(self): 14502c452ef5bcfafe49450059f7927664a393e0235Joel Fernandes return None 146