trace.py revision 8224360b6dbfe7e28c28ef7a06fa100b2556c656
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 188e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport glob 198e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport matplotlib.gridspec as gridspec 208e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport matplotlib.pyplot as plt 218e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport numpy as np 228e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport os 238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport pandas as pd 248e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport pylab as pl 258e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport re 268e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport sys 278e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport trappy 2879a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasiimport json 2979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 3079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasifrom trappy.utils import listify 318e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 328e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi# Configure logging 338e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiimport logging 348e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 358e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasiclass Trace(object): 368e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 37f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi def __init__(self, platform, data_dir, events, 3834f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi tasks=None, window=(0,None), 39b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino normalize_time=True, 4069a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi trace_format='FTrace', 4169a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi plots_dir=None, 4269a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi plots_prefix=''): 438e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 448e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # The platform used to run the experiments 4550b5967280ce939d80f2d8b74253a0130ba16561Patrick Bellasi self.platform = platform 468e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 4734f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi # TRAPpy Trace object 489c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi self.ftrace = None 498e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 5034f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi # Trace format 5134f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = trace_format 5234f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi 53a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi # The time window used to limit trace parsing to 54a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi self.window = window 55a8fdc5fe3719b498318e0451f5b4cdfac1f5015ePatrick Bellasi 568e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Dynamically registered TRAPpy events 578e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.trappy_cls = {} 588e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 598e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Maximum timespan for all collected events 608e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.time_range = 0 618e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 62877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi # Time the system was overutilzied 63877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_time = 0 64877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_prc = 0 65877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 668e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # The dictionary of tasks descriptors available in the dataset 678e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks = {} 688e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 69e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi # List of events required by user 70e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = [] 71e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi 728e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # List of events available in the parsed trace 738e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.available_events = [] 748e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 759e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio # Cluster frequency coherency flag 769e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio self.freq_coherency = True 779e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 78f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi # Folder containing all trace data 79f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = None 80f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi 818e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Folder containing trace 82f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi if not os.path.isdir(data_dir): 83f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = os.path.dirname(data_dir) 84881f14cdb8b78ad422f739fe28cbce2525020430Patrick Bellasi else: 85f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.data_dir = data_dir 868e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 8769a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi # By deafult, use the trace dir to save plots 8869a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_dir = plots_dir 8969a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi if self.plots_dir is None: 9069a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_dir = self.data_dir 9169a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi self.plots_prefix = plots_prefix 9269a445cdc130949aa54b84fb9b3dfbcb55fa2d53Patrick Bellasi 93e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.__registerTraceEvents(events) 94f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi self.__parseTrace(data_dir, tasks, window, normalize_time, trace_format) 958e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__computeTimeSpan() 968e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 978224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi # Minimum and Maximum x_time to use for all plots 988224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = 0 998224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = self.time_range 1008224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 1018224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi # Reset x axis time range to full scale 1028224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi t_min = self.window[0] 1038224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi t_max = self.window[1] 1048224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.setXTimeRange(t_min, t_max) 1058224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 1068224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi # Initialize supported analysis modules 1078224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 1088224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi def setXTimeRange(self, t_min=None, t_max=None): 1098224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi if t_min is None: 1108224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = 0 1118224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi else: 1128224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min = t_min 1138224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi if t_max is None: 1148224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = self.time_range 1158224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi else: 1168224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_max = t_max 1178224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi logging.info('Set plots time range to (%.6f, %.6f)[s]', 1188224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi self.x_min, self.x_max) 1198224360b6dbfe7e28c28ef7a06fa100b2556c656Patrick Bellasi 120e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi def __registerTraceEvents(self, events): 121e09821241ca9697b75c8a53fb0813212202d1c65Patrick Bellasi 122e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi if isinstance(events, basestring): 123e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = events.split(' ') 124e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi elif isinstance(events, list): 125e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi self.events = events 126e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi else: 127e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi raise ValueError('Events must be a string or a list of strings') 1288e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1298e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 130b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino def __parseTrace(self, path, tasks, window, normalize_time, trace_format): 131881f14cdb8b78ad422f739fe28cbce2525020430Patrick Bellasi logging.debug('Loading [sched] events from trace in [%s]...', path) 132e24e02a9565a8ca8f948e15b573eeb808b8ece86Patrick Bellasi logging.debug("Parsing events: %s", self.events) 13334f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi if trace_format.upper() == 'SYSTRACE' or path.endswith('html'): 13434f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi logging.info('Parsing SysTrace format...') 135edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino trace_class = trappy.SysTrace 13634f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = 'SysTrace' 13734f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi elif trace_format.upper() == 'FTRACE': 13834f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi logging.info('Parsing FTrace format...') 139edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino trace_class = trappy.FTrace 14034f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi self.trace_format = 'FTrace' 141d02408964a1d1042b99f51ba01989e8cf02478faJavi Merino else: 142d02408964a1d1042b99f51ba01989e8cf02478faJavi Merino raise ValueError("Unknown trace format {}".format(trace_format)) 1438e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 144edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino self.ftrace = trace_class(path, scope="custom", events=self.events, 145b4ab05a5cc9630963cdfafeab214dcf1661167c7Javi Merino window=window, normalize_time=normalize_time) 146edc53078c056df33a9872fd170d6a66c2acd82d8Javi Merino 14779a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi # Load Functions profiling data 14879a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi has_function_stats = self._loadFunctionsStats(path) 14979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 1508e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Check for events available on the parsed trace 1518e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__checkAvailableEvents() 1528e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(self.available_events) == 0: 15379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if has_function_stats: 15479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi logging.info('Trace contains only functions stats') 15579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return 15679a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi raise ValueError('The trace does not contain useful events ' 15779a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 'nor function stats') 1588e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1598e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Setup internal data reference to interesting events/dataframes 1608e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 16166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedLoadAvgCpu() 16266b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedLoadAvgTask() 16366b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedCpuCapacity() 16466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedBoostCpu() 16566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedBoostTask() 16666b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedEnergyDiff() 16766b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self._sanitize_SchedOverutilized() 16847895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi self._sanitize_CpuFrequency() 1698e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1708e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.__loadTasksNames(tasks) 1718e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1729e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 173db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio # Compute plot window 174db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio if not normalize_time: 175db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio start = self.window[0] 176db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio if self.window[1]: 177db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio duration = min(self.ftrace.get_duration(), self.window[1]) 178db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio else: 179db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio duration = self.ftrace.get_duration() 180db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio self.window = (self.ftrace.basetime + start, 181db6e903112f0f5b2c5c66a63a5d3cdf35d0a6f55Michele Di Giorgio self.ftrace.basetime + duration) 1828e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 18334f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi def __checkAvailableEvents(self, key=""): 18434f5d28c5ef4415709f75afcc636c37a210f4d02Patrick Bellasi for val in self.ftrace.get_filters(key): 1859c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi obj = getattr(self.ftrace, val) 1868e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(obj.data_frame): 1878e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.available_events.append(val) 1888e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.debug('Events found on trace:') 1898e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi for evt in self.available_events: 1908e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.debug(' - %s', evt) 1918e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1928e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 1938e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def __loadTasksNames(self, tasks): 1948e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Try to load tasks names using one of the supported events 1958e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if 'sched_switch' in self.available_events: 19666b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self.getTasks(self.df('sched_switch'), tasks, 1978e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi name_key='next_comm', pid_key='next_pid') 1983a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._scanTasks(self.df('sched_switch'), 1993a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi name_key='next_comm', pid_key='next_pid') 2008e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return 2018e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if 'sched_load_avg_task' in self.available_events: 20266b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi self.getTasks(self.df('sched_load_avg_task'), tasks) 2033a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._scanTasks(self.df('sched_load_avg_task')) 2048e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return 2058e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.warning('Failed to load tasks names from trace events') 2068e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2078e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def hasEvents(self, dataset): 2088e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if dataset in self.available_events: 2098e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return True 2108e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return False 2118e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2128e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def __computeTimeSpan(self): 2138e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Compute time axis range, considering all the parsed events 2148e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ts = sys.maxint 2158e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi te = 0 2168e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 21766b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi for events in self.available_events: 21866b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi df = self.df(events) 2198e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(df) == 0: 2208e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 2218e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if (df.index[0]) < ts: 2228e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ts = df.index[0] 2238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if (df.index[-1]) > te: 2248e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi te = df.index[-1] 2258e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.time_range = te - ts 2268e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 2278e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.info('Collected events spans a %.3f [s] time interval', 2288e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.time_range) 2298e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 230877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi # Build a stat on trace overutilization 231877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi if self.hasEvents('sched_overutilized'): 232877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df = self.df('sched_overutilized') 233877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_time = df[df.overutilized == 1].len.sum() 234877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_prc = 100. * self.overutilized_time / self.time_range 235877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 236877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi logging.info('Overutilized time: %.6f [s] (%.3f%% of trace time)', 237877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi self.overutilized_time, self.overutilized_prc) 238877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi 23979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi def _loadFunctionsStats(self, path='trace.stats'): 24079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if os.path.isdir(path): 24179a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi path = os.path.join(path, 'trace.stats') 24279a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if path.endswith('dat') or path.endswith('html'): 24379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi pre, ext = os.path.splitext(path) 24479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi path = pre + '.stats' 24579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if not os.path.isfile(path): 24679a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return False 24779a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 24879a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi # Opening functions profiling JSON data file 24979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi logging.debug('Loading functions profiling data from [%s]...', path) 25079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi with open(os.path.join(path), 'r') as fh: 25179a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi trace_stats = json.load(fh) 25279a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 25379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi # Build DataFrame of function stats 25479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi frames = {} 25579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi for cpu, data in trace_stats.iteritems(): 25679a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi frames[int(cpu)] = pd.DataFrame.from_dict(data, orient='index') 25779a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 25879a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi # Build and keep track of the DataFrame 25979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi self._functions_stats_df = pd.concat(frames.values(), keys=frames.keys()) 26079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 26179a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return len(self._functions_stats_df) > 0 26279a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 26379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi def functions_stats_df(self, functions=None): 26479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi """ 26579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi Get a DataFrame of specified kernel functions profile data 26679a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 26779a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi For each profiled function a DataFrame is returned which reports stats 26879a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi on kernel functions execution time. The reported stats are per-CPU and 26979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi includes: number of times the function has been executed (hits), 27079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi average execution time (avg), overall execution time (time) and samples 27179a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi variance (s_2). 27279a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi By default returns a DataFrame of all the functions profiled. 27379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 27479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi :param functions: the name of the function or a list of function names 27579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi to report 27679a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi :type functions: str or list 27779a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 27879a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi """ 27979a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if not hasattr(self, '_functions_stats_df'): 28079a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return None 28179a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi df = self._functions_stats_df 28279a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi if not functions: 28379a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return df 28479a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi return df.loc[df.index.get_level_values(1).isin(listify(functions))] 28579a153ae2cea469af80c9d5324c479365980a3adPatrick Bellasi 2863a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def _scanTasks(self, df, name_key='comm', pid_key='pid'): 2873a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi df = df[[name_key, pid_key]] 2883a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_name = df.set_index(name_key) 2893a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_pid = df.set_index(pid_key) 2903a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 2913a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def getTaskByName(self, name): 2923a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if name not in self._tasks_by_name.index: 2933a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [] 2943a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if len(self._tasks_by_name.ix[name].values) > 1: 2953a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return list({task[0] for task in 2963a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_name.ix[name].values}) 2973a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [self._tasks_by_name.ix[name].values[0]] 2983a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 2993a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi def getTaskByPid(self, pid): 3003a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if pid not in self._tasks_by_pid.index: 3013a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [] 3023a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi if len(self._tasks_by_pid.ix[pid].values) > 1: 3033a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return list({task[0] for task in 3043a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi self._tasks_by_pid.ix[pid].values}) 3053a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi return [self._tasks_by_pid.ix[pid].values[0]] 3063a044edddce5a950d10a2ed95d96c9bd72d2363aPatrick Bellasi 3078e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def getTasks(self, dataframe=None, 3088e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi task_names=None, name_key='comm', pid_key='pid'): 3098e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # """ Helper function to get PIDs of specified tasks 3108e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # 3118e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # This method requires a Pandas dataset in input to be used to 3128e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # fiter out the PIDs of all the specified tasks. 3138e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # In a dataset is not provided, previouslt filtered PIDs are 3148e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # returned. 3158e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # If a list of task names is not provided, the workload defined 3168e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # task names is used instead. 3178e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # The specified dataframe must provide at least two columns 3188e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # reporting the task name and the task PID. The default values of 3198e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # this colums could be specified using the provided parameters. 3208e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # 3218e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # :param task_names: The list of tasks to get the PID of (by default 3228e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # the workload defined tasks) 3238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # :param dataframe: A Pandas datafram containing at least 'pid' and 3248e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # 'task name' columns. If None, the previously 3258e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # filtered PIDs are returned 3268e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # :param name_key: The name of the dataframe columns containing 3278e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # task names 3288e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # :param pid_key: The name of the dataframe columns containing 3298e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # task PIDs 3308e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # """ 3318e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if dataframe is None: 3328e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return self.tasks 3338e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df = dataframe 3348e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if task_names is None: 3358e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi task_names = self.tasks.keys() 3368e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.debug("Lookup dataset for tasks...") 3378e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi for tname in task_names: 3388e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.debug("Lookup for task [%s]...", tname) 3398e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi results = df[df[name_key] == tname][[name_key,pid_key]] 3408e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if len(results)==0: 3418e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.error(' task %16s NOT found', tname) 3428e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 3438e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi (name, pid) = results.head(1).values[0] 3448e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if name!=tname: 3458e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.error(' task %16s NOT found', tname) 3468e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi continue 3478e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi if (tname not in self.tasks): 3488e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks[tname] = {} 3498e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi pids = list(results[pid_key].unique()) 3508e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi self.tasks[tname]['pid'] = pids 3518e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi logging.info(' task %16s found, pid: %s', 3528e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi tname, self.tasks[tname]['pid']) 3538e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi return self.tasks 3548e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 3558e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi def df(self, event): 3568e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi """ 3578e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi Return the PANDAS dataframe with the performance data for the specified 3588e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi event 3598e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi """ 360f0ca15ec410a73b8f223a48e1be234c8561c6c2cPatrick Bellasi if self.data_dir is None: 3618e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi raise ValueError("trace data not (yet) loaded") 3629c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi if self.ftrace and hasattr(self.ftrace, event): 3639c42a5ae0f2a627860e5cc68dc7626da0c5b232fPatrick Bellasi return getattr(self.ftrace, event).data_frame 36466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi raise ValueError('Event [{}] not supported. '\ 36566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi 'Supported events are: {}'\ 36666b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi .format(event, self.available_events)) 3678e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 368c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedCpuCapacity(self): 369680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi # Add more columns if the energy model is available 37066b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('cpu_capacity') \ 37166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi or 'nrg_model' not in self.platform: 372680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi return 373680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi 37466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi df = self.df('cpu_capacity') 37566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi 3768e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Add column with LITTLE and big CPUs max capacities 3778e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi nrg_model = self.platform['nrg_model'] 3788e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi max_lcap = nrg_model['little']['cpu']['cap_max'] 3798e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi max_bcap = nrg_model['big']['cpu']['cap_max'] 3808e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['max_capacity'] = np.select( 3818e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 3828e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [max_lcap], max_bcap) 3838e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Add LITTLE and big CPUs "tipping point" threshold 3848e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi tip_lcap = 0.8 * max_lcap 3858e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi tip_bcap = 0.8 * max_bcap 3868e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['tip_capacity'] = np.select( 3878e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 3888e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [tip_lcap], tip_bcap) 3898e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 390997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi def _sanitize_SchedLoadAvgCpu(self): 39166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_load_avg_cpu'): 39266b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 393c94900dcb499cd2a6df32b7c6532be4e589d0e8bPatrick Bellasi df = self.df('sched_load_avg_cpu') 394997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi if 'utilization' in df: 395997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi # Convert signals name from v5.0 to v5.1 format 396997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi df.rename(columns={'utilization':'util_avg'}, inplace=True) 397997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi df.rename(columns={'load':'load_avg'}, inplace=True) 398997f0ca86a715c99bd1adce42c1812d650ea516cPatrick Bellasi 399c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedLoadAvgTask(self): 40066b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_load_avg_task'): 40166b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 402c94900dcb499cd2a6df32b7c6532be4e589d0e8bPatrick Bellasi df = self.df('sched_load_avg_task') 40317c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi if 'utilization' in df: 40417c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi # Convert signals name from v5.0 to v5.1 format 40517c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df.rename(columns={'utilization':'util_avg'}, inplace=True) 40617c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df.rename(columns={'load':'load_avg'}, inplace=True) 40717c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df.rename(columns={'avg_period':'period_contrib'}, inplace=True) 40817c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df.rename(columns={'runnable_avg_sum':'load_sum'}, inplace=True) 40917c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df.rename(columns={'running_avg_sum':'util_sum'}, inplace=True) 4108e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['cluster'] = np.select( 4118e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [df.cpu.isin(self.platform['clusters']['little'])], 4128e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ['LITTLE'], 'big') 4138e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 414c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedBoostCpu(self): 41566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_boost_cpu'): 41666b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 417c94900dcb499cd2a6df32b7c6532be4e589d0e8bPatrick Bellasi df = self.df('sched_boost_cpu') 41817c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi if 'usage' in df: 41917c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi # Convert signals name from to v5.1 format 42017c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df.rename(columns={'usage':'util'}, inplace=True) 42117c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi df['boosted_util'] = df['util'] + df['margin'] 42217c7721066c57695ba43bac0c4170c324093d693Patrick Bellasi 4238e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 424c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedBoostTask(self): 42566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_boost_task'): 42666b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi return 427c94900dcb499cd2a6df32b7c6532be4e589d0e8bPatrick Bellasi df = self.df('sched_boost_task') 428418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi if 'utilization' in df: 429418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi # Convert signals name from to v5.1 format 430418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi df.rename(columns={'utilization':'util'}, inplace=True) 431418cfb6405256f744cc3023fd7a5fcbff1f757a7Patrick Bellasi df['boosted_util'] = df['util'] + df['margin'] 4328e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 433c5d46e8caeb638b88b75557a30262a6912a86629Patrick Bellasi def _sanitize_SchedEnergyDiff(self): 43466b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi if not self.hasEvents('sched_energy_diff') \ 43566b843f6127403f8a6933f8d9f90576a11ac998dPatrick Bellasi or 'nrg_model' not in self.platform: 436680ad8b9c70754064b686e1fcea6db022bc5e152Patrick Bellasi return 4378e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi nrg_model = self.platform['nrg_model'] 4388e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_lcluster = nrg_model['little']['cluster'] 4398e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_bcluster = nrg_model['big']['cluster'] 4408e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_lcpu = nrg_model['little']['cpu'] 4418e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_bcpu = nrg_model['big']['cpu'] 4428e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi lcpus = len(self.platform['clusters']['little']) 4438e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi bcpus = len(self.platform['clusters']['big']) 4448e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi SCHED_LOAD_SCALE = 1024 4458e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 4468e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi power_max = em_lcpu['nrg_max'] * lcpus + em_bcpu['nrg_max'] * bcpus + \ 4478e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi em_lcluster['nrg_max'] + em_bcluster['nrg_max'] 4488e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi print "Maximum estimated system energy: {0:d}".format(power_max) 4498e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 450c94900dcb499cd2a6df32b7c6532be4e589d0e8bPatrick Bellasi df = self.df('sched_energy_diff') 4518e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['nrg_diff_pct'] = SCHED_LOAD_SCALE * df.nrg_diff / power_max 4528e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 4538e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Tag columns by usage_delta 4548e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ccol = df.usage_delta 4558e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['usage_delta_group'] = np.select( 4568e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [ccol < 150, ccol < 400, ccol < 600], 4578e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ['< 150', '< 400', '< 600'], '>= 600') 4588e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 4598e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi # Tag columns by nrg_payoff 4608e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ccol = df.nrg_payoff 4618e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi df['nrg_payoff_group'] = np.select( 4628e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi [ccol > 2e9, ccol > 0, ccol > -2e9], 4638e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi ['Optimal Accept', 'SchedTune Accept', 'SchedTune Reject'], 'Suboptimal Reject') 4648e6284e58870ec8b4e5fd02186668934287a22f5Patrick Bellasi 465877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi def _sanitize_SchedOverutilized(self): 466877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi if not self.hasEvents('sched_overutilized'): 467877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi return 468877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi # Add a column with overutilized status duration 469877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df = self.df('sched_overutilized') 470877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df['start'] = df.index 471877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df['len'] = (df.start - df.start.shift()).fillna(0).shift(-1) 472877f3408c7f7705157f6c533957c30275e6972a2Patrick Bellasi df.drop('start', axis=1, inplace=True) 4739e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 47447895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi def _chunker(self, seq, size): 4759e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return (seq.iloc[pos:pos + size] for pos in range(0, len(seq), size)) 4769e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 47747895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi def _sanitize_CpuFrequency(self): 4789e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio if not self.hasEvents('cpu_frequency'): 4799e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return 48047895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi # Verify that all platform reported clusters are frequency choerent 4819e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio df = self.df('cpu_frequency') 4829e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio clusters = self.platform['clusters'] 4839e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio for c, cpus in clusters.iteritems(): 4849e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio cluster_df = df[df.cpu.isin(cpus)] 48547895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi for chunk in self._chunker(cluster_df, len(cpus)): 4869e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio f = chunk.iloc[0].frequency 4879e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio if any(chunk.frequency != f): 4889e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio logging.warn('Cluster Frequency is not coherent! '\ 4899e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio 'Failure in [cpu_frequency] events at:') 4909e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio logging.warn(chunk) 4919e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio self.freq_coherency = False 4929e7a48bf52c1e0cf136dfdce5ba7ecc12768a092Michele Di Giorgio return 49347895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi logging.info("Platform clusters verified to be Frequency choerent") 49447895783a9a4b581c1c7aa15caf2a407201948dbPatrick Bellasi 495