1d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# SPDX-License-Identifier: Apache-2.0 2d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# 3d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# Copyright (C) 2015, ARM Limited and contributors. 4d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# 5d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# Licensed under the Apache License, Version 2.0 (the "License"); you may 6d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# not use this file except in compliance with the License. 7d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# You may obtain a copy of the License at 8d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# 9d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# http://www.apache.org/licenses/LICENSE-2.0 10d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# 11d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# Unless required by applicable law or agreed to in writing, software 12d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# See the License for the specific language governing permissions and 15d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# limitations under the License. 16d95e98d88a6cf4347853427dc4ef6fd0222a3881Patrick Bellasi# 178e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 18b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio""" Trace Parser Module """ 19b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 208e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport numpy as np 218e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport os 228e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport pandas as pd 238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport sys 248e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport trappy 2579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasiimport json 26fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasiimport warnings 27691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgioimport operator 28c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasiimport logging 2979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 306721d173e18d3c56a33fd3f2eb9b50acd675ec27Patrick Bellasifrom analysis_register import AnalysisRegister 31691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgiofrom collections import namedtuple 32691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgiofrom devlib.utils.misc import memoized 33d1ed4c86118d4a2231231d185b423e90ac38df56Patrick Bellasifrom trappy.utils import listify, handle_duplicate_index 348e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 358e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 36d162fa6bab716eacb5b423f94e60c720993bbe5bBrendan JackmanNON_IDLE_STATE = -1 37691fc118e5dff4df885a039cc855a746de4b7556Michele Di GiorgioResidencyTime = namedtuple('ResidencyTime', ['total', 'active']) 38691fc118e5dff4df885a039cc855a746de4b7556Michele Di GiorgioResidencyData = namedtuple('ResidencyData', ['label', 'residency']) 39b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 408e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiclass Trace(object): 41f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 42f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio The Trace object is the LISA trace events parser. 43f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 44f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param platform: a dictionary containing information about the target 45f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio platform 46f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type platform: dict 47f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 48f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param data_dir: folder containing all trace data 49f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type data_dir: str 50f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 51f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param events: events to be parsed (everything in the trace by default) 52f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type events: list(str) 53f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 54aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :param tasks: filter data for the specified tasks only. If None (default), 55aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman use data for all tasks found in the trace. 56aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :type tasks: list(str) or NoneType 57f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 58f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param window: time window to consider when parsing the trace 59f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type window: tuple(int, int) 60f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 61f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param normalize_time: normalize trace time stamps 62f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type normalize_time: bool 63f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 64f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param trace_format: format of the trace. Possible values are: 65f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio - FTrace 66f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio - SysTrace 67f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type trace_format: str 68f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 69f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param plots_dir: directory where to save plots 70f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type plots_dir: str 71f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 72f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param plots_prefix: prefix for plots file names 73f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type plots_prefix: str 749ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 759ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes :param cgroup_info: add cgroup information for sanitization 769ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes example: 779ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes { 789ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 'controller_ids': { 2: 'schedtune', 4: 'cpuset' }, 799ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 'cgroups': [ 'root', 'background', 'foreground' ], # list of allowed cgroup names 809ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes } 819ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes :type cgroup_info: dict 82f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 838e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 844e260b2b7c2b8718781f2fd4b502391ed1465f5aJoel Fernandes def __init__(self, platform, data_dir, events=None, 85b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio tasks=None, window=(0, None), 86b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino normalize_time=True, 8769a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi trace_format='FTrace', 8869a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi plots_dir=None, 899ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes plots_prefix='', 909ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes cgroup_info={}): 918e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 928e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # The platform used to run the experiments 9350b5967280ce939d80f2d8b74253a0130ba16561Patrick Bellasi self.platform = platform 948e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 9534f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi # TRAPpy Trace object 969c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi self.ftrace = None 978e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 9834f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi # Trace format 9934f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = trace_format 10034f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi 101a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi # The time window used to limit trace parsing to 102a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi self.window = window 103a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi 1048e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Dynamically registered TRAPpy events 1058e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.trappy_cls = {} 1068e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1078e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Maximum timespan for all collected events 1088e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.time_range = 0 1098e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 110877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi # Time the system was overutilzied 111877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_time = 0 112877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_prc = 0 113877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 1148e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # The dictionary of tasks descriptors available in the dataset 1158e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks = {} 1168e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 117e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi # List of events required by user 118e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = [] 119e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi 1208e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # List of events available in the parsed trace 1218e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.available_events = [] 1228e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1239e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio # Cluster frequency coherency flag 1249e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio self.freq_coherency = True 1259e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 126f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi # Folder containing all trace data 127f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = None 128f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi 129c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi # Setup logging 130c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log = logging.getLogger('Trace') 131c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 1328e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Folder containing trace 133f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi if not os.path.isdir(data_dir): 134f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = os.path.dirname(data_dir) 135881f14cdb8b78ad422f739fe28cbce2525020430Patrick Bellasi else: 136f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = data_dir 1378e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 13869a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi # By deafult, use the trace dir to save plots 13969a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_dir = plots_dir 14069a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi if self.plots_dir is None: 14169a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_dir = self.data_dir 14269a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_prefix = plots_prefix 14369a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi 1449ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes # Cgroup info for sanitization 1459ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes self.cgroup_info = cgroup_info 1469ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 1474e260b2b7c2b8718781f2fd4b502391ed1465f5aJoel Fernandes self.__registerTraceEvents(events) if events else None 148b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio self.__parseTrace(data_dir, tasks, window, normalize_time, 149b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio trace_format) 1508e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__computeTimeSpan() 1518e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1528224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi # Minimum and Maximum x_time to use for all plots 1538224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = 0 1548224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = self.time_range 1558224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 1568224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi # Reset x axis time range to full scale 1578224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi t_min = self.window[0] 1588224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi t_max = self.window[1] 1598224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.setXTimeRange(t_min, t_max) 1608224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 161f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi self.data_frame = TraceData() 162f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi self._registerDataFrameGetters(self) 163f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi 1646721d173e18d3c56a33fd3f2eb9b50acd675ec27Patrick Bellasi self.analysis = AnalysisRegister(self) 1656721d173e18d3c56a33fd3f2eb9b50acd675ec27Patrick Bellasi 166f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi def _registerDataFrameGetters(self, module): 167f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 168f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Internal utility function that looks up getter functions with a "_dfg_" 169f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio prefix in their name and bounds them to the specified module. 170f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 171f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param module: module to which the function is added 172f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type module: class 173f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 174c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Registering [%s] local data frames', module) 175f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi for func in dir(module): 176f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi if not func.startswith('_dfg_'): 177f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi continue 178f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi dfg_name = func.replace('_dfg_', '') 179f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi dfg_func = getattr(module, func) 180c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug(' %s', dfg_name) 181f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi setattr(self.data_frame, dfg_name, dfg_func) 1828224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 1838224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi def setXTimeRange(self, t_min=None, t_max=None): 184f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 185f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Set x axis time range to the specified values. 186f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 187f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param t_min: lower bound 188f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type t_min: int or float 189f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 190f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param t_max: upper bound 191f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type t_max: int or float 192f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 1938224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi if t_min is None: 1948224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = 0 1958224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi else: 1968224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = t_min 1978224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi if t_max is None: 1988224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = self.time_range 1998224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi else: 2008224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = t_max 201ba2538fac6e49e4cc1c8f4d525970c0f1ae41ed6Brendan Jackman self._log.debug('Set plots time range to (%.6f, %.6f)[s]', 202c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self.x_min, self.x_max) 2038224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 204e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi def __registerTraceEvents(self, events): 205f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 206f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Save a copy of the parsed events. 207e09821241ca9697b75c8a53fb0813212202d1c65Patrick Bellasi 208f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param events: single event name or list of events names 209f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type events: str or list(str) 210f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 211e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi if isinstance(events, basestring): 212e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = events.split(' ') 213e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi elif isinstance(events, list): 214e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = events 215e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi else: 216e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi raise ValueError('Events must be a string or a list of strings') 217602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # Register devlib fake cpu_frequency events 218602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio if 'cpu_frequency' in events: 219602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio self.events.append('cpu_frequency_devlib') 2208e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 221b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino def __parseTrace(self, path, tasks, window, normalize_time, trace_format): 222f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 223f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Internal method in charge of performing the actual parsing of the 224f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio trace. 225f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 226f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param path: path to the trace folder (or trace file) 227f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type path: str 228f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 229f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param tasks: filter data for the specified tasks only 230f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type tasks: list(str) 231f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 232f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param window: time window to consider when parsing the trace 233f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type window: tuple(int, int) 234f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 235f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param normalize_time: normalize trace time stamps 236f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type normalize_time: bool 237f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 238f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param trace_format: format of the trace. Possible values are: 239f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio - FTrace 240f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio - SysTrace 241f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type trace_format: str 242f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 243c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Loading [sched] events from trace in [%s]...', path) 2444e260b2b7c2b8718781f2fd4b502391ed1465f5aJoel Fernandes self._log.debug('Parsing events: %s', self.events if self.events else 'ALL') 24534f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi if trace_format.upper() == 'SYSTRACE' or path.endswith('html'): 246ba2538fac6e49e4cc1c8f4d525970c0f1ae41ed6Brendan Jackman self._log.debug('Parsing SysTrace format...') 247edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino trace_class = trappy.SysTrace 24834f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = 'SysTrace' 24934f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi elif trace_format.upper() == 'FTRACE': 250ba2538fac6e49e4cc1c8f4d525970c0f1ae41ed6Brendan Jackman self._log.debug('Parsing FTrace format...') 251edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino trace_class = trappy.FTrace 25234f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = 'FTrace' 253d02408964a1d1042b99f51ba01989e8cf02478faJavi Merino else: 254d02408964a1d1042b99f51ba01989e8cf02478faJavi Merino raise ValueError("Unknown trace format {}".format(trace_format)) 2558e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2564e260b2b7c2b8718781f2fd4b502391ed1465f5aJoel Fernandes scope = 'custom' if self.events else 'all' 2574e260b2b7c2b8718781f2fd4b502391ed1465f5aJoel Fernandes self.ftrace = trace_class(path, scope=scope, events=self.events, 258b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino window=window, normalize_time=normalize_time) 259edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino 26079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi # Load Functions profiling data 26179a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi has_function_stats = self._loadFunctionsStats(path) 26279a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 2638e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Check for events available on the parsed trace 2648e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__checkAvailableEvents() 2658e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(self.available_events) == 0: 26679a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if has_function_stats: 267c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Trace contains only functions stats') 26879a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return 26979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi raise ValueError('The trace does not contain useful events ' 27079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 'nor function stats') 2718e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2729ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes # Sanitize cgroup info if any 2739ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes self._sanitize_CgroupAttachTask() 2749ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 2751330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes # Santization not possible if platform missing 2761330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes if not self.platform: 2771330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes # Setup internal data reference to interesting events/dataframes 2781330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_SchedLoadAvgCpu() 2791330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_SchedLoadAvgTask() 2801330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_SchedCpuCapacity() 2811330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_SchedBoostCpu() 2821330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_SchedBoostTask() 2831330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_SchedEnergyDiff() 2841330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_SchedOverutilized() 2851330ce42dd0ee40de1ffbf20a0d71b2d431c80e7Joel Fernandes self._sanitize_CpuFrequency() 2868e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2878e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__loadTasksNames(tasks) 2888e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 289db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio # Compute plot window 290db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio if not normalize_time: 291db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio start = self.window[0] 292db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio if self.window[1]: 293db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio duration = min(self.ftrace.get_duration(), self.window[1]) 294db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio else: 295db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio duration = self.ftrace.get_duration() 296db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio self.window = (self.ftrace.basetime + start, 297db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio self.ftrace.basetime + duration) 2988e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 29934f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi def __checkAvailableEvents(self, key=""): 300f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 301f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Internal method used to build a list of available events. 302f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 303f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param key: key to be used for TRAPpy filtering 304f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type key: str 305f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 30634f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi for val in self.ftrace.get_filters(key): 3079c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi obj = getattr(self.ftrace, val) 3088e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(obj.data_frame): 3098e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.available_events.append(val) 310c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Events found on trace:') 3118e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi for evt in self.available_events: 312c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug(' - %s', evt) 3138e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 3148e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def __loadTasksNames(self, tasks): 315f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 316f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Try to load tasks names using one of the supported events. 317f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 318aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :param tasks: list of task names. If None, load all tasks found. 319aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :type tasks: list(str) or NoneType 320f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 32167d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman def load(tasks, event, name_key, pid_key): 32267d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman df = self._dfg_trace_event(event) 323aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman if tasks is None: 324aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman tasks = df[name_key].unique() 32567d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman self.getTasks(df, tasks, name_key=name_key, pid_key=pid_key) 32667d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman self._scanTasks(df, name_key=name_key, pid_key=pid_key) 32712d7ce8db067749087819bf59d86b55d98779514Joel Fernandes self._scanTgids(df) 32867d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman 3298e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if 'sched_switch' in self.available_events: 33067d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman load(tasks, 'sched_switch', 'next_comm', 'next_pid') 33167d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman elif 'sched_load_avg_task' in self.available_events: 33267d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman load(tasks, 'sched_load_avg_task', 'comm', 'pid') 33367d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman else: 334c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Failed to load tasks names from trace events') 3358e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 3368e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def hasEvents(self, dataset): 337f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 338f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Returns True if the specified event is present in the parsed trace, 339f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio False otherwise. 340f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 341f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param dataset: trace event name or list of trace events 342f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type dataset: str or list(str) 343f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 3448e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if dataset in self.available_events: 3458e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return True 3468e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return False 3478e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 3488e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def __computeTimeSpan(self): 349f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 350f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Compute time axis range, considering all the parsed events. 351f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 3528e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ts = sys.maxint 3538e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi te = 0 3548e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 35566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi for events in self.available_events: 356fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event(events) 3578e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(df) == 0: 3588e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 3598e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if (df.index[0]) < ts: 3608e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ts = df.index[0] 3618e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if (df.index[-1]) > te: 3628e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi te = df.index[-1] 3638e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.time_range = te - ts 3648e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 365ba2538fac6e49e4cc1c8f4d525970c0f1ae41ed6Brendan Jackman self._log.debug('Collected events spans a %.3f [s] time interval', 366c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self.time_range) 3678e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 368877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi # Build a stat on trace overutilization 369877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi if self.hasEvents('sched_overutilized'): 370fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_overutilized') 371877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_time = df[df.overutilized == 1].len.sum() 372877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_prc = 100. * self.overutilized_time / self.time_range 373877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 374ba2538fac6e49e4cc1c8f4d525970c0f1ae41ed6Brendan Jackman self._log.debug('Overutilized time: %.6f [s] (%.3f%% of trace time)', 375c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self.overutilized_time, self.overutilized_prc) 376877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 37712d7ce8db067749087819bf59d86b55d98779514Joel Fernandes def _scanTgids(self, df): 37812d7ce8db067749087819bf59d86b55d98779514Joel Fernandes if not '__tgid' in df.columns: 37912d7ce8db067749087819bf59d86b55d98779514Joel Fernandes return 38012d7ce8db067749087819bf59d86b55d98779514Joel Fernandes df = df[['__pid', '__tgid']] 38112d7ce8db067749087819bf59d86b55d98779514Joel Fernandes df = df.drop_duplicates(keep='first').set_index('__pid') 38212d7ce8db067749087819bf59d86b55d98779514Joel Fernandes df.rename(columns = { '__pid': 'pid', '__tgid': 'tgid' }, 38312d7ce8db067749087819bf59d86b55d98779514Joel Fernandes inplace=True) 38412d7ce8db067749087819bf59d86b55d98779514Joel Fernandes self._pid_tgid = df 38512d7ce8db067749087819bf59d86b55d98779514Joel Fernandes 3863a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def _scanTasks(self, df, name_key='comm', pid_key='pid'): 387f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 388f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Extract tasks names and PIDs from the input data frame. The data frame 389f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio should contain a task name column and PID column. 390f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 391f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param df: data frame containing trace events from which tasks names 392f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio and PIDs will be extracted 393f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type df: :mod:`pandas.DataFrame` 394f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 395b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio :param name_key: The name of the dataframe columns containing task 396b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio names 397f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name_key: str 398f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 399f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param pid_key: The name of the dataframe columns containing task PIDs 400f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type pid_key: str 401f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 4024caccc95d240baab7ffb21476de3dcf5a42ef6d6Joel Fernandes df = df[[name_key, pid_key]].drop_duplicates() 4033a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_name = df.set_index(name_key) 404b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio self._tasks_by_pid = df.set_index(pid_key) 4053a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 4063a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def getTaskByName(self, name): 407f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 408f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get the PIDs of all tasks with the specified name. 409f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 410f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param name: task name 411f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name: str 412f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 4133a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if name not in self._tasks_by_name.index: 4143a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [] 4153a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if len(self._tasks_by_name.ix[name].values) > 1: 4163a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return list({task[0] for task in 4173a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_name.ix[name].values}) 4183a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [self._tasks_by_name.ix[name].values[0]] 4193a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 4203a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def getTaskByPid(self, pid): 421f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 422f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get the names of all tasks with the specified PID. 423f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 424f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param name: task PID 425f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name: int 426f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 4273a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if pid not in self._tasks_by_pid.index: 4283a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [] 4293a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if len(self._tasks_by_pid.ix[pid].values) > 1: 4303a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return list({task[0] for task in 4313a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_pid.ix[pid].values}) 4323a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [self._tasks_by_pid.ix[pid].values[0]] 4333a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 43412d7ce8db067749087819bf59d86b55d98779514Joel Fernandes def getTgidFromPid(self, pid): 43512d7ce8db067749087819bf59d86b55d98779514Joel Fernandes return _pid_tgid.ix[pid].values[0] 43612d7ce8db067749087819bf59d86b55d98779514Joel Fernandes 4378e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def getTasks(self, dataframe=None, 438b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio task_names=None, name_key='comm', pid_key='pid'): 439f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 440f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Helper function to get PIDs of specified tasks. 441f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 44207785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman This method can take a Pandas dataset in input to be used to fiter out 443f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio the PIDs of all the specified tasks. If a dataset is not provided, 444f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio previously filtered PIDs are returned. 445f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 44607785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman If a list of task names is not provided, all tasks detected in the trace 44707785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman will be used. The specified dataframe must provide at least two columns 44807785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman reporting the task name and the task PID. The default values of this 44907785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman colums could be specified using the provided parameters. 450f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 451aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :param dataframe: A Pandas dataframe containing at least 'name_key' and 452aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman 'pid_key' columns. If None, the all PIDs are returned. 453f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type dataframe: :mod:`pandas.DataFrame` 454f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 455aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :param task_names: The list of tasks to get the PID of (default: all 456aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman tasks) 457f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type task_names: list(str) 458f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 459b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio :param name_key: The name of the dataframe columns containing task 460b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio names 461f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name_key: str 462f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 463f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param pid_key: The name of the dataframe columns containing task PIDs 464f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type pid_key: str 465f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 4668e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if task_names is None: 4678e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi task_names = self.tasks.keys() 468b196b8cd11030c4353903f18deb30905e406074fBrendan Jackman if dataframe is None: 469b196b8cd11030c4353903f18deb30905e406074fBrendan Jackman return {k: v for k, v in self.tasks.iteritems() if k in task_names} 470b196b8cd11030c4353903f18deb30905e406074fBrendan Jackman df = dataframe 471c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Lookup dataset for tasks...') 4728e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi for tname in task_names: 473c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Lookup for task [%s]...', tname) 474b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio results = df[df[name_key] == tname][[name_key, pid_key]] 475b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio if len(results) == 0: 476c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.error(' task %16s NOT found', tname) 4778e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 4788e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi (name, pid) = results.head(1).values[0] 479b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio if name != tname: 480c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.error(' task %16s NOT found', tname) 4818e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 482b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio if tname not in self.tasks: 4838e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks[tname] = {} 4848e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi pids = list(results[pid_key].unique()) 4858e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks[tname]['pid'] = pids 486c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug(' task %16s found, pid: %s', 487c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi tname, self.tasks[tname]['pid']) 4888e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return self.tasks 4898e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 490fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 491b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 492fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi# DataFrame Getter Methods 493b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 494fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 4958e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def df(self, event): 496f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 497f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get a dataframe containing all occurrences of the specified trace event 498f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio in the parsed trace. 499f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 500f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param event: Trace event name 501f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type event: str 502f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 503fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi warnings.simplefilter('always', DeprecationWarning) #turn off filter 504fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi warnings.warn("\n\tUse of Trace::df() is deprecated and will be soon removed." 505fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi "\n\tUse Trace::data_frame.trace_event(event_name) instead.", 506fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi category=DeprecationWarning) 507fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi warnings.simplefilter('default', DeprecationWarning) #reset filter 508fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi return self._dfg_trace_event(event) 509fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 510fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi def _dfg_trace_event(self, event): 5118e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi """ 512f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get a dataframe containing all occurrences of the specified trace event 513f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio in the parsed trace. 514f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 515f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param event: Trace event name 516f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type event: str 5178e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi """ 518f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi if self.data_dir is None: 5198e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi raise ValueError("trace data not (yet) loaded") 5209c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi if self.ftrace and hasattr(self.ftrace, event): 5219c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi return getattr(self.ftrace, event).data_frame 522b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio raise ValueError('Event [{}] not supported. ' 523b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 'Supported events are: {}' 52466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi .format(event, self.available_events)) 5258e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 526ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi def _dfg_functions_stats(self, functions=None): 527ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi """ 528ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi Get a DataFrame of specified kernel functions profile data 529ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 530ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi For each profiled function a DataFrame is returned which reports stats 531ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi on kernel functions execution time. The reported stats are per-CPU and 532ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi includes: number of times the function has been executed (hits), 533ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi average execution time (avg), overall execution time (time) and samples 534ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi variance (s_2). 535ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi By default returns a DataFrame of all the functions profiled. 536ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 537ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi :param functions: the name of the function or a list of function names 538ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi to report 539f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type functions: str or list(str) 540ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi """ 541ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if not hasattr(self, '_functions_stats_df'): 542ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return None 543ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi df = self._functions_stats_df 544ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if not functions: 545ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return df 546ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return df.loc[df.index.get_level_values(1).isin(listify(functions))] 547ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 5480e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # cgroup_attach_task with just merged fake and real events 5490e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes def _cgroup_attach_task(self): 5509ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes cgroup_events = ['cgroup_attach_task', 'cgroup_attach_task_devlib'] 5519ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes df = None 5529ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 553d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes if set(cgroup_events).isdisjoint(set(self.available_events)): 554d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes self._log.error('atleast one of {} is needed for cgroup_attach_task event generation'.format(cgroup_events)) 555d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes return None 556d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes 5579ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes for cev in cgroup_events: 5589ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes if not cev in self.available_events: 5599ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes continue 5609ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes cdf = self._dfg_trace_event(cev) 561e82d56694c9f909009d7348f8c9265fd4810eea9Joel Fernandes cdf = cdf[['__line', 'pid', 'controller', 'cgroup']] 5629ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes if not isinstance(df, pd.DataFrame): 5639ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes df = cdf 5649ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes else: 5659ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes df = pd.concat([cdf, df]) 5669ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 5670e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # Always drop na since this DF is used as secondary 5680e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes df.dropna(inplace=True, how='any') 5699ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes return df 5709ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 571dbe282d7a48bbb8b93ff1e2ee944f6ff4fbcfebfJoel Fernandes @memoized 5720e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes def _dfg_cgroup_attach_task(self, controllers = ['schedtune', 'cpuset']): 5730e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # Since fork doesn't result in attach events, generate fake attach events 5740e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # The below mechanism doesn't work to propogate nested fork levels: 5750e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # For ex: 5760e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # cgroup_attach_task: pid=1166 5770e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # fork: pid=1166 child_pid=2222 <-- fake attach generated 5780e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # fork: pid=2222 child_pid=3333 <-- fake attach not generated 5790e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes def fork_add_cgroup(fdf, cdf, controller): 5800e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes cdf = cdf[cdf['controller'] == controller] 5810e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes ret_df = trappy.utils.merge_dfs(fdf, cdf, pivot='pid') 5820e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes return ret_df 5830e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 584d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes if not 'sched_process_fork' in self.available_events: 585d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes self._log.error('sched_process_fork is mandatory to get proper cgroup_attach events') 586d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes return None 5870e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes fdf = self._dfg_trace_event('sched_process_fork') 5880e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 5890e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes forks_len = len(fdf) 5900e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes forkdf = fdf 5910e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes cdf = self._cgroup_attach_task() 5920e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes for idx, c in enumerate(controllers): 5930e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes fdf = fork_add_cgroup(fdf, cdf, c) 5940e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes if (idx != (len(controllers) - 1)): 595304c111f5a33409220adf13bb9c69cd2727f5aa0Joel Fernandes fdf = pd.concat([fdf, forkdf]).sort_values(by='__line') 5960e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 5970e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes fdf = fdf[['__line', 'child_pid', 'controller', 'cgroup']] 5980e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes fdf.rename(columns = { 'child_pid': 'pid' }, inplace=True) 5990e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 6000e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes # Always drop na since this DF is used as secondary 6010e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes fdf.dropna(inplace=True, how='any') 6020e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 6030e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes new_forks_len = len(fdf) / len(controllers) 6040e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 605304c111f5a33409220adf13bb9c69cd2727f5aa0Joel Fernandes fdf = pd.concat([fdf, cdf]).sort_values(by='__line') 6060e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 6070e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes if new_forks_len < forks_len: 6080e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes dropped = forks_len - new_forks_len 6090e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes self._log.info("Couldn't attach all forks cgroup with-attach events ({} dropped)".format(dropped)) 6100e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes return fdf 6110e2f35b9031b3f2d2701ebfb7c7a73bb81b2111bJoel Fernandes 612dbe282d7a48bbb8b93ff1e2ee944f6ff4fbcfebfJoel Fernandes @memoized 61365039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes def _dfg_sched_switch_cgroup(self, controllers = ['schedtune', 'cpuset']): 61465039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes def sched_switch_add_cgroup(sdf, cdf, controller, direction): 61565039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes cdf = cdf[cdf['controller'] == controller] 61665039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes 61765039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes ret_df = sdf.rename(columns = { direction + '_pid': 'pid' }) 61865039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes ret_df = trappy.utils.merge_dfs(ret_df, cdf, pivot='pid') 61965039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes ret_df.rename(columns = { 'pid': direction + '_pid' }, inplace=True) 62065039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes 62165039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes ret_df.drop('controller', axis=1, inplace=True) 62265039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes ret_df.rename(columns = { 'cgroup': direction + '_' + controller }, inplace=True) 62365039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes return ret_df 62465039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes 625d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes if not 'sched_switch' in self.available_events: 626d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes self._log.error('sched_switch is mandatory to generate sched_switch_cgroup event') 627d0253ba206620c79c0abf2adfb27fc921ca05d81Joel Fernandes return None 62865039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes sdf = self._dfg_trace_event('sched_switch') 62965039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes cdf = self._dfg_cgroup_attach_task() 63065039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes 63165039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes for c in controllers: 63265039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes sdf = sched_switch_add_cgroup(sdf, cdf, c, 'next') 63365039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes sdf = sched_switch_add_cgroup(sdf, cdf, c, 'prev') 63465039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes 63512d7ce8db067749087819bf59d86b55d98779514Joel Fernandes # Augment with TGID information 63612d7ce8db067749087819bf59d86b55d98779514Joel Fernandes sdf = sdf.join(self._pid_tgid, on='next_pid').rename(columns = {'tgid': 'next_tgid'}) 63712d7ce8db067749087819bf59d86b55d98779514Joel Fernandes sdf = sdf.join(self._pid_tgid, on='prev_pid').rename(columns = {'tgid': 'prev_tgid'}) 638063cbf3392db88e1dbe454be1f25db4640b63423Joel Fernandes 639063cbf3392db88e1dbe454be1f25db4640b63423Joel Fernandes df = self._tasks_by_pid.rename(columns = { 'next_comm': 'comm' }) 640063cbf3392db88e1dbe454be1f25db4640b63423Joel Fernandes sdf = sdf.join(df, on='next_tgid').rename(columns = {'comm': 'next_tgid_comm'}) 641063cbf3392db88e1dbe454be1f25db4640b63423Joel Fernandes sdf = sdf.join(df, on='prev_tgid').rename(columns = {'comm': 'prev_tgid_comm'}) 64265039ca96253a8791c682fd35910ca40b3e8cc5bJoel Fernandes return sdf 6435824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi 644b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 645fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi# Trace Events Sanitize Methods 646b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 647fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 648c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedCpuCapacity(self): 649f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 650f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Add more columns to cpu_capacity data frame if the energy model is 651f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio available. 652f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 65366b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('cpu_capacity') \ 65466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi or 'nrg_model' not in self.platform: 655680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi return 656680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi 657fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('cpu_capacity') 65866b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi 6598e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Add column with LITTLE and big CPUs max capacities 6608e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi nrg_model = self.platform['nrg_model'] 6618e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi max_lcap = nrg_model['little']['cpu']['cap_max'] 6628e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi max_bcap = nrg_model['big']['cpu']['cap_max'] 6638e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['max_capacity'] = np.select( 6648e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 6658e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [max_lcap], max_bcap) 6668e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Add LITTLE and big CPUs "tipping point" threshold 6678e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi tip_lcap = 0.8 * max_lcap 6688e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi tip_bcap = 0.8 * max_bcap 6698e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['tip_capacity'] = np.select( 6708e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 6718e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [tip_lcap], tip_bcap) 6728e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 673997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi def _sanitize_SchedLoadAvgCpu(self): 674f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 675f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio If necessary, rename certain signal names from v5.0 to v5.1 format. 676f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 67766b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_load_avg_cpu'): 67866b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 679fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_load_avg_cpu') 680997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi if 'utilization' in df: 681b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'utilization': 'util_avg'}, inplace=True) 682b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'load': 'load_avg'}, inplace=True) 683997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi 684c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedLoadAvgTask(self): 685f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 686f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio If necessary, rename certain signal names from v5.0 to v5.1 format. 687f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 68866b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_load_avg_task'): 68966b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 690fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_load_avg_task') 69117c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi if 'utilization' in df: 692b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'utilization': 'util_avg'}, inplace=True) 693b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'load': 'load_avg'}, inplace=True) 694b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'avg_period': 'period_contrib'}, inplace=True) 695b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'runnable_avg_sum': 'load_sum'}, inplace=True) 696b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'running_avg_sum': 'util_sum'}, inplace=True) 6978e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['cluster'] = np.select( 6988e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 6998e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ['LITTLE'], 'big') 7009d69537e219bc1052a28be114cb14ad47cc22c8fPatrick Bellasi # Add a column which represents the max capacity of the smallest 7019d69537e219bc1052a28be114cb14ad47cc22c8fPatrick Bellasi # clustre which can accomodate the task utilization 702b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio little_cap = self.platform['nrg_model']['little']['cpu']['cap_max'] 703b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio big_cap = self.platform['nrg_model']['big']['cpu']['cap_max'] 7049d69537e219bc1052a28be114cb14ad47cc22c8fPatrick Bellasi df['min_cluster_cap'] = df.util_avg.map( 705b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio lambda util_avg: big_cap if util_avg > little_cap else little_cap 706b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio ) 7078e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 708c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedBoostCpu(self): 709f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 710f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Add a boosted utilization signal as the sum of utilization and margin. 711f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 712f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Also, if necessary, rename certain signal names from v5.0 to v5.1 713f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio format. 714f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 71566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_boost_cpu'): 71666b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 717fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_boost_cpu') 71817c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi if 'usage' in df: 719b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'usage': 'util'}, inplace=True) 72017c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df['boosted_util'] = df['util'] + df['margin'] 72117c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi 722c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedBoostTask(self): 723f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 724f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Add a boosted utilization signal as the sum of utilization and margin. 725f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 726f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Also, if necessary, rename certain signal names from v5.0 to v5.1 727f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio format. 728f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 72966b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_boost_task'): 73066b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 731fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_boost_task') 732418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi if 'utilization' in df: 733418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi # Convert signals name from to v5.1 format 734b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'utilization': 'util'}, inplace=True) 735418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi df['boosted_util'] = df['util'] + df['margin'] 7368e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 737c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedEnergyDiff(self): 738f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 739f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio If a energy model is provided, some signals are added to the 740f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio sched_energy_diff trace event data frame. 7415439b256782dc2a902146b5bea9b957b9dbdea58Brendan Jackman 7425439b256782dc2a902146b5bea9b957b9dbdea58Brendan Jackman Also convert between existing field name formats for sched_energy_diff 743f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 74466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_energy_diff') \ 74566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi or 'nrg_model' not in self.platform: 746680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi return 7478e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi nrg_model = self.platform['nrg_model'] 7488e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_lcluster = nrg_model['little']['cluster'] 7498e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_bcluster = nrg_model['big']['cluster'] 7508e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_lcpu = nrg_model['little']['cpu'] 7518e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_bcpu = nrg_model['big']['cpu'] 7528e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi lcpus = len(self.platform['clusters']['little']) 7538e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi bcpus = len(self.platform['clusters']['big']) 7548e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi SCHED_LOAD_SCALE = 1024 7558e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 7568e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi power_max = em_lcpu['nrg_max'] * lcpus + em_bcpu['nrg_max'] * bcpus + \ 757b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio em_lcluster['nrg_max'] + em_bcluster['nrg_max'] 7588f7f28b61f6f4bf6d43f2919886a4bc51578a659Brendan Jackman self._log.debug( 7598f7f28b61f6f4bf6d43f2919886a4bc51578a659Brendan Jackman "Maximum estimated system energy: {0:d}".format(power_max)) 7608e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 761fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_energy_diff') 7625439b256782dc2a902146b5bea9b957b9dbdea58Brendan Jackman 7633e798bfa116035c12353783e803516880794976aPatrick Bellasi translations = {'nrg_d' : 'nrg_diff', 7643e798bfa116035c12353783e803516880794976aPatrick Bellasi 'utl_d' : 'usage_delta', 7653e798bfa116035c12353783e803516880794976aPatrick Bellasi 'payoff' : 'nrg_payoff' 7663e798bfa116035c12353783e803516880794976aPatrick Bellasi } 7675439b256782dc2a902146b5bea9b957b9dbdea58Brendan Jackman df.rename(columns=translations, inplace=True) 7685439b256782dc2a902146b5bea9b957b9dbdea58Brendan Jackman 7698e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['nrg_diff_pct'] = SCHED_LOAD_SCALE * df.nrg_diff / power_max 7708e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 7718e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Tag columns by usage_delta 7728e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ccol = df.usage_delta 7738e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['usage_delta_group'] = np.select( 7748e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [ccol < 150, ccol < 400, ccol < 600], 7758e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ['< 150', '< 400', '< 600'], '>= 600') 7768e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 7778e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Tag columns by nrg_payoff 7788e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ccol = df.nrg_payoff 7798e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['nrg_payoff_group'] = np.select( 7808e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [ccol > 2e9, ccol > 0, ccol > -2e9], 781b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio ['Optimal Accept', 'SchedTune Accept', 'SchedTune Reject'], 782b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 'Suboptimal Reject') 7838e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 784877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi def _sanitize_SchedOverutilized(self): 785f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ Add a column with overutilized status duration. """ 786877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi if not self.hasEvents('sched_overutilized'): 787877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi return 788fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_overutilized') 789877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df['start'] = df.index 790877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df['len'] = (df.start - df.start.shift()).fillna(0).shift(-1) 791877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df.drop('start', axis=1, inplace=True) 7929e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 7939ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes # Sanitize cgroup information helper 7949ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes def _helper_sanitize_CgroupAttachTask(self, df, allowed_cgroups, controller_id_name): 795b27ac8f8ba1027eebe95725edc45aeaac1bd9e27Joel Fernandes # Drop rows that aren't in the root-id -> name map 796b27ac8f8ba1027eebe95725edc45aeaac1bd9e27Joel Fernandes df = df[df['dst_root'].isin(controller_id_name.keys())] 797b27ac8f8ba1027eebe95725edc45aeaac1bd9e27Joel Fernandes 7989ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes def get_cgroup_name(path, valid_names): 7999ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes name = os.path.basename(path) 8009ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes name = 'root' if not name in valid_names else name 8019ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes return name 8029ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 8039ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes def get_cgroup_names(rows): 8049ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes ret = [] 8059ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes for r in rows.iterrows(): 8069ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes ret.append(get_cgroup_name(r[1]['dst_path'], allowed_cgroups)) 8079ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes return ret 8089ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 8099ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes def get_controller_names(rows): 8109ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes ret = [] 8119ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes for r in rows.iterrows(): 8129ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes ret.append(controller_id_name[r[1]['dst_root']]) 8139ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes return ret 8149ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 8159ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes # Sanitize cgroup names 8169ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes # cgroup column isn't in mainline, add it in 8179ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes # its already added for some out of tree kernels so check first 8189ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes if not 'cgroup' in df.columns: 8199ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes if not 'dst_path' in df.columns: 8209ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes raise RuntimeError('Cant santize cgroup DF, need dst_path') 8219ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes df = df.assign(cgroup = get_cgroup_names) 8229ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 8239ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes # Sanitize controller names 8249ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes if not 'controller' in df.columns: 8259ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes if not 'dst_root' in df.columns: 8269ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes raise RuntimeError('Cant santize cgroup DF, need dst_path') 8279ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes df = df.assign(controller = get_controller_names) 8289ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 8299ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes return df 8309ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 8319ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes def _sanitize_CgroupAttachTask(self): 8329ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes def sanitize_cgroup_event(name): 8339ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes if not name in self.available_events: 8349ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes return 8355bb44a7d61d5bb160d8207cf085ea5375bfe8f2dJoel Fernandes 8369ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes df = self._dfg_trace_event(name) 8375bb44a7d61d5bb160d8207cf085ea5375bfe8f2dJoel Fernandes 8385bb44a7d61d5bb160d8207cf085ea5375bfe8f2dJoel Fernandes if len(df.groupby(level=0).filter(lambda x: len(x) > 1)) > 0: 8395bb44a7d61d5bb160d8207cf085ea5375bfe8f2dJoel Fernandes self._log.warning('Timstamp Collisions seen in {} event!'.format(name)) 8405bb44a7d61d5bb160d8207cf085ea5375bfe8f2dJoel Fernandes 8419ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes df = self._helper_sanitize_CgroupAttachTask(df, self.cgroup_info['cgroups'], 8429ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes self.cgroup_info['controller_ids']) 8439ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes getattr(self.ftrace, name).data_frame = df 8449ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes sanitize_cgroup_event('cgroup_attach_task') 8459ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes sanitize_cgroup_event('cgroup_attach_task_devlib') 8469ceeb1caf9293d1b5e8f5b6d23c0ed5079dfd9c8Joel Fernandes 84747895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi def _chunker(self, seq, size): 848f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 849f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Given a data frame or a series, generate a sequence of chunks of the 850f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio given size. 851f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 852f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param seq: data to be split into chunks 853f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type seq: :mod:`pandas.Series` or :mod:`pandas.DataFrame` 854f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 855f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param size: size of each chunk 856f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type size: int 857f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 8589e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return (seq.iloc[pos:pos + size] for pos in range(0, len(seq), size)) 8599e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 86047895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi def _sanitize_CpuFrequency(self): 861f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 862f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Verify that all platform reported clusters are frequency coherent (i.e. 863f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio frequency scaling is performed at a cluster level). 864f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 865602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio if not self.hasEvents('cpu_frequency_devlib'): 8669e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return 867602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio 868602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio devlib_freq = self._dfg_trace_event('cpu_frequency_devlib') 869602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio devlib_freq.rename(columns={'cpu_id':'cpu'}, inplace=True) 870602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio devlib_freq.rename(columns={'state':'frequency'}, inplace=True) 871602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio 872fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('cpu_frequency') 8739e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio clusters = self.platform['clusters'] 874602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio 875602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # devlib always introduces fake cpu_frequency events, in case the 876602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # OS has not generated cpu_frequency envets there are the only 877602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # frequency events to report 878602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio if len(df) == 0: 879602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # Register devlib injected events as 'cpu_frequency' events 880602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio setattr(self.ftrace.cpu_frequency, 'data_frame', devlib_freq) 881602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio df = devlib_freq 882602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio self.available_events.append('cpu_frequency') 883602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio 884602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # make sure fake cpu_frequency events are never interleaved with 885602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # OS generated events 886602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio else: 887602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio if len(devlib_freq) > 0: 88893f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi 88993f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # Frequencies injection is done in a per-cluster based. 89093f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # This is based on the assumption that clusters are 89193f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # frequency choerent. 89293f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # For each cluster we inject devlib events only if 89393f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # these events does not overlaps with os-generated ones. 89493f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi 89593f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # Inject "initial" devlib frequencies 89693f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi os_df = df 89793f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi dl_df = devlib_freq.iloc[:self.platform['cpus_count']] 89893f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi for _,c in self.platform['clusters'].iteritems(): 89993f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi dl_freqs = dl_df[dl_df.cpu.isin(c)] 90093f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi os_freqs = os_df[os_df.cpu.isin(c)] 90193f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi self._log.debug("First freqs for %s:\n%s", c, dl_freqs) 90293f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # All devlib events "before" os-generated events 90393f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi self._log.debug("Min os freq @: %s", os_freqs.index.min()) 90493f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi if os_freqs.empty or \ 90593f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi os_freqs.index.min() > dl_freqs.index.max(): 90693f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi self._log.debug("Insert devlib freqs for %s", c) 90793f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi df = pd.concat([dl_freqs, df]) 90893f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi 90993f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # Inject "final" devlib frequencies 91093f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi os_df = df 91193f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi dl_df = devlib_freq.iloc[self.platform['cpus_count']:] 91293f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi for _,c in self.platform['clusters'].iteritems(): 91393f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi dl_freqs = dl_df[dl_df.cpu.isin(c)] 91493f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi os_freqs = os_df[os_df.cpu.isin(c)] 91593f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi self._log.debug("Last freqs for %s:\n%s", c, dl_freqs) 91693f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi # All devlib events "after" os-generated events 91793f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi self._log.debug("Max os freq @: %s", os_freqs.index.max()) 91893f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi if os_freqs.empty or \ 91993f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi os_freqs.index.max() < dl_freqs.index.min(): 92093f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi self._log.debug("Append devlib freqs for %s", c) 92193f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi df = pd.concat([df, dl_freqs]) 92293f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi 92393f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi df.sort_index(inplace=True) 92493f88632840e58b03a2600d1956ea064a13f69e5Patrick Bellasi 925602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio setattr(self.ftrace.cpu_frequency, 'data_frame', df) 926602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio 927602f6c82b6cf07634b51451c59dbb23bd768a8b9Michele Di Giorgio # Frequency Coherency Check 928b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio for _, cpus in clusters.iteritems(): 9299e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio cluster_df = df[df.cpu.isin(cpus)] 93047895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi for chunk in self._chunker(cluster_df, len(cpus)): 9319e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio f = chunk.iloc[0].frequency 9329e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio if any(chunk.frequency != f): 933c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Cluster Frequency is not coherent! ' 934c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 'Failure in [cpu_frequency] events at:') 935c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning(chunk) 9369e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio self.freq_coherency = False 9379e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return 938c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Platform clusters verified to be Frequency coherent') 93947895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi 940b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 941f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi# Utility Methods 942b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 943f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi 9445824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi def integrate_square_wave(self, sq_wave): 9455824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi """ 9465824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi Compute the integral of a square wave time series. 9475824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi 9485824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi :param sq_wave: square wave assuming only 1.0 and 0.0 values 9495824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi :type sq_wave: :mod:`pandas.Series` 9505824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi """ 9515824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi sq_wave.iloc[-1] = 0.0 9525824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi # Compact signal to obtain only 1-0-1-0 sequences 9535824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi comp_sig = sq_wave.loc[sq_wave.shift() != sq_wave] 9545824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi # First value for computing the difference must be a 1 9555824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi if comp_sig.iloc[0] == 0.0: 9565824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi return sum(comp_sig.iloc[2::2].index - comp_sig.iloc[1:-1:2].index) 9575824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi else: 9585824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi return sum(comp_sig.iloc[1::2].index - comp_sig.iloc[:-1:2].index) 9595824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi 960ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi def _loadFunctionsStats(self, path='trace.stats'): 961f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 962f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Read functions profiling file and build a data frame containing all 963f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio relevant data. 964f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 965f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param path: path to the functions profiling trace file 966f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type path: str 967f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 968ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if os.path.isdir(path): 969ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi path = os.path.join(path, 'trace.stats') 970ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if path.endswith('dat') or path.endswith('html'): 971ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi pre, ext = os.path.splitext(path) 972ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi path = pre + '.stats' 973ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if not os.path.isfile(path): 974ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return False 975ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 976ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi # Opening functions profiling JSON data file 977c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Loading functions profiling data from [%s]...', path) 978ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi with open(os.path.join(path), 'r') as fh: 979ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi trace_stats = json.load(fh) 980ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 981ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi # Build DataFrame of function stats 982ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi frames = {} 983ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi for cpu, data in trace_stats.iteritems(): 984ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi frames[int(cpu)] = pd.DataFrame.from_dict(data, orient='index') 985ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 986ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi # Build and keep track of the DataFrame 987b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio self._functions_stats_df = pd.concat(frames.values(), 988b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio keys=frames.keys()) 989ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 990ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return len(self._functions_stats_df) > 0 991ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 992691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio @memoized 993691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio def getCPUActiveSignal(self, cpu): 994691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 995691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio Build a square wave representing the active (i.e. non-idle) CPU time, 996691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio i.e.: 99724494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman 99824494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman cpu_active[t] == 1 if the CPU is reported to be non-idle by cpuidle at 99924494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman time t 100024494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman cpu_active[t] == 0 otherwise 1001691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1002691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :param cpu: CPU ID 1003691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :type cpu: int 1004691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1005ac4e391db53c274712f31e7a1048a27bb1a5d7cfBrendan Jackman :returns: A :mod:`pandas.Series` or ``None`` if the trace contains no 1006ac4e391db53c274712f31e7a1048a27bb1a5d7cfBrendan Jackman "cpu_idle" events 1007691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 1008691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio if not self.hasEvents('cpu_idle'): 1009c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Events [cpu_idle] not found, ' 1010c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 'cannot compute CPU active signal!') 1011691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio return None 1012691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1013691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio idle_df = self._dfg_trace_event('cpu_idle') 1014691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cpu_df = idle_df[idle_df.cpu_id == cpu] 1015691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1016691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cpu_active = cpu_df.state.apply( 1017691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio lambda s: 1 if s == NON_IDLE_STATE else 0 1018691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio ) 1019691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1020691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio start_time = 0.0 1021691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio if not self.ftrace.normalized_time: 1022691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio start_time = self.ftrace.basetime 102320a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman 102420a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman if cpu_active.empty: 102520a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman cpu_active = pd.Series([0], index=[start_time]) 102620a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman elif cpu_active.index[0] != start_time: 1027691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio entry_0 = pd.Series(cpu_active.iloc[0] ^ 1, index=[start_time]) 1028691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cpu_active = pd.concat([entry_0, cpu_active]) 1029691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1030d1ed4c86118d4a2231231d185b423e90ac38df56Patrick Bellasi # Fix sequences of wakeup/sleep events reported with the same index 1031d1ed4c86118d4a2231231d185b423e90ac38df56Patrick Bellasi return handle_duplicate_index(cpu_active) 1032d1ed4c86118d4a2231231d185b423e90ac38df56Patrick Bellasi 1033691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1034691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio @memoized 1035691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio def getClusterActiveSignal(self, cluster): 1036691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 1037691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio Build a square wave representing the active (i.e. non-idle) cluster 1038691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio time, i.e.: 103924494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman 104024494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman cluster_active[t] == 1 if at least one CPU is reported to be non-idle 104124494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman by CPUFreq at time t 104224494084386ca0664120df7aeccd7f3c9bde5057Brendan Jackman cluster_active[t] == 0 otherwise 1043691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1044691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :param cluster: list of CPU IDs belonging to a cluster 1045691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :type cluster: list(int) 1046691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1047ac4e391db53c274712f31e7a1048a27bb1a5d7cfBrendan Jackman :returns: A :mod:`pandas.Series` or ``None`` if the trace contains no 1048ac4e391db53c274712f31e7a1048a27bb1a5d7cfBrendan Jackman "cpu_idle" events 1049691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 1050691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio if not self.hasEvents('cpu_idle'): 1051c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Events [cpu_idle] not found, ' 1052c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 'cannot compute cluster active signal!') 1053691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio return None 1054691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1055403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio active = self.getCPUActiveSignal(cluster[0]).to_frame(name=cluster[0]) 1056403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio for cpu in cluster[1:]: 1057403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio active = active.join( 1058403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio self.getCPUActiveSignal(cpu).to_frame(name=cpu), 1059403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio how='outer' 1060403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio ) 1061691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1062691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio active.fillna(method='ffill', inplace=True) 1063691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1064691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio # Cluster active is the OR between the actives on each CPU 1065691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio # belonging to that specific cluster 1066691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cluster_active = reduce( 1067691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio operator.or_, 1068691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio [cpu_active.astype(int) for _, cpu_active in 1069691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio active.iteritems()] 1070691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio ) 1071691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1072691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio return cluster_active 1073691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 1074b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 1075f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasiclass TraceData: 1076b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio """ A DataFrame collector exposed to Trace's clients """ 1077f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi pass 1078f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi 1079b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio# vim :set tabstop=4 shiftwidth=4 expandtab 1080