From 877f3408c7f7705157f6c533957c30275e6972a2 Mon Sep 17 00:00:00 2001 From: Patrick Bellasi Date: Tue, 9 Feb 2016 18:53:37 +0000 Subject: [PATCH 1/2] libs/utils/trace: add support for overutilized events The sched_overutilized tracepoint is used to report when the system is running in EAS mode or it's over the tipping point. This patch adds the required code to parse overutilized events as well as to compute and report the percentage of time the system was running in overutilized mode (for the specific trace). Signed-off-by: Patrick Bellasi --- libs/utils/trace.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libs/utils/trace.py b/libs/utils/trace.py index f1cff7e3d..39f626937 100644 --- a/libs/utils/trace.py +++ b/libs/utils/trace.py @@ -51,6 +51,10 @@ class Trace(object): # Maximum timespan for all collected events self.time_range = 0 + # Time the system was overutilzied + self.overutilized_time = 0 + self.overutilized_prc = 0 + # The dictionary of tasks descriptors available in the dataset self.tasks = {} @@ -147,6 +151,15 @@ class Trace(object): logging.info('Collected events spans a %.3f [s] time interval', self.time_range) + # Build a stat on trace overutilization + if self.hasEvents('sched_overutilized'): + df = self.df('sched_overutilized') + self.overutilized_time = df[df.overutilized == 1].len.sum() + self.overutilized_prc = 100. * self.overutilized_time / self.time_range + + logging.info('Overutilized time: %.6f [s] (%.3f%% of trace time)', + self.overutilized_time, self.overutilized_prc) + def getTasks(self, dataframe=None, task_names=None, name_key='comm', pid_key='pid'): # """ Helper function to get PIDs of specified tasks @@ -305,3 +318,11 @@ class Trace(object): [ccol > 2e9, ccol > 0, ccol > -2e9], ['Optimal Accept', 'SchedTune Accept', 'SchedTune Reject'], 'Suboptimal Reject') + def _sanitize_SchedOverutilized(self): + if not self.hasEvents('sched_overutilized'): + return + # Add a column with overutilized status duration + df = self.df('sched_overutilized') + df['start'] = df.index + df['len'] = (df.start - df.start.shift()).fillna(0).shift(-1) + df.drop('start', axis=1, inplace=True) -- GitLab From fb0a000f7685e1673064faa9fe506f99cad315da Mon Sep 17 00:00:00 2001 From: Patrick Bellasi Date: Wed, 10 Feb 2016 18:10:27 +0000 Subject: [PATCH 2/2] libs/utils/trace_analysis: add plots for EAS overutilized status This patch add a new method which can be used to generate a standalone plot of the system EAS/non-EAS mode (i.e. overutilized mode) as well as to over-impose that status to another plot which axes are specified. Signed-off-by: Patrick Bellasi --- libs/utils/trace_analysis.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/libs/utils/trace_analysis.py b/libs/utils/trace_analysis.py index 35dfa4a4c..866705d50 100644 --- a/libs/utils/trace_analysis.py +++ b/libs/utils/trace_analysis.py @@ -128,6 +128,7 @@ class TraceAnalysis(object): axes.grid(True); axes.set_xticklabels([]) axes.set_xlabel('') + self.plotOverutilized(axes) axes = pltaxes[1] axes.set_title('LITTLE Cluster'); @@ -143,6 +144,7 @@ class TraceAnalysis(object): axes.set_xlim(self.x_min, self.x_max); axes.set_ylabel('MHz') axes.grid(True); + self.plotOverutilized(axes) # Save generated plots into datadir figname = '{}/cluster_freqs.png'.format(self.plotsdir) @@ -253,6 +255,32 @@ class TraceAnalysis(object): lcpus = set(cpus) & set(self.platform['clusters']['little']) self.__plotCPU(lcpus, "LITTLE") + def plotOverutilized(self, axes=None): + if not self.trace.hasEvents('sched_overutilized'): + logging.warn('Events [sched_overutilized] not found, '\ + 'plot DISABLED!') + return + + # Build sequence of overutilization "bands" + df = self.trace.df('sched_overutilized') + bands = [(t, df['len'][t], df['overutilized'][t]) for t in df.index] + + # If not axis provided: generate a standalone plot + if not axes: + gs = gridspec.GridSpec(1, 1) + plt.figure(figsize=(16, 1)) + axes = plt.subplot(gs[0,0]) + axes.set_title('System Status {white: EAS mode, red: Non EAS mode}'); + axes.set_xlim(self.x_min, self.x_max); + axes.grid(True); + + # Otherwise: draw overutilized bands on top of the specified plot + for (t1,td,overutilized) in bands: + if not overutilized: + continue + t2 = t1+td + axes.axvspan(t1, t2, facecolor='r', alpha=0.1) + def plotTasks(self, tasks=None): if not self.trace.hasEvents('sched_load_avg_task'): logging.warn('Events [sched_load_avg_task] not found, '\ @@ -307,6 +335,7 @@ class TraceAnalysis(object): axes.grid(True); axes.set_xticklabels([]) axes.set_xlabel('') + self.plotOverutilized(axes) # Plot CPUs residency axes = plt.subplot(gs[1,0]); @@ -323,6 +352,7 @@ class TraceAnalysis(object): axes.grid(True); axes.set_xticklabels([]) axes.set_xlabel('') + self.plotOverutilized(axes) # Plot PELT signals axes = plt.subplot(gs[2,0]); @@ -331,6 +361,7 @@ class TraceAnalysis(object): data.plot(ax=axes, drawstyle='steps-post'); axes.set_xlim(self.x_min, self.x_max); axes.grid(True); + self.plotOverutilized(axes) # Save generated plots into datadir figname = '{}/task_util_{}.png'.format(self.plotsdir, task_name) @@ -401,6 +432,7 @@ class TraceAnalysis(object): axes.grid(True); axes.set_xticklabels([]) axes.set_xlabel('') + self.plotOverutilized(axes) # Plot2: energy and capacity variations axes = plt.subplot(gs[1,:]); @@ -416,6 +448,7 @@ class TraceAnalysis(object): axes.grid(True); axes.set_xticklabels([]) axes.set_xlabel('') + self.plotOverutilized(axes) # Plot3: energy payoff axes = plt.subplot(gs[2,:]); @@ -430,12 +463,15 @@ class TraceAnalysis(object): axes.grid(True); axes.set_xticklabels([]) axes.set_xlabel('') + self.plotOverutilized(axes) # Plot4: energy deltas (kernel and host computed values) axes = plt.subplot(gs[3,:]); axes.set_title('Energy Deltas Values'); df[['nrg_delta', 'nrg_diff_pct']].plot(ax=axes, style=['ro', 'b+']); axes.set_xlim(self.x_min, self.x_max); + axes.grid(True); + self.plotOverutilized(axes) # Save generated plots into datadir figname = '{}/ediff_time.png'.format(self.plotsdir) -- GitLab