trace.py revision c278c2343c7f25083a80cb164b6bdc761d50050b
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 3379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasifrom trappy.utils import listify 348e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 358e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 36691fc118e5dff4df885a039cc855a746de4b7556Michele Di GiorgioNON_IDLE_STATE = 4294967295 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 74f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 758e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 76f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi def __init__(self, platform, data_dir, events, 77b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio tasks=None, window=(0, None), 78b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino normalize_time=True, 7969a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi trace_format='FTrace', 8069a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi plots_dir=None, 8169a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi plots_prefix=''): 828e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 838e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # The platform used to run the experiments 8450b5967280ce939d80f2d8b74253a0130ba16561Patrick Bellasi self.platform = platform 858e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 8634f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi # TRAPpy Trace object 879c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi self.ftrace = None 888e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 8934f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi # Trace format 9034f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = trace_format 9134f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi 92a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi # The time window used to limit trace parsing to 93a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi self.window = window 94a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi 958e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Dynamically registered TRAPpy events 968e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.trappy_cls = {} 978e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 988e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Maximum timespan for all collected events 998e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.time_range = 0 1008e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 101877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi # Time the system was overutilzied 102877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_time = 0 103877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_prc = 0 104877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 1058e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # The dictionary of tasks descriptors available in the dataset 1068e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks = {} 1078e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 108e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi # List of events required by user 109e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = [] 110e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi 1118e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # List of events available in the parsed trace 1128e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.available_events = [] 1138e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1149e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio # Cluster frequency coherency flag 1159e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio self.freq_coherency = True 1169e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 117f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi # Folder containing all trace data 118f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = None 119f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi 120c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi # Setup logging 121c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log = logging.getLogger('Trace') 122c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 1238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Folder containing trace 124f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi if not os.path.isdir(data_dir): 125f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = os.path.dirname(data_dir) 126881f14cdb8b78ad422f739fe28cbce2525020430Patrick Bellasi else: 127f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = data_dir 1288e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 12969a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi # By deafult, use the trace dir to save plots 13069a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_dir = plots_dir 13169a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi if self.plots_dir is None: 13269a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_dir = self.data_dir 13369a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_prefix = plots_prefix 13469a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi 135e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.__registerTraceEvents(events) 136b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio self.__parseTrace(data_dir, tasks, window, normalize_time, 137b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio trace_format) 1388e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__computeTimeSpan() 1398e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1408224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi # Minimum and Maximum x_time to use for all plots 1418224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = 0 1428224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = self.time_range 1438224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 1448224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi # Reset x axis time range to full scale 1458224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi t_min = self.window[0] 1468224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi t_max = self.window[1] 1478224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.setXTimeRange(t_min, t_max) 1488224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 149f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi self.data_frame = TraceData() 150f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi self._registerDataFrameGetters(self) 151f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi 1526721d173e18d3c56a33fd3f2eb9b50acd675ec27Patrick Bellasi self.analysis = AnalysisRegister(self) 1536721d173e18d3c56a33fd3f2eb9b50acd675ec27Patrick Bellasi 154f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi def _registerDataFrameGetters(self, module): 155f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 156f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Internal utility function that looks up getter functions with a "_dfg_" 157f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio prefix in their name and bounds them to the specified module. 158f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 159f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param module: module to which the function is added 160f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type module: class 161f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 162c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Registering [%s] local data frames', module) 163f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi for func in dir(module): 164f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi if not func.startswith('_dfg_'): 165f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi continue 166f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi dfg_name = func.replace('_dfg_', '') 167f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi dfg_func = getattr(module, func) 168c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug(' %s', dfg_name) 169f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi setattr(self.data_frame, dfg_name, dfg_func) 1708224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 1718224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi def setXTimeRange(self, t_min=None, t_max=None): 172f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 173f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Set x axis time range to the specified values. 174f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 175f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param t_min: lower bound 176f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type t_min: int or float 177f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 178f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param t_max: upper bound 179f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type t_max: int or float 180f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 1818224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi if t_min is None: 1828224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = 0 1838224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi else: 1848224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = t_min 1858224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi if t_max is None: 1868224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = self.time_range 1878224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi else: 1888224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = t_max 189c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Set plots time range to (%.6f, %.6f)[s]', 190c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self.x_min, self.x_max) 1918224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 192e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi def __registerTraceEvents(self, events): 193f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 194f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Save a copy of the parsed events. 195e09821241ca9697b75c8a53fb0813212202d1c65Patrick Bellasi 196f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param events: single event name or list of events names 197f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type events: str or list(str) 198f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 199e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi if isinstance(events, basestring): 200e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = events.split(' ') 201e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi elif isinstance(events, list): 202e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = events 203e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi else: 204e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi raise ValueError('Events must be a string or a list of strings') 2058e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 206b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino def __parseTrace(self, path, tasks, window, normalize_time, trace_format): 207f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 208f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Internal method in charge of performing the actual parsing of the 209f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio trace. 210f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 211f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param path: path to the trace folder (or trace file) 212f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type path: str 213f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 214f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param tasks: filter data for the specified tasks only 215f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type tasks: list(str) 216f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 217f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param window: time window to consider when parsing the trace 218f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type window: tuple(int, int) 219f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 220f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param normalize_time: normalize trace time stamps 221f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type normalize_time: bool 222f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 223f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param trace_format: format of the trace. Possible values are: 224f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio - FTrace 225f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio - SysTrace 226f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type trace_format: str 227f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 228c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Loading [sched] events from trace in [%s]...', path) 229c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Parsing events: %s', self.events) 23034f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi if trace_format.upper() == 'SYSTRACE' or path.endswith('html'): 231c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Parsing SysTrace format...') 232edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino trace_class = trappy.SysTrace 23334f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = 'SysTrace' 23434f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi elif trace_format.upper() == 'FTRACE': 235c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Parsing FTrace format...') 236edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino trace_class = trappy.FTrace 23734f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = 'FTrace' 238d02408964a1d1042b99f51ba01989e8cf02478faJavi Merino else: 239d02408964a1d1042b99f51ba01989e8cf02478faJavi Merino raise ValueError("Unknown trace format {}".format(trace_format)) 2408e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 241edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino self.ftrace = trace_class(path, scope="custom", events=self.events, 242b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino window=window, normalize_time=normalize_time) 243edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino 24479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi # Load Functions profiling data 24579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi has_function_stats = self._loadFunctionsStats(path) 24679a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 2478e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Check for events available on the parsed trace 2488e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__checkAvailableEvents() 2498e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(self.available_events) == 0: 25079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if has_function_stats: 251c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Trace contains only functions stats') 25279a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return 25379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi raise ValueError('The trace does not contain useful events ' 25479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 'nor function stats') 2558e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2568e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Setup internal data reference to interesting events/dataframes 2578e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 25866b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedLoadAvgCpu() 25966b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedLoadAvgTask() 26066b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedCpuCapacity() 26166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedBoostCpu() 26266b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedBoostTask() 26366b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedEnergyDiff() 26466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedOverutilized() 26547895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi self._sanitize_CpuFrequency() 2668e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2678e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__loadTasksNames(tasks) 2688e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 269db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio # Compute plot window 270db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio if not normalize_time: 271db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio start = self.window[0] 272db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio if self.window[1]: 273db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio duration = min(self.ftrace.get_duration(), self.window[1]) 274db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio else: 275db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio duration = self.ftrace.get_duration() 276db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio self.window = (self.ftrace.basetime + start, 277db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio self.ftrace.basetime + duration) 2788e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 27934f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi def __checkAvailableEvents(self, key=""): 280f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 281f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Internal method used to build a list of available events. 282f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 283f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param key: key to be used for TRAPpy filtering 284f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type key: str 285f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 28634f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi for val in self.ftrace.get_filters(key): 2879c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi obj = getattr(self.ftrace, val) 2888e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(obj.data_frame): 2898e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.available_events.append(val) 290c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Events found on trace:') 2918e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi for evt in self.available_events: 292c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug(' - %s', evt) 2938e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2948e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def __loadTasksNames(self, tasks): 295f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 296f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Try to load tasks names using one of the supported events. 297f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 298aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :param tasks: list of task names. If None, load all tasks found. 299aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :type tasks: list(str) or NoneType 300f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 30167d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman def load(tasks, event, name_key, pid_key): 30267d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman df = self._dfg_trace_event(event) 303aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman if tasks is None: 304aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman tasks = df[name_key].unique() 30567d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman self.getTasks(df, tasks, name_key=name_key, pid_key=pid_key) 30667d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman self._scanTasks(df, name_key=name_key, pid_key=pid_key) 30767d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman 3088e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if 'sched_switch' in self.available_events: 30967d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman load(tasks, 'sched_switch', 'next_comm', 'next_pid') 31067d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman elif 'sched_load_avg_task' in self.available_events: 31167d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman load(tasks, 'sched_load_avg_task', 'comm', 'pid') 31267d14d05928174971c4b583efebe17e83fa7067aBrendan Jackman else: 313c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Failed to load tasks names from trace events') 3148e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 3158e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def hasEvents(self, dataset): 316f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 317f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Returns True if the specified event is present in the parsed trace, 318f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio False otherwise. 319f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 320f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param dataset: trace event name or list of trace events 321f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type dataset: str or list(str) 322f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 3238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if dataset in self.available_events: 3248e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return True 3258e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return False 3268e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 3278e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def __computeTimeSpan(self): 328f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 329f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Compute time axis range, considering all the parsed events. 330f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 3318e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ts = sys.maxint 3328e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi te = 0 3338e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 33466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi for events in self.available_events: 335fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event(events) 3368e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(df) == 0: 3378e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 3388e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if (df.index[0]) < ts: 3398e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ts = df.index[0] 3408e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if (df.index[-1]) > te: 3418e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi te = df.index[-1] 3428e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.time_range = te - ts 3438e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 344c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Collected events spans a %.3f [s] time interval', 345c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self.time_range) 3468e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 347877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi # Build a stat on trace overutilization 348877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi if self.hasEvents('sched_overutilized'): 349fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_overutilized') 350877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_time = df[df.overutilized == 1].len.sum() 351877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_prc = 100. * self.overutilized_time / self.time_range 352877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 353c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Overutilized time: %.6f [s] (%.3f%% of trace time)', 354c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self.overutilized_time, self.overutilized_prc) 355877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 3563a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def _scanTasks(self, df, name_key='comm', pid_key='pid'): 357f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 358f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Extract tasks names and PIDs from the input data frame. The data frame 359f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio should contain a task name column and PID column. 360f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 361f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param df: data frame containing trace events from which tasks names 362f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio and PIDs will be extracted 363f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type df: :mod:`pandas.DataFrame` 364f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 365b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio :param name_key: The name of the dataframe columns containing task 366b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio names 367f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name_key: str 368f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 369f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param pid_key: The name of the dataframe columns containing task PIDs 370f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type pid_key: str 371f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 372b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df = df[[name_key, pid_key]] 3733a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_name = df.set_index(name_key) 374b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio self._tasks_by_pid = df.set_index(pid_key) 3753a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 3763a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def getTaskByName(self, name): 377f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 378f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get the PIDs of all tasks with the specified name. 379f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 380f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param name: task name 381f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name: str 382f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 3833a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if name not in self._tasks_by_name.index: 3843a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [] 3853a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if len(self._tasks_by_name.ix[name].values) > 1: 3863a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return list({task[0] for task in 3873a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_name.ix[name].values}) 3883a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [self._tasks_by_name.ix[name].values[0]] 3893a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 3903a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def getTaskByPid(self, pid): 391f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 392f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get the names of all tasks with the specified PID. 393f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 394f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param name: task PID 395f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name: int 396f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 3973a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if pid not in self._tasks_by_pid.index: 3983a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [] 3993a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if len(self._tasks_by_pid.ix[pid].values) > 1: 4003a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return list({task[0] for task in 4013a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_pid.ix[pid].values}) 4023a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [self._tasks_by_pid.ix[pid].values[0]] 4033a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 4048e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def getTasks(self, dataframe=None, 405b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio task_names=None, name_key='comm', pid_key='pid'): 406f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 407f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Helper function to get PIDs of specified tasks. 408f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 40907785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman This method can take a Pandas dataset in input to be used to fiter out 410f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio the PIDs of all the specified tasks. If a dataset is not provided, 411f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio previously filtered PIDs are returned. 412f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 41307785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman If a list of task names is not provided, all tasks detected in the trace 41407785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman will be used. The specified dataframe must provide at least two columns 41507785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman reporting the task name and the task PID. The default values of this 41607785500fa9f857ba507fc3357ee13636c3e6129Brendan Jackman colums could be specified using the provided parameters. 417f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 418aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :param dataframe: A Pandas dataframe containing at least 'name_key' and 419aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman 'pid_key' columns. If None, the all PIDs are returned. 420f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type dataframe: :mod:`pandas.DataFrame` 421f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 422aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman :param task_names: The list of tasks to get the PID of (default: all 423aa9f74b7a17e863acbfa558aee6b5a3ac997c0b8Brendan Jackman tasks) 424f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type task_names: list(str) 425f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 426b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio :param name_key: The name of the dataframe columns containing task 427b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio names 428f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type name_key: str 429f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 430f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param pid_key: The name of the dataframe columns containing task PIDs 431f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type pid_key: str 432f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 4338e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if task_names is None: 4348e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi task_names = self.tasks.keys() 435b196b8cd11030c4353903f18deb30905e406074fBrendan Jackman if dataframe is None: 436b196b8cd11030c4353903f18deb30905e406074fBrendan Jackman return {k: v for k, v in self.tasks.iteritems() if k in task_names} 437b196b8cd11030c4353903f18deb30905e406074fBrendan Jackman df = dataframe 438c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Lookup dataset for tasks...') 4398e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi for tname in task_names: 440c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Lookup for task [%s]...', tname) 441b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio results = df[df[name_key] == tname][[name_key, pid_key]] 442b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio if len(results) == 0: 443c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.error(' task %16s NOT found', tname) 4448e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 4458e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi (name, pid) = results.head(1).values[0] 446b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio if name != tname: 447c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.error(' task %16s NOT found', tname) 4488e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 449b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio if tname not in self.tasks: 4508e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks[tname] = {} 4518e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi pids = list(results[pid_key].unique()) 4528e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks[tname]['pid'] = pids 453c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug(' task %16s found, pid: %s', 454c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi tname, self.tasks[tname]['pid']) 4558e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return self.tasks 4568e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 457fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 458b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 459fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi# DataFrame Getter Methods 460b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 461fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 4628e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def df(self, event): 463f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 464f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get a dataframe containing all occurrences of the specified trace event 465f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio in the parsed trace. 466f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 467f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param event: Trace event name 468f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type event: str 469f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 470fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi warnings.simplefilter('always', DeprecationWarning) #turn off filter 471fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi warnings.warn("\n\tUse of Trace::df() is deprecated and will be soon removed." 472fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi "\n\tUse Trace::data_frame.trace_event(event_name) instead.", 473fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi category=DeprecationWarning) 474fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi warnings.simplefilter('default', DeprecationWarning) #reset filter 475fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi return self._dfg_trace_event(event) 476fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 477fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi def _dfg_trace_event(self, event): 4788e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi """ 479f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Get a dataframe containing all occurrences of the specified trace event 480f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio in the parsed trace. 481f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 482f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param event: Trace event name 483f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type event: str 4848e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi """ 485f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi if self.data_dir is None: 4868e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi raise ValueError("trace data not (yet) loaded") 4879c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi if self.ftrace and hasattr(self.ftrace, event): 4889c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi return getattr(self.ftrace, event).data_frame 489b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio raise ValueError('Event [{}] not supported. ' 490b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 'Supported events are: {}' 49166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi .format(event, self.available_events)) 4928e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 493ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi def _dfg_functions_stats(self, functions=None): 494ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi """ 495ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi Get a DataFrame of specified kernel functions profile data 496ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 497ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi For each profiled function a DataFrame is returned which reports stats 498ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi on kernel functions execution time. The reported stats are per-CPU and 499ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi includes: number of times the function has been executed (hits), 500ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi average execution time (avg), overall execution time (time) and samples 501ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi variance (s_2). 502ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi By default returns a DataFrame of all the functions profiled. 503ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 504ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi :param functions: the name of the function or a list of function names 505ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi to report 506f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type functions: str or list(str) 507ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi """ 508ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if not hasattr(self, '_functions_stats_df'): 509ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return None 510ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi df = self._functions_stats_df 511ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if not functions: 512ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return df 513ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return df.loc[df.index.get_level_values(1).isin(listify(functions))] 514ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 5155824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi 516b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 517fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi# Trace Events Sanitize Methods 518b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 519fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi 520c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedCpuCapacity(self): 521f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 522f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Add more columns to cpu_capacity data frame if the energy model is 523f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio available. 524f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 52566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('cpu_capacity') \ 52666b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi or 'nrg_model' not in self.platform: 527680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi return 528680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi 529fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('cpu_capacity') 53066b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi 5318e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Add column with LITTLE and big CPUs max capacities 5328e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi nrg_model = self.platform['nrg_model'] 5338e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi max_lcap = nrg_model['little']['cpu']['cap_max'] 5348e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi max_bcap = nrg_model['big']['cpu']['cap_max'] 5358e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['max_capacity'] = np.select( 5368e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 5378e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [max_lcap], max_bcap) 5388e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Add LITTLE and big CPUs "tipping point" threshold 5398e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi tip_lcap = 0.8 * max_lcap 5408e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi tip_bcap = 0.8 * max_bcap 5418e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['tip_capacity'] = np.select( 5428e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 5438e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [tip_lcap], tip_bcap) 5448e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 545997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi def _sanitize_SchedLoadAvgCpu(self): 546f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 547f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio If necessary, rename certain signal names from v5.0 to v5.1 format. 548f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 54966b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_load_avg_cpu'): 55066b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 551fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_load_avg_cpu') 552997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi if 'utilization' in df: 553b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'utilization': 'util_avg'}, inplace=True) 554b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'load': 'load_avg'}, inplace=True) 555997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi 556c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedLoadAvgTask(self): 557f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 558f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio If necessary, rename certain signal names from v5.0 to v5.1 format. 559f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 56066b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_load_avg_task'): 56166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 562fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_load_avg_task') 56317c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi if 'utilization' in df: 564b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'utilization': 'util_avg'}, inplace=True) 565b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'load': 'load_avg'}, inplace=True) 566b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'avg_period': 'period_contrib'}, inplace=True) 567b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'runnable_avg_sum': 'load_sum'}, inplace=True) 568b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'running_avg_sum': 'util_sum'}, inplace=True) 5698e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['cluster'] = np.select( 5708e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 5718e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ['LITTLE'], 'big') 5729d69537e219bc1052a28be114cb14ad47cc22c8fPatrick Bellasi # Add a column which represents the max capacity of the smallest 5739d69537e219bc1052a28be114cb14ad47cc22c8fPatrick Bellasi # clustre which can accomodate the task utilization 574b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio little_cap = self.platform['nrg_model']['little']['cpu']['cap_max'] 575b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio big_cap = self.platform['nrg_model']['big']['cpu']['cap_max'] 5769d69537e219bc1052a28be114cb14ad47cc22c8fPatrick Bellasi df['min_cluster_cap'] = df.util_avg.map( 577b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio lambda util_avg: big_cap if util_avg > little_cap else little_cap 578b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio ) 5798e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 580c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedBoostCpu(self): 581f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 582f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Add a boosted utilization signal as the sum of utilization and margin. 583f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 584f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Also, if necessary, rename certain signal names from v5.0 to v5.1 585f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio format. 586f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 58766b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_boost_cpu'): 58866b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 589fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_boost_cpu') 59017c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi if 'usage' in df: 591b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'usage': 'util'}, inplace=True) 59217c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df['boosted_util'] = df['util'] + df['margin'] 59317c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi 594c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedBoostTask(self): 595f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 596f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Add a boosted utilization signal as the sum of utilization and margin. 597f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 598f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Also, if necessary, rename certain signal names from v5.0 to v5.1 599f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio format. 600f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 60166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_boost_task'): 60266b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 603fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_boost_task') 604418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi if 'utilization' in df: 605418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi # Convert signals name from to v5.1 format 606b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio df.rename(columns={'utilization': 'util'}, inplace=True) 607418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi df['boosted_util'] = df['util'] + df['margin'] 6088e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 609c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedEnergyDiff(self): 610f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 611f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio If a energy model is provided, some signals are added to the 612f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio sched_energy_diff trace event data frame. 613f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 61466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_energy_diff') \ 61566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi or 'nrg_model' not in self.platform: 616680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi return 6178e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi nrg_model = self.platform['nrg_model'] 6188e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_lcluster = nrg_model['little']['cluster'] 6198e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_bcluster = nrg_model['big']['cluster'] 6208e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_lcpu = nrg_model['little']['cpu'] 6218e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_bcpu = nrg_model['big']['cpu'] 6228e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi lcpus = len(self.platform['clusters']['little']) 6238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi bcpus = len(self.platform['clusters']['big']) 6248e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi SCHED_LOAD_SCALE = 1024 6258e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 6268e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi power_max = em_lcpu['nrg_max'] * lcpus + em_bcpu['nrg_max'] * bcpus + \ 627b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio em_lcluster['nrg_max'] + em_bcluster['nrg_max'] 6288e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi print "Maximum estimated system energy: {0:d}".format(power_max) 6298e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 630fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_energy_diff') 6318e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['nrg_diff_pct'] = SCHED_LOAD_SCALE * df.nrg_diff / power_max 6328e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 6338e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Tag columns by usage_delta 6348e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ccol = df.usage_delta 6358e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['usage_delta_group'] = np.select( 6368e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [ccol < 150, ccol < 400, ccol < 600], 6378e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ['< 150', '< 400', '< 600'], '>= 600') 6388e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 6398e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Tag columns by nrg_payoff 6408e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ccol = df.nrg_payoff 6418e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['nrg_payoff_group'] = np.select( 6428e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [ccol > 2e9, ccol > 0, ccol > -2e9], 643b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio ['Optimal Accept', 'SchedTune Accept', 'SchedTune Reject'], 644b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 'Suboptimal Reject') 6458e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 646877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi def _sanitize_SchedOverutilized(self): 647f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ Add a column with overutilized status duration. """ 648877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi if not self.hasEvents('sched_overutilized'): 649877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi return 650fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('sched_overutilized') 651877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df['start'] = df.index 652877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df['len'] = (df.start - df.start.shift()).fillna(0).shift(-1) 653877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df.drop('start', axis=1, inplace=True) 6549e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 65547895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi def _chunker(self, seq, size): 656f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 657f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Given a data frame or a series, generate a sequence of chunks of the 658f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio given size. 659f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 660f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param seq: data to be split into chunks 661f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type seq: :mod:`pandas.Series` or :mod:`pandas.DataFrame` 662f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 663f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param size: size of each chunk 664f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type size: int 665f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 6669e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return (seq.iloc[pos:pos + size] for pos in range(0, len(seq), size)) 6679e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 66847895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi def _sanitize_CpuFrequency(self): 669f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 670f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Verify that all platform reported clusters are frequency coherent (i.e. 671f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio frequency scaling is performed at a cluster level). 672f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 6739e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio if not self.hasEvents('cpu_frequency'): 6749e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return 675fae44f68c443723378b83ab146fc20bc5a844a7dPatrick Bellasi df = self._dfg_trace_event('cpu_frequency') 6769e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio clusters = self.platform['clusters'] 677b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio for _, cpus in clusters.iteritems(): 6789e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio cluster_df = df[df.cpu.isin(cpus)] 67947895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi for chunk in self._chunker(cluster_df, len(cpus)): 6809e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio f = chunk.iloc[0].frequency 6819e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio if any(chunk.frequency != f): 682c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Cluster Frequency is not coherent! ' 683c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 'Failure in [cpu_frequency] events at:') 684c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning(chunk) 6859e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio self.freq_coherency = False 6869e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return 687c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.info('Platform clusters verified to be Frequency coherent') 68847895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi 689b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 690f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi# Utility Methods 691b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio############################################################################### 692f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi 6935824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi def integrate_square_wave(self, sq_wave): 6945824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi """ 6955824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi Compute the integral of a square wave time series. 6965824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi 6975824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi :param sq_wave: square wave assuming only 1.0 and 0.0 values 6985824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi :type sq_wave: :mod:`pandas.Series` 6995824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi """ 7005824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi sq_wave.iloc[-1] = 0.0 7015824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi # Compact signal to obtain only 1-0-1-0 sequences 7025824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi comp_sig = sq_wave.loc[sq_wave.shift() != sq_wave] 7035824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi # First value for computing the difference must be a 1 7045824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi if comp_sig.iloc[0] == 0.0: 7055824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi return sum(comp_sig.iloc[2::2].index - comp_sig.iloc[1:-1:2].index) 7065824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi else: 7075824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi return sum(comp_sig.iloc[1::2].index - comp_sig.iloc[:-1:2].index) 7085824ef082910363b2258cedecdabc60f6a2ea4c7Patrick Bellasi 709ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi def _loadFunctionsStats(self, path='trace.stats'): 710f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 711f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio Read functions profiling file and build a data frame containing all 712f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio relevant data. 713f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio 714f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :param path: path to the functions profiling trace file 715f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio :type path: str 716f93efbe21b68cf8f422a221d81fcd723a2ced356Michele Di Giorgio """ 717ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if os.path.isdir(path): 718ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi path = os.path.join(path, 'trace.stats') 719ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if path.endswith('dat') or path.endswith('html'): 720ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi pre, ext = os.path.splitext(path) 721ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi path = pre + '.stats' 722ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi if not os.path.isfile(path): 723ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return False 724ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 725ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi # Opening functions profiling JSON data file 726c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.debug('Loading functions profiling data from [%s]...', path) 727ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi with open(os.path.join(path), 'r') as fh: 728ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi trace_stats = json.load(fh) 729ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 730ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi # Build DataFrame of function stats 731ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi frames = {} 732ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi for cpu, data in trace_stats.iteritems(): 733ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi frames[int(cpu)] = pd.DataFrame.from_dict(data, orient='index') 734ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 735ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi # Build and keep track of the DataFrame 736b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio self._functions_stats_df = pd.concat(frames.values(), 737b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio keys=frames.keys()) 738ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 739ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi return len(self._functions_stats_df) > 0 740ff49ae1f0c3dcf5eba2b063c3571b692355f5320Patrick Bellasi 741691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio @memoized 742691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio def getCPUActiveSignal(self, cpu): 743691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 744691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio Build a square wave representing the active (i.e. non-idle) CPU time, 745691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio i.e.: 74606132f5606ea11cc7ec281595b9d9424c8d00e5fBrendan Jackman cpu_active[t] == 1 if the CPU is reported to be non-idle by cpuidle 74706132f5606ea11cc7ec281595b9d9424c8d00e5fBrendan Jackman at time t 748691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cpu_active[t] == 0 otherwise 749691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 750691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :param cpu: CPU ID 751691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :type cpu: int 752691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 753691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :returns: :mod:`pandas.Series` 754691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 755691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio if not self.hasEvents('cpu_idle'): 756c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Events [cpu_idle] not found, ' 757c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 'cannot compute CPU active signal!') 758691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio return None 759691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 760691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio idle_df = self._dfg_trace_event('cpu_idle') 761691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cpu_df = idle_df[idle_df.cpu_id == cpu] 762691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 763691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cpu_active = cpu_df.state.apply( 764691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio lambda s: 1 if s == NON_IDLE_STATE else 0 765691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio ) 766691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 767691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio start_time = 0.0 768691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio if not self.ftrace.normalized_time: 769691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio start_time = self.ftrace.basetime 77020a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman 77120a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman if cpu_active.empty: 77220a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman cpu_active = pd.Series([0], index=[start_time]) 77320a1ac25fb898bd3b045b3aecf894df04c93fc80Brendan Jackman elif cpu_active.index[0] != start_time: 774691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio entry_0 = pd.Series(cpu_active.iloc[0] ^ 1, index=[start_time]) 775691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cpu_active = pd.concat([entry_0, cpu_active]) 776691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 777691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio return cpu_active 778691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 779691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio @memoized 780691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio def getClusterActiveSignal(self, cluster): 781691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 782691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio Build a square wave representing the active (i.e. non-idle) cluster 783691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio time, i.e.: 784691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cluster_active[t] == 1 if at least one CPU is reported to be 785691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio non-idle by CPUFreq at time t 786691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cluster_active[t] == 0 otherwise 787691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 788691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :param cluster: list of CPU IDs belonging to a cluster 789691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :type cluster: list(int) 790691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 791691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio :returns: :mod:`pandas.Series` 792691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio """ 793691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio if not self.hasEvents('cpu_idle'): 794c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi self._log.warning('Events [cpu_idle] not found, ' 795c278c2343c7f25083a80cb164b6bdc761d50050bPatrick Bellasi 'cannot compute cluster active signal!') 796691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio return None 797691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 798403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio active = self.getCPUActiveSignal(cluster[0]).to_frame(name=cluster[0]) 799403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio for cpu in cluster[1:]: 800403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio active = active.join( 801403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio self.getCPUActiveSignal(cpu).to_frame(name=cpu), 802403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio how='outer' 803403a36f57d676a98b3632847e5655f9128a50216Michele Di Giorgio ) 804691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 805691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio active.fillna(method='ffill', inplace=True) 806691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 807691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio # Cluster active is the OR between the actives on each CPU 808691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio # belonging to that specific cluster 809691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio cluster_active = reduce( 810691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio operator.or_, 811691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio [cpu_active.astype(int) for _, cpu_active in 812691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio active.iteritems()] 813691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio ) 814691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 815691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio return cluster_active 816691fc118e5dff4df885a039cc855a746de4b7556Michele Di Giorgio 817b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio 818f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasiclass TraceData: 819b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio """ A DataFrame collector exposed to Trace's clients """ 820f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi pass 821f493b3388f11c03a2ad4522d69aaf49c82da787fPatrick Bellasi 822b9c02fe3f7682ceb9e1c703d218bb4c9449358a1Michele Di Giorgio# vim :set tabstop=4 shiftwidth=4 expandtab 823