blob: 6e8658f3777272e966c33c0e1f78c5c14aaff407 [file] [log] [blame]
{
"cells": [
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false,
"init_cell": false,
"run_control": {
"marked": false
}
},
"outputs": [],
"source": [
"# Enable in-notebook generation of plots\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Experiments collected data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Data required to run this notebook are available for download at this link:\n",
"\n",
"https://www.dropbox.com/s/q9ulf3pusu0uzss/SchedTuneAnalysis.tar.xz?dl=0\n",
"\n",
"This archive has to be extracted from within the LISA's results folder."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Initial set of data"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false,
"hidden": true,
"hide_input": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[01;34m../../results/SchedTuneAnalysis/\u001b[00m\r\n",
"├── \u001b[01;35mboost15_cluster_freqs.png\u001b[00m\r\n",
"├── \u001b[01;35mboost15_task_util_task_ramp.png\u001b[00m\r\n",
"├── energy.json\r\n",
"├── output.log\r\n",
"├── platform.json\r\n",
"├── rt-app-task_ramp-0.log\r\n",
"├── test_00.json\r\n",
"├── trace_boost15.dat\r\n",
"├── trace_boost15.raw.txt\r\n",
"├── trace_boost15.txt\r\n",
"├── trace_boost25.dat\r\n",
"└── trace_noboost.dat\r\n",
"\r\n",
"0 directories, 12 files\r\n"
]
}
],
"source": [
"res_dir = '../../results/SchedTuneAnalysis/'\n",
"!tree {res_dir}"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"noboost_trace = res_dir + 'trace_noboost.dat'\n",
"boost15_trace = res_dir + 'trace_boost15.dat'\n",
"boost25_trace = res_dir + 'trace_boost25.dat'\n",
"\n",
"# trace_file = noboost_trace\n",
"trace_file = boost15_trace\n",
"# trace_file = boost25_trace"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Loading support data collected from the target"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Platform descriptio collected from the target:\n",
"{\n",
" \"nrg_model\": {\n",
" \"big\": {\n",
" \"cluster\": {\n",
" \"nrg_max\": 64\n",
" }, \n",
" \"cpu\": {\n",
" \"cap_max\": 1024, \n",
" \"nrg_max\": 616\n",
" }\n",
" }, \n",
" \"little\": {\n",
" \"cluster\": {\n",
" \"nrg_max\": 57\n",
" }, \n",
" \"cpu\": {\n",
" \"cap_max\": 447, \n",
" \"nrg_max\": 93\n",
" }\n",
" }\n",
" }, \n",
" \"clusters\": {\n",
" \"big\": [\n",
" 1, \n",
" 2\n",
" ], \n",
" \"little\": [\n",
" 0, \n",
" 3, \n",
" 4, \n",
" 5\n",
" ]\n",
" }, \n",
" \"cpus_count\": 6, \n",
" \"freqs\": {\n",
" \"big\": [\n",
" 450000, \n",
" 625000, \n",
" 800000, \n",
" 950000, \n",
" 1100000\n",
" ], \n",
" \"little\": [\n",
" 450000, \n",
" 575000, \n",
" 700000, \n",
" 775000, \n",
" 850000\n",
" ]\n",
" }, \n",
" \"topology\": [\n",
" [\n",
" 0, \n",
" 3, \n",
" 4, \n",
" 5\n",
" ], \n",
" [\n",
" 1, \n",
" 2\n",
" ]\n",
" ]\n",
"}\n"
]
}
],
"source": [
"import json\n",
"\n",
"# Load the platform information\n",
"with open('../../results/SchedTuneAnalysis/platform.json', 'r') as fh:\n",
" platform = json.load(fh)\n",
"print \"Platform descriptio collected from the target:\"\n",
"print json.dumps(platform, indent=4)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [],
"source": [
"from trappy.stats.Topology import Topology\n",
"\n",
"# Create a topology descriptor\n",
"topology = Topology(platform['topology'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Trace analysis"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"We want to ensure that the task has the expected workload:<br>\n",
"- LITTLE CPU bandwidth of **[10, 35 and 60]%** every **2[ms]**\n",
"- activations every **32ms**\n",
"- always **starts on a big** core"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Trace inspection"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Using kernelshark"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"version = 6\r\n"
]
}
],
"source": [
"# Let's look at the trace using kernelshark...\n",
"!kernelshark {trace_file} 2>/dev/null"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"- Requires a lot of interactions and hand made measurements\n",
"- We cannot easily annotate our findings to produre a sharable notebook"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Using the TRAPpy Trace Plotter"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"An overall view on the trace is still useful to get a graps on what we are looking at."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"code_folding": [],
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"text/html": [
"<style>\n",
"/*\n",
"\n",
" * Copyright 2015-2016 ARM Limited\n",
"\n",
" *\n",
"\n",
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"\n",
" * you may not use this file except in compliance with the License.\n",
"\n",
" * You may obtain a copy of the License at\n",
"\n",
" *\n",
"\n",
" * http://www.apache.org/licenses/LICENSE-2.0\n",
"\n",
" *\n",
"\n",
" * Unless required by applicable law or agreed to in writing, software\n",
"\n",
" * distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"\n",
" * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"\n",
" * See the License for the specific language governing permissions and\n",
"\n",
" * limitations under the License.\n",
"\n",
" */\n",
"\n",
"\n",
"\n",
".d3-tip {\n",
"\n",
" line-height: 1;\n",
"\n",
" padding: 12px;\n",
"\n",
" background: rgba(0, 0, 0, 0.6);\n",
"\n",
" color: #fff;\n",
"\n",
" border-radius: 2px;\n",
"\n",
" position: absolute !important;\n",
"\n",
" z-index: 99999;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".d3-tip:after {\n",
"\n",
" box-sizing: border-box;\n",
"\n",
" pointer-events: none;\n",
"\n",
" display: inline;\n",
"\n",
" font-size: 10px;\n",
"\n",
" width: 100%;\n",
"\n",
" line-height: 1;\n",
"\n",
" color: rgba(0, 0, 0, 0.6);\n",
"\n",
" content: \"\\25BC\";\n",
"\n",
" position: absolute !important;\n",
"\n",
" z-index: 99999;\n",
"\n",
" text-align: center;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".d3-tip.n:after {\n",
"\n",
" margin: -1px 0 0 0;\n",
"\n",
" top: 100%;\n",
"\n",
" left: 0;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".contextRect {\n",
"\n",
" fill: lightgray;\n",
"\n",
" fill-opacity: 0.5;\n",
"\n",
" stroke: black;\n",
"\n",
" stroke-width: 1;\n",
"\n",
" stroke-opacity: 1;\n",
"\n",
" pointer-events: none;\n",
"\n",
" shape-rendering: crispEdges;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".chart {\n",
"\n",
" shape-rendering: crispEdges;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".mini text {\n",
"\n",
" font: 9px sans-serif;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".main text {\n",
"\n",
" font: 12px sans-serif;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".axis line, .axis path {\n",
"\n",
" stroke: black;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".miniItem {\n",
"\n",
" stroke-width: 8;\n",
"\n",
"}\n",
"\n",
"\n",
"\n",
".brush .extent {\n",
"\n",
"\n",
"\n",
" stroke: #000;\n",
"\n",
" fill-opacity: .125;\n",
"\n",
" shape-rendering: crispEdges;\n",
"\n",
"}\n",
"\n",
"</style>\n",
"<div id=\"fig_e79c6fb0e4324389a92f1aa080f4f390\" class=\"eventplot\">\n",
" <script>\n",
" var req = require.config( {\n",
"\n",
" paths: {\n",
"\n",
" \"EventPlot\": '/nbextensions/plotter_scripts/EventPlot/EventPlot',\n",
" \"d3-tip\": '/nbextensions/plotter_scripts/EventPlot/d3.tip.v0.6.3',\n",
" \"d3-plotter\": '/nbextensions/plotter_scripts/EventPlot/d3.min'\n",
" },\n",
" shim: {\n",
" \"d3-plotter\" : {\n",
" \"exports\" : \"d3\"\n",
" },\n",
" \"d3-tip\": [\"d3-plotter\"],\n",
" \"EventPlot\": {\n",
"\n",
" \"deps\": [\"d3-tip\", \"d3-plotter\" ],\n",
" \"exports\": \"EventPlot\"\n",
" }\n",
" }\n",
" });\n",
" req([\"require\", \"EventPlot\"], function() {\n",
" EventPlot.generate('fig_e79c6fb0e4324389a92f1aa080f4f390', '/nbextensions/');\n",
" });\n",
" </script>\n",
" </div>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Suport for FTrace events parsing and visualization\n",
"import trappy\n",
"\n",
"# NOTE: The interactive trace visualization is available only if you run\n",
"# the workload to generate a new trace-file\n",
"trappy.plotter.plot_trace(trace_file)#, execnames=\"task_ramp\")#, pids=[2221])"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Events Plotting"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"The **sched_load_avg_task** trace events reports this information"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Using all the unix arsenal to parse and filter the trace"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"First 5 sched_load_avg events:\n",
" trace-cmd-2204 [000] 1773.509207: sched_load_avg_task: comm=trace-cmd pid=2204 cpu=0 load_avg=452 util_avg=176 util_est=176 load_sum=21607277 util_sum=8446887 period_contrib=125\n",
" trace-cmd-2204 [000] 1773.509223: sched_load_avg_task: comm=trace-cmd pid=2204 cpu=0 load_avg=452 util_avg=176 util_est=176 load_sum=21607277 util_sum=8446887 period_contrib=125\n",
" <idle>-0 [002] 1773.509522: sched_load_avg_task: comm=sudo pid=2203 cpu=2 load_avg=0 util_avg=0 util_est=941 load_sum=7 util_sum=7 period_contrib=576\n",
" sudo-2203 [002] 1773.511197: sched_load_avg_task: comm=sudo pid=2203 cpu=2 load_avg=14 util_avg=14 util_est=941 load_sum=688425 util_sum=688425 period_contrib=219\n",
" sudo-2203 [002] 1773.511219: sched_load_avg_task: comm=sudo pid=2203 cpu=2 load_avg=14 util_avg=14 util_est=14 load_sum=688425 util_sum=688425 period_contrib=219\n",
"grep: write error\n"
]
}
],
"source": [
"# Get a list of first 5 \"sched_load_avg_events\" events\n",
"sched_load_avg_events = !(\\\n",
" grep sched_load_avg_task {trace_file.replace('.dat', '.txt')} | \\\n",
" head -n5 \\\n",
")\n",
" \n",
"print \"First 5 sched_load_avg events:\"\n",
"for line in sched_load_avg_events:\n",
" print line"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"A graphical representation whould be really usefuly!"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Using TRAPpy generated DataFrames"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Generate DataFrames from Trace Events"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [],
"source": [
"# Load the LISA::Trace parsing module\n",
"from trace import Trace\n",
"\n",
"# Define which event we are interested into\n",
"trace = Trace(platform, trace_file, [\n",
" \"sched_switch\",\n",
" \"sched_load_avg_cpu\",\n",
" \"sched_load_avg_task\",\n",
" \"sched_boost_cpu\",\n",
" \"sched_boost_task\",\n",
" \"cpu_frequency\",\n",
" \"cpu_capacity\",\n",
" ])"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Get the DataFrames for the events of interest"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>__comm</th>\n",
" <th>__cpu</th>\n",
" <th>__pid</th>\n",
" <th>comm</th>\n",
" <th>cpu</th>\n",
" <th>load_avg</th>\n",
" <th>load_sum</th>\n",
" <th>period_contrib</th>\n",
" <th>pid</th>\n",
" <th>util_avg</th>\n",
" <th>util_est</th>\n",
" <th>util_sum</th>\n",
" <th>cluster</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Time</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0.000065</th>\n",
" <td>trace-cmd</td>\n",
" <td>0</td>\n",
" <td>2204</td>\n",
" <td>trace-cmd</td>\n",
" <td>0</td>\n",
" <td>452</td>\n",
" <td>21607277</td>\n",
" <td>125</td>\n",
" <td>2204</td>\n",
" <td>176</td>\n",
" <td>176</td>\n",
" <td>8446887</td>\n",
" <td>LITTLE</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.000081</th>\n",
" <td>trace-cmd</td>\n",
" <td>0</td>\n",
" <td>2204</td>\n",
" <td>trace-cmd</td>\n",
" <td>0</td>\n",
" <td>452</td>\n",
" <td>21607277</td>\n",
" <td>125</td>\n",
" <td>2204</td>\n",
" <td>176</td>\n",
" <td>176</td>\n",
" <td>8446887</td>\n",
" <td>LITTLE</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.000380</th>\n",
" <td>&lt;idle&gt;</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>sudo</td>\n",
" <td>2</td>\n",
" <td>0</td>\n",
" <td>7</td>\n",
" <td>576</td>\n",
" <td>2203</td>\n",
" <td>0</td>\n",
" <td>941</td>\n",
" <td>7</td>\n",
" <td>big</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.002055</th>\n",
" <td>sudo</td>\n",
" <td>2</td>\n",
" <td>2203</td>\n",
" <td>sudo</td>\n",
" <td>2</td>\n",
" <td>14</td>\n",
" <td>688425</td>\n",
" <td>219</td>\n",
" <td>2203</td>\n",
" <td>14</td>\n",
" <td>941</td>\n",
" <td>688425</td>\n",
" <td>big</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.002077</th>\n",
" <td>sudo</td>\n",
" <td>2</td>\n",
" <td>2203</td>\n",
" <td>sudo</td>\n",
" <td>2</td>\n",
" <td>14</td>\n",
" <td>688425</td>\n",
" <td>219</td>\n",
" <td>2203</td>\n",
" <td>14</td>\n",
" <td>14</td>\n",
" <td>688425</td>\n",
" <td>big</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" __comm __cpu __pid comm cpu load_avg load_sum \\\n",
"Time \n",
"0.000065 trace-cmd 0 2204 trace-cmd 0 452 21607277 \n",
"0.000081 trace-cmd 0 2204 trace-cmd 0 452 21607277 \n",
"0.000380 <idle> 2 0 sudo 2 0 7 \n",
"0.002055 sudo 2 2203 sudo 2 14 688425 \n",
"0.002077 sudo 2 2203 sudo 2 14 688425 \n",
"\n",
" period_contrib pid util_avg util_est util_sum cluster \n",
"Time \n",
"0.000065 125 2204 176 176 8446887 LITTLE \n",
"0.000081 125 2204 176 176 8446887 LITTLE \n",
"0.000380 576 2203 0 941 7 big \n",
"0.002055 219 2203 14 941 688425 big \n",
"0.002077 219 2203 14 14 688425 big "
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Trace events are converted into tables, let's have a look at one\n",
"# of such tables\n",
"load_df = trace.data_frame.trace_event('sched_load_avg_task')\n",
"load_df.head()"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['kworker/u12:0' 'kworker/5:0' 'kworker/2:1' 'kworker/1:1' 'kworker/0:1'\n",
" 'ksoftirqd/0' 'kworker/3:1' 'kworker/4:1' 'ksoftirqd/5' 'kworker/5:1H'\n",
" 'ksoftirqd/2' 'ksoftirqd/1' 'kworker/2:2' 'kthreadd' 'kworker/2:0'\n",
" 'kworker/u12:2']\n"
]
}
],
"source": [
"df = load_df[load_df.comm.str.match('k.*')]\n",
"# df.head()\n",
"print df.comm.unique()"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>__comm</th>\n",
" <th>__cpu</th>\n",
" <th>__pid</th>\n",
" <th>cpu</th>\n",
" <th>capacity</th>\n",
" <th>max_capacity</th>\n",
" <th>tip_capacity</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Time</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0.002708</th>\n",
" <td>kschedfreq:0</td>\n",
" <td>4</td>\n",
" <td>1489</td>\n",
" <td>0</td>\n",
" <td>236</td>\n",
" <td>447</td>\n",
" <td>357.6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.002710</th>\n",
" <td>kschedfreq:0</td>\n",
" <td>4</td>\n",
" <td>1489</td>\n",
" <td>3</td>\n",
" <td>236</td>\n",
" <td>447</td>\n",
" <td>357.6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.002711</th>\n",
" <td>kschedfreq:0</td>\n",
" <td>4</td>\n",
" <td>1489</td>\n",
" <td>4</td>\n",
" <td>236</td>\n",
" <td>447</td>\n",
" <td>357.6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.002712</th>\n",
" <td>kschedfreq:0</td>\n",
" <td>4</td>\n",
" <td>1489</td>\n",
" <td>5</td>\n",
" <td>236</td>\n",
" <td>447</td>\n",
" <td>357.6</td>\n",
" </tr>\n",
" <tr>\n",
" <th>0.410816</th>\n",
" <td>kschedfreq:1</td>\n",
" <td>2</td>\n",
" <td>1490</td>\n",
" <td>1</td>\n",
" <td>1024</td>\n",
" <td>1024</td>\n",
" <td>819.2</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" __comm __cpu __pid cpu capacity max_capacity \\\n",
"Time \n",
"0.002708 kschedfreq:0 4 1489 0 236 447 \n",
"0.002710 kschedfreq:0 4 1489 3 236 447 \n",
"0.002711 kschedfreq:0 4 1489 4 236 447 \n",
"0.002712 kschedfreq:0 4 1489 5 236 447 \n",
"0.410816 kschedfreq:1 2 1490 1 1024 1024 \n",
"\n",
" tip_capacity \n",
"Time \n",
"0.002708 357.6 \n",
"0.002710 357.6 \n",
"0.002711 357.6 \n",
"0.002712 357.6 \n",
"0.410816 819.2 "
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cap_df = trace.data_frame.trace_event('cpu_capacity')\n",
"cap_df.head()"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Plot the signals of interest"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"code_folding": [],
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"text/html": [
"<table style=\"border-style: hidden;\">\n",
"<tr>\n",
"<td style=\"border-style: hidden;\"><div class=\"ilineplot\" id=\"fig_9f11ea1e66b64b52b8d9c9de9722d549\">\n",
" <script>\n",
" var ilp_req = require.config( {\n",
"\n",
" paths: {\n",
" \"dygraph-sync\": '/nbextensions/plotter_scripts/ILinePlot/synchronizer',\n",
" \"dygraph\": '/nbextensions/plotter_scripts/ILinePlot/dygraph-combined',\n",
" \"ILinePlot\": '/nbextensions/plotter_scripts/ILinePlot/ILinePlot',\n",
" \"underscore\": '/nbextensions/plotter_scripts/ILinePlot/underscore-min',\n",
" },\n",
"\n",
" shim: {\n",
" \"dygraph-sync\": [\"dygraph\"],\n",
" \"ILinePlot\": {\n",
"\n",
" \"deps\": [\"dygraph-sync\", \"dygraph\", \"underscore\"],\n",
" \"exports\": \"ILinePlot\"\n",
" }\n",
" }\n",
" });\n",
" ilp_req([\"require\", \"ILinePlot\"], function() {\n",
" ILinePlot.generate('fig_9f11ea1e66b64b52b8d9c9de9722d549', '/nbextensions/');\n",
" });\n",
" </script>\n",
" </div></td>\n",
"<td style=\"border-style: hidden;\"><div class=\"ilineplot\" id=\"fig_63446a0cdc7e4257b218739f97e04140\">\n",
" <script>\n",
" var ilp_req = require.config( {\n",
"\n",
" paths: {\n",
" \"dygraph-sync\": '/nbextensions/plotter_scripts/ILinePlot/synchronizer',\n",
" \"dygraph\": '/nbextensions/plotter_scripts/ILinePlot/dygraph-combined',\n",
" \"ILinePlot\": '/nbextensions/plotter_scripts/ILinePlot/ILinePlot',\n",
" \"underscore\": '/nbextensions/plotter_scripts/ILinePlot/underscore-min',\n",
" },\n",
"\n",
" shim: {\n",
" \"dygraph-sync\": [\"dygraph\"],\n",
" \"ILinePlot\": {\n",
"\n",
" \"deps\": [\"dygraph-sync\", \"dygraph\", \"underscore\"],\n",
" \"exports\": \"ILinePlot\"\n",
" }\n",
" }\n",
" });\n",
" ilp_req([\"require\", \"ILinePlot\"], function() {\n",
" ILinePlot.generate('fig_63446a0cdc7e4257b218739f97e04140', '/nbextensions/');\n",
" });\n",
" </script>\n",
" </div></td>\n",
"</tr>\n",
"<tr>\n",
"<td style=\"border-style: hidden;\"><div style=\"text-align:center\" id=\"fig_9f11ea1e66b64b52b8d9c9de9722d549_legend\"></div></td>\n",
"<td style=\"border-style: hidden;\"><div style=\"text-align:center\" id=\"fig_63446a0cdc7e4257b218739f97e04140_legend\"></div></td>\n",
"</tr>\n",
"</table>"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Signals can be easily plot using the ILinePlotter\n",
"trappy.ILinePlot(\n",
" \n",
" # FTrace object\n",
" trace.ftrace,\n",
" \n",
" # Signals to be plotted\n",
" signals=[\n",
" 'cpu_capacity:capacity',\n",
" 'sched_load_avg_task:util_avg'\n",
" ],\n",
" \n",
" # Generate one plot for each value of the specified column\n",
" pivot='cpu',\n",
" \n",
" # Generate only plots which satisfy these filters\n",
" filters={\n",
" 'comm': ['task_ramp'],\n",
" 'cpu' : [2,5]\n",
" },\n",
" \n",
" # Formatting style\n",
" per_line=2,\n",
" drawstyle='steps-post',\n",
" marker = '+',\n",
" \n",
" sync_zoom=True,\n",
" group=\"GroupTag\"\n",
"\n",
").view()"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Use a set of standard plots"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"A graphical representation can always be on hand"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"trace = Trace(platform, boost15_trace,\n",
" [\"sched_switch\",\n",
" \"sched_overutilized\",\n",
" \"sched_load_avg_cpu\",\n",
" \"sched_load_avg_task\",\n",
" \"sched_boost_cpu\",\n",
" \"sched_boost_task\",\n",
" \"cpu_frequency\",\n",
" \"cpu_capacity\",\n",
" ],\n",
" plots_prefix='boost15_'\n",
" )"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"Usually a common set of plots can be generated which capture the most useful information realted to a workload we are analysing"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Example of task realted signals"
]
},
{
"cell_type": "code",
"execution_count": 130,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"image/png": "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\nYTtLKEbyKp+gulVp3ovAXIrkqfyamMqH6Hyc4jbP35af4lpFZaI4ieK24XcCi2L1+1zLT/b9AsWt\nrj+vWDa7Yv1vUozWPVqx/JSK5TdRJMEHlPq/jOKhUETE2yOishb216V/F0TEn0p1sv9GkXS9SJEQ\nX1XRfrfS9pcCM4Efp5RurTzQlNLi0rEdWhr57bOU0oPAWcBdFLfJvhG4o7IJ3ZO/3pLBBFxKkfgt\nAPajeMhRpd5Ga5eV+jMPeJ7iDxlHpZTmVml7OkUcPEFR1/trinrS3vpW7vsPgM0pYmwm8Dt6Pq43\nA38ofY9XAf/WQ38kSQ0gimcqSJLUWCLiIYoHEP0mpWQ94XoUERcCT6eUvtrD8ocpaksvTyl9tMb7\n/iRwTErpH9bYWJLUtAbqJeGSJPUqpbTnQPdhA9ZrbWtKqdpDkfq3o4jtKV6RcxewO/B54NxabV+S\nlCcTVUmSGkxE7Aw8UGVRAsanlKo9GbeWqt0qXC+bULwu6A0UtaPTgfPW074lSQ3KW38lSZIkSQ3F\nhylJkiRJkhpKQ9/6GxEO90qSJElSE0spdXs2QkMnqgCNdGty+5w5tAwZQntHBy3jxtVse0DNtlkr\n7XPmADRcn2p5/mul8nu8d/Zs9pswAYBpZ53FtC98of/bbbDj1IZn2rRpTJs2baC7IfWL8avc9SeG\nK69Jui3r6GD+/PmwbFnntUqP26nStnxd0ts+etteeV1ovOtLaLw+NXKO0Jfr8b7Eb3t7Oy0tLfT0\nynJv/ZXqZO5TTw10F6R1Mnfu3IHugtRvxq9yZwwrZ7WIXxNVSZIkSVJDMVGV6mTqMccMdBekdTJ1\n6tSB7oLUb8avcmcMK2e1iF8TValOWidNGuguSOuktbV1oLsg9Zvxq9wZw8pZLeLXRFWqk7aZMwe6\nC9I6aWtrG+guSP1m/Cp3xrByVov4NVGVJEmSJDUUE1WpTrz1V7nztjPlzPhV7oxh5cxbfyVJkiRJ\nTcdEVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElN\nx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3H\nRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdE\nVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RV\nqhNrVJU766OUM+NXuTOGlbNaxG+klNa9J3USEQ3cO6l3bUDrAPdBWhdtGMPKVxvGr/LWhjGsfLXR\n9/gNIKUU3eabqEqSJEmSBkJPiergAejL2mmgVLV9zhxahgyhvaODlnHjarY9oGbbrJX2OXMAGq5P\ntTz/tVL5Pf7ownlsO+INAGy/3Wsc9NaV/d9ugx2nJElqbJXXJN2WdXQwf/58WLaM/SZM6H07VdqW\nr0t620dv2yuvC413fQmN16dGzhFqdT3e3t5OS0sLRLccFbBGVaqpe+4dwW9+tzmX/nZzjvzwfQPd\nHWmdWB+lnBm/yp0xrJzVIn4bf0RVysjnPjaH/SZsyvMLBrHb2wa6N5IkSVKe1mpENSJ+HhHzI2J2\nxbwREXFTRMyJiBkRMaxi2akR8UhEPBQRB1fMf1NEzC4t+2FtDkVqLJts3DrQXZDWie/wU86MX+XO\nGFbOBuI9qhcCh3SZdwpwU0ppHHBzaZqIGA98ABhfWue8iM4bkP8T+EhKaXdg94jouk1JkiRJ0gZq\nrRLVlNLtwMIus48ALi59vhh4T+nzkcD0lNIrKaW5wKPA30fEDsDQlNI9pXa/qFhHahorX2kb6C5I\n68T6KOXM+FXujGHlrBbxW4uHKY1KKc0vfZ4PjCp9bgGermj3NDC6yvxnSvMlSZIkSartw5RSSiki\navo+malTpzJmzBgAhg0bxsSJEzvveS5n6utreubdd7PN5pszbp99arq91kmTBuR4+tS/9vbG6k8N\nz3+tpse1tBTTM2fyyOOPv+6R720zZ67+fmfOLNbv43SjnX+nN8zpskbpj9NOr810WaP0x2mn18v0\nzJnFdJfri/L105/uu4/FS5f2ej3ywvLljC1df3ddv9v1aw/767q9o0uvMmm065uZd98N0Nm/ge5P\nW1sbLzz1FEdPntzZv0Y7X+t6PT5r1iwWLVrE0qVLWbBgAT2JtJbvKY2IMcA1KaUJpemHgNaU0rOl\n23pvSSntGRGnAKSUvl1qdwPwdeDJUpu9SvOPBQ5KKX2iyr7S2vavnnyP6sDK4T2q986ezX4TJvD8\ngkGMb92W52fPX8PavWy3wY5TkiQ1Nt+juvYatU+NnCPU+j2qEUFKqdvLVAet09YLVwMnlj6fCPy2\nYv6UiNgkIt4A7A7ck1J6FlgSEX9ferjSCRXrSE3DGlXlrvxXUClHxq9yZwwrZ7WI37W69TcipgMH\nAdtExFPA14BvA1dExEeAucAxACmlByPiCuBBYBXwqYrh0U8BFwGbA9enlG5Y5yORJEmSJDWFtUpU\nU0rH9rDon3pofwZwRpX5fwZ6v+dAylzxHtX+3/orDbRyPYmUI+NXuTOGlbNaxG8tbv2VJEmSJKlm\nTFSlOrFGVbmzPko5M36VO2NYOatF/JqoSpIkSZIaiomqVCdFjaqUL+ujlDPjV7kzhpUza1QlSZIk\nSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJ\nTcdEVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElN\nx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3H\nRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdE\nVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RV\nqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWq\nE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoT\na1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RVqhNr\nVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tU\nlTvro5Qz41e5M4aVM2tUJUmSJElNx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SV\nO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNx0RVqhNrVJU7\n66OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SVO+ujlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvr\no5Qz41e5M4aVM2tUJUmSJElNx0RVqhNrVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SVO+uj\nlDPjV7kzhpUza1QlSZIkSU3HRFWqE2tUlTvro5Qz41e5M4aVM2tUJUmSJElNp/ET1YjuP9OmVW87\nbVpd2w8991wYPZqWPfZoiP6sl+NttP404Plv2WMPGD0aRo9mv0MOgbPOAqrUqJ51Vme71/2U2lc9\n3gY6/7bf8Nq3NVh/bG/7tWnf1mD9sb3t17Z9Z43f2m6/h+uNoeee2+f2LXvswfY//3nV5uXrsb5e\nz3DWWZ3Xbi177LH6Oq5Bzn9nnxqkP+U+9Xg+GyQ+19S+berUNbZvGT26+NyDSCn1uHCgRURqpP61\nz5lDy5AhtHd00DJuXM22B9Rsm7XSPmcOQMP1qZbnv1Yqv8d7Z89mvwkTeH7BIHZ72wMsfmiv/m+3\nwY5TG562tjZvPVO2jF/lrj8xXHlN0m1ZRwfz58+HZcvYb8KE3rdTpW35uqS3ffS2vfK60HjXl9B4\nfWrkHKEv1+N9id/29nZaWlqICFJK3TLWmo2oRsSpEfFARMyOiEsjYtOIGBERN0XEnIiYERHDurR/\nJCIeioiDa9UPqVFYo6rceZGvnBm/yp0xrJw1TI1qRIwBPgb8XUppArARMAU4BbgppTQOuLk0TUSM\nBz4AjAcOAc6LiMa/DVmSJEmSVHe1Sg6XAK8AW0TEYGALoB04Ari41OZi4D2lz0cC01NKr6SU5gKP\nAvvXqC9SQ/A9qsqd7/BTzoxf5c4YVs4a5j2qKaUXgbOAv1EkqItSSjcBo1JK80vN5gOjSp9bgKcr\nNvE0MLoWfZEkSZIk5a1Wt/6OBU4CxlAkoUMi4oOVbUpPRertyUiN89QkqQasUVXurI9Szoxf5c4Y\nVs5qEb+D170bALwZmJlSWgAQEb8B3go8GxHbp5SejYgdgOdK7Z8BdqpYf8fSvG6mTp3KmDFjABg2\nbBgTJ07sPPDykPL6mp55991ss/nmjNtnn5pur3XSpAE5nj71r729sfpTw/Nfq+lxLS3F9MyZPPL4\n451Px1v5ShttMxeu/n5nzizW7+N0o51/p5122mmnnXY6g+mZM4vpLtcX5eunP913H4uXLu31euSF\n5csZW7r+7rp+t+vXHvbXdXtHl54Q22jXNzPvvhugs38D3Z+2tjZeeOopjp48ubN/jXa+1vV6fNas\nWSxatIilS5eyYMECelKT19NExL7AJcBbgJeBi4B7gF2ABSmlMyPiFGBYSumU0sOULqWoSx0N/B7Y\nreu7aHw9zcBp5Ed1N+K58vU0akZtbW2d/2ORcmP8Knf9iWFfT7P2GrVPjZwjrK/X09RkRDWldF9E\n/AL4E/Aa8BfgfGAocEVEfASYCxxTav9gRFwBPAisAj7VUBmpJEmSJGnA1OrWX1JK3wG+02X2i8A/\n9dD+DOCMWu1fajRFjer8NTWTGpajUcqZ8avcGcPKWS3id9C6d0OSJEmSpNoxUZXqxPeoKnflByBI\nOTJ+lTtjWDmrRfyaqEqSJEmSGoqJqlQnvkdVubM+SjkzfpU7Y1g5s0ZVkiRJktR0TFSlOrFGVbmz\nPko5M36VO2NYObNGVZIkSZLUdExUpTqxRlW5sz5KOTN+lTtjWDmzRlWSJEmS1HRMVKU6sUZVubM+\nSjkzfpU7Y1g5s0ZVkiRJktR0TFSlOrFGVbmzPko5M36VO2NYObNGVZIkSZLUdExUpTqxRlW5sz5K\nOTN+lTtjWDmzRlWSJEmS1HRMVKU6sUZVubM+SjkzfpU7Y1g5s0ZVkiRJktR0TFSlOrFGVbmzPko5\nM36VO2NYObNGVZIkSZLUdExUpTqxRlW5sz5KOTN+lTtjWDmzRlWSJEmS1HRMVKU6sUZVubM+Sjkz\nfpU7Y1g5s0ZVkiRJktR0TFSlOrFGVbmzPko5M36VO2NYObNGVZIkSZLUdExUpTqxRlW5sz5KOTN+\nlTtjWDmzRlWSJEmS1HRMVKU6sUZVubM+SjkzfpU7Y1g5s0ZVkiRJktR0TFSlOrFGVbmzPko5M36V\nO2NYObNGVZIkSZLUdExUpTqxRlW5sz5KOTN+lTtjWDmzRlWSJEmS1HRMVKU6sUZVubM+SjkzfpU7\nY1g5s0ZVkiRJktR0TFSlOrFGVbmzPko5M36VO2NYObNGVZIkSZLUdExUpTqxRlW5sz5KOTN+lTtj\nWDmzRlWSJEmS1HRMVKU6sUZVubM+SjkzfpU7Y1g5s0ZVkiRJktR0TFSlOrFGVbmzPko5M36VO2NY\nObNGVZIkSZLUdExUpTqxRlW5sz5KOTN+lTtjWDmzRlWSJEmS1HRMVKU6sUZVubM+SjkzfpU7Y1g5\ns0ZVkiRJktR0TFSlOrFGVbmzPko5M36VO2NYObNGVZIkSZLUdExUpTqxRlW5sz5KOTN+lTtjWDmz\n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\nUM455xyOOeYYRowYwfTp0znyyCNf12b77bdn0qRJ3HXXXXzgAx/onD9+/HjOPfdcpkyZQktLC0OH\nDmW77bZj0003rdHRS5JUe976K9VJUaO610B3Q+q3trY2/6LfR29605v461//2uPyn/3sZ/zsZz/r\nnP7617/e+XnMmDG8+uqra9zHpz71KT71qU/12ub3v/991fknnngiJ554IgAdHR2cdtppr6tbbUbG\nr3JnDCtntYhfR1QlSWpy11xzDcuWLeOll17i5JNPZp999mGXXXYZ6G5JktQjE1WpTqxRVe78S/76\nN2TIEIYOHdrt584771yn7V599dWMHj2a0aNH89hjj3HZZZfVqMeNy/hV7oxh5awW8eutv5IkNYiO\njo66bPeCCy7gggsuqMu2JUmqB0dUpTrxParKne/wU86MX+XOGFbOahG/JqqSJEmSpIbirb9SnSxZ\nOpn3fHg5gwbBQQes5LMffWmguyStFeujlDPjV7kzhpUz36MqNbj3Hfoy+45/hd/esNlAd0WSJEnK\nhomqVDdtvO+wl3nH368c6I5I/WJ9lHJm/Cp3xrByZo2qJEmSJKnpmKhKddM60B2Q1on1UX03ZswY\nbr755oHuRp8NGjSIxx9/vKbbvP3229lzzz07pwf6nBi/yp0xrJxZoypJUgOICCJivezroosu4u1v\nf/t62Vdvuia7b3/723nooYc6p9fnOZEkNR8TVakOhm75Gm/aZwabbZoGuitSv1kfpTVJqXF/xxm/\nyp0xrJxZoyo1qM02g+99dQmDfQGUtMG455572HvvvRkxYgQf/vCHWbFiBQAXXHABu+++OyNHjuTI\nI49k3rx5nevMnDmTt7zlLQwbNoz999+fu+66q3PZRRddxNixY9lqq63YddddufTSS3nooYf4xCc+\nwV133cXQoUMZMWIEACtWrODkk09ml112Yfvtt+eTn/wkL7/8cue2vvvd79LS0sKOO+7Iz3/+8z4d\nT2trKz/72c9e15/ySO473vEOAPbdd1+GDh3Kr3/9a9ra2thpp536efYkSXo9L6OlOmmdNGmguyCt\nkxzro9ra1v1W09bWtR8lTClx6aWXMmPGDLbYYgve/e53841vfIN/+Id/4Mtf/jI33XQT48eP5+ST\nT2bKlCnceuutvPjii7zrXe/iRz/6EcceeyxXXHEF73rXu3jsscfYZJNN+OxnP8uf/vQndt99d+bP\nn8+CBQvYc889+a//+i9++tOfcvvtt3fu/5RTTuGJJ57gvvvuY/DgwRx33HGcfvrpnHHGGdxwww2c\nddZZ/O///i9jxozhox/9aJ+Oqbdbd2+77TYGDRrE/fffz6677go03uhPjvErVTKGlbNaxK+JqiSp\nafQnyayFiODTn/40o0ePBuArX/kKn/nMZ5g3bx4f+chHmDhxIgDf+ta3GD58OE8++SS33XYbe+yx\nB8cffzwAU6ZM4ZxzzuHqq6/m/e9/P4MGDWL27NnsuOOOjBo1ilGjRgHdb7dNKXHBBRdw//33M2zY\nMABOPfVUjj/+eM444wyuuOIKPvzhDzN+/HgATjvtNC677LL1cl4kSeovb/2V6qRt5syB7oK0Thpt\nhKzRVd72uvPOO9Pe3k57ezs777xz5/wtt9ySkSNH8swzzzBv3rzXLQPYZZddaG9vZ4sttuDyyy/n\nJz/5CS0tLRx++OE8/PDDVff7/PPPs2zZMt70pjcxfPhwhg8fzqGHHsoLL7wAwLx587r1bUNg/Cp3\nxrByZo2qJEkN4m9/+9vrPre0tNDS0sKTTz7ZOf+ll15iwYIF7Ljjjt2WATz55JOdo7IHH3wwM2bM\n4Nlnn2XPPffkYx/7GEC323G32WYbNt98cx588EEWLlzIwoULWbRoEUuWLAFghx126Na3vthyyy15\n6aWXOqefffbZPq0nSVItmKhKdWKNqnJnfVTfpZT48Y9/zDPPPMOLL77IN7/5TaZMmcKxxx7LhRde\nyH333ceKFSv48pe/zAEHHMDOO+/MoYceypw5c5g+fTqrVq3i8ssv56GHHuLwww/nueee46qrruKl\nl15i4403Zsstt2SjjTYCYNSoUTz99NO88sorQPGamI997GOcdNJJPP/88wA888wzzJgxA4BjjjmG\niy66iP/7v/9j2bJlnHbaaX06pokTJ/Kb3/yG5cuX8+ijj77uwUrlfjz22GO1OoU1Z/wqd8awcuZ7\nVCVJagARwfHHH8/BBx/M2LFj2X333fn3f/93Jk+ezH/8x39w1FFH0dLSwhNPPNFZHzpy5EiuvfZa\nzjrrLLbZZhu+973vce211zJixAhee+01zj77bEaPHs3IkSO5/fbb+c///E8AJk+ezN57783222/P\ndtttB8CZZ57JbrvtxgEHHMDWW2/NO9/5TubMmQPAIYccwkknncQ//uM/Mm7cOCZPntyn95t+7nOf\nY5NNNmHUqFF86EMf4oMf/ODr1ps2bRonnngiw4cP58orr/S9qZKkmopGfgdaRKRG6l/7nDm0DBlC\ne0cHLePG1Wx7QM22WSvtpQucRutTLc9/rVR+j/fOns1+EyYARY1q66RJ3HLnJpx+9lBuuXLB2m23\nwY5TG562traG+ot+RDT0ezvVN+vre2y0+JXWVn9iuPKapNuyjg7mz58Py5Z1Xqv0uJ0qbcvXJb3t\no7ftldeFxru+hMbrUyPnCH25Hu9L/La3t9PS0lL+/0K3v3Q6oipJkiRJaigmqlKdWKOq3Dka1fz2\n3ntvhg4d2u1n+vTpA921dWb8KnfGsHLme1QlSVK/PfDAAwPdBUmSqnJEVaoT36Oq3PkOP+XM+FXu\njGHlzPeoSpIkSZKajrf+SnVijapy14j1Ub7+RH3ViPErrQ1jWDmzRlWStMHw1TSSJG04vPVXqhNr\nVJU766OUM+NXuTOGlTNrVCVJkiRJTcdEVaoTa1SVO+ujlDPjV7kzhpWzWsSviaokSZIkqaGYqEp1\nYo2qcmd9lHJm/Cp3xrByZo2qJEmSJKnpmKhKdWKNqnJnfZRyZvwqd8awcmaNqiRJkiSp6ZioSnVi\njapyZ32Ucmb8KnfGsHJmjaokSZIkqemYqEp1Yo2qcmd9lHJm/Cp3xrByZo2qJEmSJKnpmKhKdWKN\nqnJnfZRyZvwqd8awcmaNqiRJkiSp6URKaaD70KOISEwb6F5IkiRJkupiGqSUoutsR1QlSZIkSQ2l\n4UdUG6l/7XPm0DJkCO0dHbSMG1ez7QE122attM+ZA9Bwfarl+a+Vyu/x3tmz2W/CBKCoUW2dNIlb\n7tyE088eyi1XLli77TbYcWrD09bW5lMnla3K+L3jjhGsWrUQgMGDh3PggS8OYM+kvunP7+DKa5Ju\nyzo6mD9/Pixb1nmt0uN2qrQtX5f0to/etldeFxrv+hIar0+NnCP05Xq8L/Hb3t5OS0sLEVF1RHXw\nOvdWkiSpga1atZDW1uIP321t3a6FJEkNyFt/pTrxParKnaOpypnxq9wZw8qZ71GVJEmSJDUdE1Wp\nTnyPqnLnO/yUM+NXuTOGlTPfoypJkiRJajo+TEmqE2tUlTvro5SznuJ38ODhnQ9U8gnAamT+DlbO\nahG/JqqSJGmDUZmY+gRgSWpc3vor1Yk1qsqd9VHKmfGr3BnDypk1qpIkSZKkpmOiKtWJNarKnfVR\n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\n/vea4ykC/O53Wv8rrgBGj9Zjv/pVF+i9954L4O67T4P0fv1c/QcOBO6+Wz+/4QY3tPbRR12Q9vDD\nbqjuqFF63v77a/379wfOOcfVc/ZslyM8b54LVB94QIf4lpZqnW2O6u9+p8O1jz3WrX36xz8CDQ26\nPXeurh9r63/CCXrv9ttPf4dJk9x6rN/7nhte/NhjLqh96CF3b+6+W+vRtaveg759dd3cSZP081//\n2uUof/3reh2//r7q6mr+RZ+CxfZLoWMbppBlo/2KiZ8esoCIiCmk+kXq6lBeVoZIYyPK/dli2lge\ngKyVmS2R6HSmhVanbN7/bPF/x0VLlmB8NGJoa6BaaN+T9j58SKKQsf1S6FrThv1nkoTPGhtRX18P\nbNnS9KySspwkx9rnknTXSFeePRcovOdLoPDqVMgxQibP45m030gkgvLycogIjDEJY8o4mRJRjrRn\nbypRLvAhn0LG9kuhYxumkHEdVSIiIiIiIupwGKgS5Uhr11ElKhRcw49CxvZLoWMbppBxHVUiIiIi\nIiLqcBioEuUIc1QpdMyPopCx/VLo2IYpZMxRJSIiIiIiog4nr4GqiJwsIu+IyLsicm0+60KUbcxR\npdAxP4pCxvZLoWMbppAFnaMqIp0A3A7gZACHALhQRA7OV32Isq32zTfzXQWiNqmtrc13FYhaje2X\nQsc2TCHLRvvNZ4/qkQCWGmOWG2N2AvgrgDPzWB+irNqwaVO+q0DUJhs2bMh3FYhaje2XQsc2TCHL\nRvvNZ6C6L4CV3v6q6HtERERERES0F8tnoGryeG2inFu+cmXzBxEVsOXLl+e7CkStxvZLoWMbppBl\no/2KMfmJF0VkIoBZxpiTo/vXA9hjjPmpdwyDWSIiIiIiog7MGCPx7+UzUC0G8F8AUwFEALwM4EJj\nzNt5qRAREREREREVhOJ8XdgYs0tErgbwOIBOAO5ikEpERERERER561ElIiIiIiIiSiafkykRERER\nERERJWCgSkRERERERAWFgSoREREREREVFAaqREREREREVFAYqBIREREREVFBYaBKREREREREBYWB\nKhERERERERUUBqpERERERERUUBioEhERERERUUFhoEpEREREREQFhYEqERERERERFRQGqkRERERE\nRFRQGKgSERERERFRQWGgSkRERERERAWFgSoREREREREVFAaqREREREREVFAYqBIREREREVFBYaBK\n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\nERk9qkAZPfpo9rh3b2v58cdb69tvsjTbcvvrAQAAgLMMhSpQkMHe3tQhAAtCfxQiI38RHTmMyPLI\n32ULD6NYt99+u/r6+iRJPT09GhgYmHrjzVPKizUe2rVLFy5frv61a3PdX/OmO4v9fuYVX71ernhy\n/PzzGvdXKtK2bap+7Ws6fuSIdPCgtHq1qj//efb63l7prbdUXbUqG0vSqlXKtpYGG89XG88PNp5/\nYf16jSxbpsFNm6StW0vzfhkzZsyYMWPGJR4PDWXj5vyyMW7On3Y/84zemJg4ZX37+NCxY7q0Mf+e\nvv0p89dZjjd9f5v6+1vbl2x+KWkqvtTxVKtVHRod1aYNG6biK9vntdD5eK1W0/j4uCYmJnT48GHN\nxtx91pWLwcz6JH3L3dfMsM5Tx9euPjKiyooVqk9OqtJI5jz2Jym3fealPjIiSaWLKc/PPy/tv8c9\nw8Na99nPSg89pOrmzRocHZUeeki66irp6aezDS67THrxxbmXr7pK9SeeKNX7xNmnWq1O/Y8FiIb8\nRXRnksPtc5JT1k1OamxsTDp6VOvWnDLtPu1rm/OvuY4x1/6a20rlm19K5YupzDXCfObj88nfer2u\nSqUiM5O72/T1SxYc7QKY2VckDUnqN7NRM/t4yngAAAAAAOklvfTX3W9OeXygEBuzb1wa/OhHsxsq\nSdJ117XWt3+/6mzL7a8HEuFsFCIjfxEdOYzI8sjf0veoAuHccUf2uH59q/i8777W+gceOP3yffdJ\nk5PFxQgAAACUWNJLf4Fu1ryZABBV8wYIQETkL6IjhxFZHvlLoQoAAAAAKBUKVaAgg+09p0BA9Ech\nMvIX0ZHDiCyP/KVQBQAAAACUCoUqUBB6VBEd/VGIjPxFdOQwIqNHFQAAAADQdShUgYLQo4ro6I9C\nZOQvoiOHERk9qgAAAACArkOhChSEHlVER38UIiN/ER05jMjoUQUAAAAAdB0KVaAg9KgiOvqjEBn5\ni+jIYURGjyoAAAAAoOtQqAIFoUcV0dEfhcjIX0RHDiMyelQBAAAAAF2HQhUoCD2qiI7+KERG/iI6\nchiRhe9RNbONZvaimb1kZp9OGQsAAAAAoBySFapmtlTSVkkbJV0u6WYze0+qeIC80aOK6OiPQmTk\nL6IjhxFZ9B7VqyS97O773P2EpK9K+nDCeAAAAAAAJZCyUF0labRtvL/xHNAV6FFFdPRHITLyF9GR\nw4gseo+qJzw2AAAAAKCkliU89gFJvW3jXmVnVU9y++23q6+vT5LU09OjgYGBqQq9ee3zYo2Hdu3S\nhcuXq3/t2lz31zzzttjvZ17x1evliifHzz+vcX+lko2HhvTSK69o3Zo1kqQt27Zp4IorWr/fRs/q\nfMdl+/wZn33jWq2mzZs3lyYexozJX8Zn07j5XMfbDw1l42nzi+b8afczz+iNiYk55yOHjh3TpY35\n9/TtT5m/znK86fvb1N/f2r5E85uhXbskaSq+1PFUq1UdGh3Vpg0bpuIr2+c1n/l487mZ1tdqNY2P\nj2tiYkKHDx/WbMw9zYlNM1sm6ceSNkiqS3pa0s3u/kLbazxVfDOpj4yosmKF6pOTqjSSOY/9Scpt\nn3mpj4xIUuliyvPzz0v773HP8PBUoVodGlrQ5b9le584+1Sr1an/sQDRkL+I7kxyuH1Ocsq6yUmN\njY1JR49OzVVm3c8Mr23OS+Y6xlz7a24rlW9+KZUvpjLXCPOZj88nf+v1uiqVisxM7m7T1yc7o+ru\nb5rZnZK+LWmppPvbi1QgOnpUER2TfERG/iI6chiR5ZG/KS/9lbvvlLQzZQwAAAAAgHJZkjoAoFvx\nPaqIrr3PBIiG/EV05DAiyyN/KVQBAAAAAKVCoQoUhB5VREd/FCIjfxEdOYzI8shfClUAAAAAQKlQ\nqAIFoUcV0dEfhcjIX0RHDiMyelQBAAAAAF2HQhUoCD2qiI7+KERG/iI6chiR0aMKAAAAAOg6FKpA\nQehRRXT0RyEy8hfRkcOIjB5VAAAAAEDXoVAFCkKPKqKjPwqRkb+IjhxGZPSoAgAAAAC6DoUqUBB6\nVBEd/VGIjPxFdOQwIqNHFQAAAADQdShUgYLQo4ro6I9CZOQvoiOHERk9qgAAAACArpOkUDWz3zGz\nvWb2CzO7MkUMQNHoUUV09EchMvIX0ZHDiCxyj+qwpJskfS/R8YHC1fbuTR0CsCC1Wi11CMAZI38R\nHTmMyPLI32U5xNExd39RkswsxeGBRTH+s5+lDgFYkPHx8dQhAGeM/EV05DAiyyN/6VEFAAAAAJRK\nYWdUzewxSStnWHWvu3+rqOMCZbFvdDR1CMCC7Nu3L3UIwBkjfxEdOYzI8shfc/eFR3KmBzd7UtKf\nuvuPZlmfLjgAAAAAQOHc/ZSe0CQ9qtPM2qg6U8AAAAAAgO6W6utpbjKzUUlXS3rEzHamiAMAAAAA\nUD5JL/0FAAAAAGC6Ut7118w2mtmLZvaSmX06dTxAJ8ys18yeNLO9ZvacmX0qddw0/oIAAASmSURB\nVExAp8xsqZntMTNufodwzKzHzHaY2Qtm9ryZXZ06JmC+zOwzjTnEsJn9q5m9LXVMwFzM7AEzGzOz\n4bbnfsnMHjOzETP7TzPr6XS/pStUzWyppK2SNkq6XNLNZvaetFEBHTkh6W53v0LZ5e1/TA4joLsk\nPS+Jy24Q0d9L+g93f4+ktZJeSBwPMC9m1ifpDklXuvsaSUsl/V7KmIB5eFBZ7dbuHkmPuXu/pO80\nxh0pXaEq6SpJL7v7Pnc/Iemrkj6cOCZg3tz9oLvXGsuTyiZIlbRRAfNnZr8q6Tcl/ZPmuOEdUEZm\n9nZJv+7uD0iSu7/p7m8kDguYr58p+4P3+Wa2TNL5kg6kDQmYm7t/X9KRaU/fIGl7Y3m7pBs73W8Z\nC9VVktq/gHJ/4zkgnMZfRtdJ2pU2EqAjn5f0Z5LeSh0IcAZWS3rdzB40sx+Z2TYzOz91UMB8uPv/\nSvpbSa9Kqksad/fH00YFnJGL3X2ssTwm6eJOd1DGQpXLzNAVzGyFpB2S7mqcWQVKz8yul/RTd98j\nzqYipmWSrpT0j+5+paT/0xlccgakYGaXStosqU/Z1VgrzOxjSYMCFsizu/d2XOOVsVA9IKm3bdyr\n7KwqEIaZnSPpIUlfdvdvpI4H6MB6STeY2f9I+oqk3zCzf04cE9CJ/ZL2u/t/NcY7lBWuQATvlzTk\n7ofd/U1J/67s32UgmjEzWylJZvYrkn7a6Q7KWKjulvRuM+szs3Ml/a6kbyaOCZg3MzNJ90t63t23\npI4H6IS73+vuve6+WtkNPJ5w999PHRcwX+5+UNKomfU3nrpO0t6EIQGdeFHS1Wa2vDGfuE7Zje2A\naL4p6bbG8m2SOj5xsyzXcHLg7m+a2Z2Svq3sTmf3uzt360MkH5R0i6RnzWxP47nPuPujCWMCzhTt\nGIjoTyT9S+MP3v8t6eOJ4wHmxd2faVzFslvZfQJ+JOkLaaMC5mZmX5F0jaQLzWxU0p9L+itJ/2Zm\nn5S0T9JHO95vdskwAAAAAADlUMZLfwEAAAAAZzEKVQAAAABAqVCoAgAAAABKhUIVAAAAAFAqFKoA\nAAAAgFKhUAUAAAAAlAqFKgAABTGzXzazPY2f18xsf2N5wsy2po4PAICy4ntUAQBYBGb2F5Im3P3v\nUscCAEDZcUYVAIDFY5JkZoNm9q3G8mfNbLuZfc/M9pnZR8zsb8zsWTPbaWbLGq97n5lVzWy3mT1q\nZitTvhEAAIpEoQoAQHqrJV0r6QZJX5b0mLuvlXRM0ofM7BxJ/yDpt939/ZIelPSXqYIFAKBoy1IH\nAADAWc4l7XT3X5jZc5KWuPu3G+uGJfVJ6pd0haTHzUySlkqqJ4gVAIBFQaEKAEB6P5ckd3/LzE60\nPf+Wsv9Xm6S97r4+RXAAACw2Lv0FACAtm8drfizpIjO7WpLM7Bwzu7zYsAAASIdCFQCAxeNtjzMt\na9qyJLm7n5C0SdJfm1lN0h5JHygyUAAAUuLraQAAAAAApcIZVQAAAABAqVCoAgAAAABKhUIVAAAA\nAFAqFKoAAAAAgFKhUAUAAAAAlAqFKgAAAACgVChUAQAAAAClQqEKAAAAACiV/wcXDmKaSm4IaQAA\nAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7fa97c9ea590>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"trace.analysis.tasks.plotTasks(\n",
" tasks=['task_ramp'],\n",
" signals=['util_avg', 'boosted_util', 'sched_overutilized', 'residencies'],\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### Example of Clusters related singals"
]
},
{
"cell_type": "code",
"execution_count": 131,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA7UAAAISCAYAAAATN+jXAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3X+cXXdd4P/XuzSNqQMdoEvbSSnRwFQLKSnyS/aLZvlR\nq/Ijrl0iX6NE0Xa3uqDCaipb6RKtLSuyuG5dAgVaSqv1R7NSBNqyjMKOpCs2GCjNtEkDSS5NSWBo\nhqQ/gPf+cc6d3NzcyY+ZO3PvJ/N6Ph7zmPs553POfd8zn0w+7znnfU5kJpIkSZIkleikXgcgSZIk\nSdJ0mdRKkiRJkoplUitJkiRJKpZJrSRJkiSpWCa1kiRJkqRimdRKkiRJkoplUitJmpGI+NGIuCUi\ndkXEoxGxJyJuj4hfiIiT6j5rIuJ7EXHOLLz/ioh4e0REt/c9XfVn7fR1Q69j6xezOSYkSfPLyb0O\nQJJUroj4DeBdwKeA3wa+AjwZ+AngfwLjwEdnOYwVwO8B64B+evj6B4H3ti37ei8C6VO3AS8GHux1\nIJKkspnUSpKmJSJ+DPhj4E8y8zfaVn80Iv4IeOJchtS1HUUszMxHZ7ibXZl51zG+3xMAMvO7M3zP\nYmTmHmBPr+OQJJXPy48lSdP1O1RJyW93WpmZ2zNz81Qb15eevr1t2ZJ6+Rtalr0gIu6oL2veHxFb\nI+J/1OuupDpLC/B48zLflm1PjYhrIuKB+tLobRHxu62XKteXL38vIn4mIt4XEV+nPnsYEcMRcWtE\n7I6IAxHxlfpS6ycc78Hq8Nl/PyLWRsQDwKPAc+p1Px4Rn4qIhyNiIiI+ERHPbtv+CfX2X4uIb0fE\npyPi2e3HNCI+VO+//f1HIuLTbcv+VUT8z4jYGRGPRMSXI+JX2/o0Lxl+UUR8JCK+VV92/p6IWNjW\n9/sj4ur65/VIHetfRcTT2vZ1Ttt2l0TEF+rj/fWIeH9EPLmtz5vr+PZHxDci4v9GxMrj+RlIkk4c\nnqmVJB23Oqn7N8DfZOZjM9jVVJcLZ/0+A8Angc8BbwD2AT8A/Gjd733AYuCNwL8GJs90RsTJ9bY/\nDLwD2FxvdwXwFOCtbe/534G/A34e+L562ceAvcC/p0rgzwZ+kuqPwkc7q3pSHcPBD5X5nZbmGmAr\n8FvAt4GvRcRPA/+L6pLtn6c6+/w7wGci4vzM3FlveyVwOdWl37cDLwD+tvk2bXF0OsbZujwingR8\n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\nRcTtETHYsu7yiLgvIu6NiAtblv9IRGyu171ntuKVJEmSJJVnNs/UfhC4qG3ZWuCOzBwGPlW3iYjz\ngFXAefU210ZE1Nv8GfDGzHwW8KyIaN+nVDxralU667lUMsevSucYVsn6uqY2Mz8DfLNt8WuA6+vX\n1wMr69evBW7OzMczcztwP/CiiDgLeGJm3lX3u6FlG0mSJEnSPDfXNbVnZObu+vVu4Iz69RCws6Xf\nTmBxh+W76uXSCcWaWpXOei6VzPGr0jmGVbK+rqk9msxMIHv1/pIkSZKk8p08x++3OyLOzMwH60uL\nH6qX7wKe3tLvbKoztLvq163Ld0218zVr1rBkyRIABgcHWb58+eQ12s2/AMxVe3TjRk7fupXhOraZ\n7u+zDzzAwIIFrOjS/mbl8zYac//+0HF983h16/h3qz08NFS1R0e5b9s2Lli2jKaRrVsPfp76zG2z\n1vao7Tk+vrZtd2o39Us8tm0fT7upX+KxbXtO2lu3Vm0qzfnF8ro9Of9cuvSQ9a3zkYkHHuD8pz71\n4P5GRxk+//yD/Y9zfrPnwAEuHh4Geji/nKI9unEjwGR8vY5nZMsW9ixaxMUwGV+/Ha/TFy06OB6m\nsb9NmzYxPj7Ovn372FuPl06iOmE6OyJiCfDRzFxWt98J7M3MayJiLTCYmWvrG0XdBLyQ6vLiO4Fn\nZmZGxEbgTcBdwMeAP8nMT3R4r5zNz3K8GmNjDG3YQGPlSoZGRuCSS2a0v/F16xhcuBBWr6YxMcFQ\n/Y+pHzTGxgB6E9P69R2PbfN4NVau7LtjNTQwAMDdmzcfktRy442wevVx73P8uusYvOKKboV4qCmO\nryRJKtvk3BIOm3+MX3cd33r0UU5buPBgnw79mn0ffvhheOwxzlm8eHKuClRznuOc3zTnuePr1rF/\n1aq+m8dBj+a8naxfT2PFCoY2bOjbHGFoYKArcTUaDYZuu4249FIyM9rXnzSjvR9BRNwMjALnRsSO\niPgl4GrglRExBrysbpOZ9wC3APcAHwcua8lQLwPeD9wH3N8poZVKZ02tStf866pUIsevSucYVsm6\nMX5n7fLjzHz9FKteMUX/q4CrOiz/PLDs8C0kSZIkSfPdrJ2plXTsfE6tStesf5FK5PhV6RzDKlk3\nxq9JrSRJkiSpWCa1Uh+wplals55LJXP8qnSOYZWsG+PXpFaSJEmSVCyTWqkPWFOr0lnPpZI5flU6\nx7BKZk2tJEmSJGleM6mV+oA1tSqd9VwqmeNXpXMMq2TW1EqSJEmS5jWTWqkPrHjJS+CUU+DGG+GW\nW3odjnTcrOdSyRy/KsL69VOucgyrZN0YvyfPPAxJXfG611Xfb7yxt3FIkiRJBfFMrdQHrKlV6azn\nUskcvyqdY1gls6ZWkiRJkjSvmdRKfcDn1Kp01nOpZI5flc4xrJL5nFpJkiRJ0rxmUiv1AWtqVTrr\nuVQyx69K5xhWyYqtqY2IN0fE5oj4YkS8uV72lIi4IyLGIuL2iBhs6X95RNwXEfdGxIW9iFmSJEmS\n1H/mPKmNiOcAvwK8AHgu8KqIWAqsBe7IzGHgU3WbiDgPWAWcB1wEXBsRnmHWCcWaWpXOei6VzPGr\n0jmGVbJSa2p/CNiYmY9k5neBvwd+FngNcH3d53pgZf36tcDNmfl4Zm4H7gdeOLchS5IkSZL6US+S\n2i8CL60vNz4V+CngbOCMzNxd99kNnFG/HgJ2tmy/E1g8V8FKc8GaWpXOei6VzPGr0jmGVbJujN+T\nZx7G8cnMeyPiGuB24NvAJuC7bX0yIvJIu5nFECVJkiRJhZjzpBYgMz8AfAAgIv6A6uzr7og4MzMf\njIizgIfq7ruAp7dsfna97DBr1qxhyZIlAAwODrJ8+fLJa7SbfwGYq/boxo2cvnUrw3VsM93fZx94\ngIEFC1jRpf3NyudtNOb+/aHj+ubx6tbx71Z7eGioao+Oct+2bVywbBlNI6Ojk7W1zTO3x9ye4+Nr\n23andlO/xGPb9vG0m/olHtu256S9dWvVptKcXyyv25Pzz6VLD1nfOh+ZeOABzn/qUw/ub3SU4fPP\nP9h/69bD9n+k+c2eAwe4eHgY6OH8cor26MaNAJPx9TqekS1b2LNoERfDZHz9drxOX7To4HiYxv42\nbdrE+Pg4+/btY289XjqJzLk/6RkRT8vMhyLiHOCTwIuBtwF7M/OaiFgLDGbm2vpGUTdR1dEuBu4E\nnpltgUdE+6KeaoyNMbRhA42VKxkaGYFLLpnR/sbXrWNw4UJYvZrGxARD9T+mftAYGwPoTUzr13c8\nts3j1Vi5su+O1dDAAAB3b958SFI76cYbYfXqY97n+HXXMXjFFd0K8VBTHF9JkjTHuvx/8uTcEg6b\nd4xfdx3fevRRTlu48GCfDv2afR9++GF47DHOWbx4cq4KVHOe45zXNOe54+vWsX/Vqr6bx0GP5ryd\nrF9PY8UKhjZs6NscYWhgoCtxNRoNhm67jbj0UjIz2tefNKO9T99fRcSXgL8FLsvMbwFXA6+MiDHg\nZXWbzLwHuAW4B/h43b9/slepC6ypVemaf12VSuT4VekcwypZN8Zvry4//rEOy74BvGKK/lcBV812\nXJIkSZKksvTqTK2kFj6nVqVr1r9IJXL8qnSOYZWsG+PXpFaSJEmSVCyTWqkPWFOr0lnPpZI5flU6\nx7BK1o3xa1IrSZIkSSqWSa3UB6ypVems51LJHL8qnWNYJbOmVpIkSZI0r5nUSn3AmlqVznoulczx\nq9I5hlUya2olSZIkSfOaSa3UB6ypVems51LJHL8qnWNYJbOmVpIkSZI0r5nUSn3AmlqVznoulczx\nq9I5hlUya2olSZIkSfOaSa3UB6ypVems51LJHL8qnWNYJbOmVpIkSZI0r5nUSn3AmlqVznoulczx\nq9I5hlWyYmtqI+LyiPhSRGyOiJsiYmFEPCUi7oiIsYi4PSIG2/rfFxH3RsSFvYhZkiRJktR/5jyp\njYglwK8Cz8vMZcATgJ8D1gJ3ZOYw8Km6TUScB6wCzgMuAq6NCM8w64RiTa1KZz2XSub4VekcwyrZ\nnNTURsS2iPgPbctum8F7Pgw8DpwaEScDpwIN4DXA9XWf64GV9evXAjdn5uOZuR24H3jhDN5fkiRJ\nknSCOJYzno8DKyLigxGxsF62eLpvmJnfAN4FfJUqmR3PzDuAMzJzd91tN3BG/XoI2Nmyi50zeX+p\nH1lTq9JZz6WSOX5VOsewSjZXNbX7M3MV8GXgHyLiGTN5w4hYCvwGsIQqYR2IiNWtfTIzgTzCbo60\nTpIkSZI0T5x8rB0z850R8c/A7cBTZvCezwdGM3MvQET8DfCjwIMRcWZmPhgRZwEP1f13AU9v2f7s\netlh1qxZw5IlSwAYHBxk+fLlk9doN/8CMFft0Y0bOX3rVobr2Ga6v88+8AADCxawokv7m5XP22jM\n/ftDx/XN49Wt49+t9vDQUNUeHeW+bdu4YNkymkZGRydra5tnbo+5PcfH17btTu2mfonHtu3jaTf1\nSzy2bc9Je+vWqk2lOb9YXrcn559Llx6yvnU+sm/HDp572mkH9zc6yvD55x/sv3XrYfs/0vxmz4ED\nXDw8DPRwfjlFe3TjRoDJ+Hodz8iWLexZtIiLYTK+fjtepy9adHA8TGN/mzZtYnx8nH379rG3Hi+d\n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\nZKT38fSqvXVr1abSnF8Mn38+0DL/XLr0kPWt85E9Bw6wtJ5/t28/MjoKW7cetv8p5zP1/i4eHgZ6\nOL+coj26cSPAZHy9jmdkyxb2LFrExTAZX78dr9MXLTo4Hqaxv02bNjE+Ps6+ffvYW4+XTqI6KTq3\nIuIfgF/JzLGIuBI4tV61NzOviYi1wGBmrq1vFHUTVR3tYuBO4JnZFnhEtC/qqcbYGEMbNtBYuZKh\nkZGj31XxKMbXrWNw4UJYvZrGxARD9T+mftAYGwPoTUzr13c8ts3j1Vi5su+O1dDAAAB3b958SFLb\n0Y03wurVR+wyft11DF5xRbdCPNQUx1eSTijH8ruuV78Pm3fp9XfxzLX+DFvvflzKse3yGJycW8Jh\nc43GxASP33ADpy1ceLBPh37Nvrt374b9+yfnNY2JCYBqznMMc5n2/Q0NDzO+bh37V63qu3kc9GjO\n28n69TRWrGBow4a+zRGGBga6Elej0WDottuISy8lM6N9/Ukz2vv0/UfgIxHxBaq7H/8BcDXwyogY\nA15Wt8nMe4BbgHuAjwOX9VX2KnWBNbUqXfOvq1KJrKlV6fwdrJJ1Y/z25Dm1mfkF4AUdVr1iiv5X\nAVfNalCSJEmSpOL06kytpBY+p1ala9a/SCXyObUqnb+DVbJujF+TWkmSJElSsUxqpT5gTa1KZz2X\nSmZNrUrn72CVrBvj16RWkiRJklQsk1qpD1hTq9JZz6WSWVOr0vk7WCWzplaSJEmSNK+Z1Ep9wJpa\nlc56LpXMmlqVzt/BKpk1tZIkSZKkec2kVuoD1tSqdNZzqWTW1Kp0/g5WyayplSRJkiTNaya1Uh+w\nplals55LJbOmVqXzd7BKZk2tJEmSJGleM6mV+oA1tSqd9VwqmTW1Kp2/g1Uya2olSZIkSfOaSa3U\nB6ypVems51LJrKlV6fwdrJIVW1MbEdsj4l8i4u6IuKte9pSIuCMixiLi9ogYbOl/eUTcFxH3RsSF\nvYhZkiRJktR/enWmNoEVmXlBZr6wXrYWuCMzh4FP1W0i4jxgFXAecBFwbUR4hlknFGtqVTrruVQy\na2pVOn8Hq2Sl19RGW/s1wPX16+uBlfXr1wI3Z+bjmbkduB94IZIkSZKkea+XZ2rvjIh/iohfrZed\nkZm769e7gTPq10PAzpZtdwKL5yZMaW5YU6vSWc+lkllTq9L5O1gl68b4PXnmYUzLv87Mr0XEvwLu\n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\nzPxk7yKWZoc1tSpd+yVEUkkcvyqdY1gl68b47WlSK0mSJEnSTJjUSn3A59SqdM2bOkglcvyqdI5h\nlawb49ekVpIkSZJULJNaqQ9YU6vSWc+lkjl+VTrHsEpmTa10gmg+p1Yq1aZNm3odgjRtjl+VzjGs\nknVj/JrUSn1g/OGHex2CNCPj4+NH7yT1KcevSucYVsm6MX5NaiVJkiRJxTKplfrA9h07eh2CNCPb\nt2/vdQjStDl+VTrHsErWjfEbmTnzSPpARJwYH0SSJEmS1FFmRvuyEyaplSRJkiTNP15+LEmSJEkq\nlkmtJEmSJKlYJrWSJEmSpGKZ1EqSJEmSimVSK0mSJEkqlkmtJEmSJKlYJrWSJEmSpGKZ1EqSJEmS\nimVSK0mSJEkqlkmtJEmSJKlYJrWSJEmSpGKZ1EqSJEmSimVSK0mSJEkqlkmtJEmSJKlYJrWSJEmS\npGKZ1EqSJEmSimVSK0mSJEkqlkmtJEmSJKlYJrWSJEmSpGKZ1EqSJEmSimVSK0mSJEkqlkmtJEmS\nJKlYJrWSJEmSpGKZ1EqSJEmSimVSK0nSCSoitkfEy3sdhyRJs8mkVpKkFlMlghGxIiJ21K+/FBH7\n6q/vRMSBlvb3Wl4/FhGPtrSvbd1Ph/f4UFv/fRFx9xFifVJE/LeI+Erd9/6IeHdEPLXukvXXTI7H\nlRHx4ZnsQ5Kk2WRSK0nSoY6aCGbmszPziZn5ROAzwK8125l5Usu6jwDXtKy77Bjeu7X/EzPzgk4d\nI+IU4FPADwM/Ub/fjwJ7gBcc1yeeRRHxhF7HIEk6sZnUSpI0czHNdTPxi8DTgZ/JzHsBMvPrmfkH\nmfmJw4KozgKva2kfcsY4In4nInZGxMMRcW9EvCwiLgIuB1a1njWOiNMi4rqIaNTbrIuIk+p1ayLi\n/0TEH0fEHuDts/T5JUkC4OReByBJ0glgRpf4tjnWJPgVwMczc/8x9p/yDHREnAv8GvD8zHwwIs4B\nTs7MbRFxFbA0M3+xZZMPAQ8CS4EB4DZgB7C+Xv9C4CbgacApxxifJEnT4plaSZL6RwBvjYhvtnx9\ncIq+TwG+No39d/JdYCHw7IhYkJlfzcxtLdtMbhcRZwA/CfxmZh7IzK8D/w34uZb9NTLzf2Tm9zLz\nkeOMUZKk4+KZWkmS+kcC/zUzf+8Y+u4Fhrryppn3R8RvAFdSJbafBH4rMzslzc8AFgBfi5jMdU8C\nvtrSp+ONsCRJmg2eqZUkqUx3Aj8REaceY/9vA619z2xdmZk3Z+ZLqZLWBK5prmrbzw7gUeCpmfnk\n+uu0zFzWurtj/RCSJM2USa0kSYc7JSK+r+XraHfwneqy3inrYyNiYet7tPQ/1praD1MlmH8dEedG\nxEkR8dSI+N2I+MkO/TcBPxURT46IM4HfaIlluL4x1EKqhPURqkuSoaqdXRL1adn67O3twB9HxBPr\n910aET92jHFLktRVJrWSJB3u74D9LV9v58iP+jnS8vZ1CSwGDrTs/9sRsbRe99ttz6l9qOOOMx+j\nulnUvcAdwLeAjVS1tp/rsMmHgS8A24FPAH/eEttC4A+Br1PV6Z5OdddjgL+sv++NiH+qX/8i1Q2g\n7gG+Ufdpnvmd8bNxJUk6HpHp/zuSJEmSpDJ5plaSJEmSVCyTWkmSJElSsUxqJUmSJEnFMqmVJEmS\nJBXr5F4H0C0R4R2vJEmSJOkElpmHPfruhElqAfrpTs6NsTGGBgZoTEwwNDzctf0BXdtntzTGxgD6\nLqZuHv9uaf053r15MxcsWwbAle96F1e+5S3T22effUbNT1deeSVXXnllr8OQpsXxq9JNZwy3zkkO\nWzcxwYMTE5w5MDBln9a+u3fvhv37J+c1jYkJgKNuO9X+hoaH+3Z+Cf0XUz/nCMcyHz+W8dtoNBga\nGqJ+ZPphvPxY6gPbd+zodQjSjGzfvr3XIUjT5vhV6RzDKlk3xq9JrSRJkiSpWCa1Uh9Y87rX9ToE\naUbWrFnT6xCkaXP8qnSOYZWsG+PXpFbqAyte8pJehyDNyIoVK3odgjRtjl+VzjGsknVj/JrUSn1g\nZHS01yFIMzIyMtLrEKRpc/yqdI5hlawb49ekVpIkSZJULJNaqQ94+bFK56VvKpnjV6VzDKtkXn4s\nSZIkSZrXTGqlPmBNrUpnPZdK5vhV6RzDKpk1tZIkSZKkea0nSW1EvDkiNkfEFyPizfWyp0TEHREx\nFhG3R8RgS//LI+K+iLg3Ii7sRczSbLKmVqWznkslc/yqdI5hlazImtqIeA7wK8ALgOcCr4qIpcBa\n4I7MHAY+VbeJiPOAVcB5wEXAtRHhGWZJkiRJUk/O1P4QsDEzH8nM7wJ/D/ws8Brg+rrP9cDK+vVr\ngZsz8/HM3A7cD7xwbkOWZpc1tSqd9VwqmeNXpXMMq2Sl1tR+EXhpfbnxqcBPAWcDZ2Tm7rrPbuCM\n+vUQsLNl+53A4rkKVpIkSZLUv06e6zfMzHsj4hrgduDbwCbgu219MiLySLuZxRClOWdNrUpnPZdK\n5vhV6RzDKlk3xu+cJ7UAmfkB4AMAEfEHVGdfd0fEmZn5YEScBTxUd98FPL1l87PrZYdZs2YNS5Ys\nAWBwcJDly5dPHqTmae25ao9u3MjpixYxfP75Xd1fM/mZ689zTPE1Gv0VTxePf7faw0NDVXt0lPu2\nbeOCZcsm23AwuT3udp98Ptu2bdu2bdt2Qe3R0ardNr9ozp8Om3926L/nwAGW1vPv9u2nM7/Zc+AA\nFw8PH3z/PptfApPx9TqekZER9uzYwcUvf/lkfP12vGY6H9+0aRPj4+Ps27ePvXv3MpXInPuTnhHx\ntMx8KCLOAT4JvBh4G7A3M6+JiLXAYGaurW8UdRNVHe1i4E7gmdkWeES0L+qpxtgYQwMDNCYmGKoH\nfjf2B3Rtn93SGBsD6LuYunn8u6X153j35s2HJLXTPVvbb59R89PIyMjkf0JSaRy/Kt10xnDrnOSw\ndRMTPDgxwZkDA1P2ae27e/du2L9/cl7TmJgAOOq2U+3v/7V3/zF2leeBx78PP+zadcMspRiugTpq\nOmlBsIa2hLbK1m0IQikBskGQqii4YmNUtm1YqQWzVdJuq0UBNdufQsI0TSelobWyDSq0aTFsJm06\nkptsGKA4ePgRC+xbBjA7xFO7xoRn/7j3ji9jezw/7sw5r+/3I41833Pfe+a55z4zfp8597mnMThY\n2/Ul1C+mOtcIs1mPzyZ/m80mjUaDiCAzY/r9lZypBb4QEd8LHARuzszXI+JTwJaIuBHYCVwLkJnb\nI2ILsB14sz2/PtWrJEmSJKkyVb39+D8dYdtrwKVHmX8HcMdixyVVxZ5alc6zXCqZ+avSmcMqWS/y\n94SFhyFJkiRJUjUsaqUa8Dq1Kl3nwx2kEpm/Kp05rJL1In8taiVJkiRJxbKolWrAnlqVzn4ulcz8\nVenMYZXMnlpJkiRJUl+zqJVqwJ5alc5+LpXM/FXpzGGVzJ5aSZIkSVJfs6iVasCeWpXOfi6VzPxV\n6cxhlcyeWkmSJElSX7OolWrAnlqVzn4ulcz8VenMYZXMnlpJkiRJUl+zqJVqwJ5alc5+LpXM/FXp\nzGGVzJ5aSZIkSVJfs6gtzNCWFWz54juqDkMLMLRlBUNbVvDg1gZDW1YA9tSqfPZzqWTmr0q3GDn8\n4IOnznrN+eCXTp9a13TWNtJs9SJ/T1p4GFpKB94I3ngjqg5DC3Cg/fq9cfCEqduSJEl1cvBg8MYJ\ns4cT4YkAACAASURBVFunvHHwBHBdowp5plaqAXtqVTr7uVQy81elM4dVMntqJUmSJEl9zaJWqgF7\nalU6exJVMvNXpTOHVTKvUytJkiRJ6msWtVIN2FOr0tnPpZKZvyqdOayS2VMrSZIkSeprFrVSDdhT\nq9LZz6WSmb8qnTmsktlTK0mSJEnqaxa1Ug3YU6vS2c+lkpm/Kp05rJLZUytJkiRJ6muVFLURcXtE\nPBURT0bE5yNieUScGhFbI2IsIh6OiIFp85+JiKcj4rIqYpYWkz21Kp39XCqZ+avSmcMqWZE9tRGx\nFvgYcFFmng+cCHwE2ARszcxB4NH2mIg4F7gOOBe4HLg7IjzDLEmSJEmq5Eztt4GDwMqIOAlYCTSB\nK4Gh9pwh4Or27auA+zPzYGbuBJ4FLl7SiKVFZk+tSmc/l0pm/qp05rBKVmRPbWa+BnwaeIFWMTuR\nmVuB1Zk53p42Dqxu324Au7p2sQtYs0ThSpIkSZJqrIq3H/8AcAuwllbBuioiru+ek5kJ5Ay7mek+\nqTj21Kp09nOpZOavSmcOq2S9yN+TFh7GnP0oMJKZewAi4q+AHwdeiogzMvOliDgTeLk9fzdwdtfj\nz2pvO8yGDRtYu3YtAAMDA6xbt27qdHbnYC3VeGTbNk5bsYLBCy7o6f7g0kqez6ziazbrFU8Pj3+v\nxoONBgA7nvsqL7/6Cues+RAAo0891Zrffhtyp8id9bgmz89x/45HR0drFY9jx+av434ad8z58SMj\nrfG09UVn/fTct/6J4ZG3ZlyPvLp/P3AJ0FrfAFzB4Iz7P9b+rhlsPb6O60tgKr6q4xkeHubVF1/k\nmve9byq+uh2v2azHO450/+joKBMTE+zdu5c9e/ZwNNE6Kbp0IuI/An8O/Bjw78CfAv8MfD+wJzPv\njIhNwEBmbmp/UNTnafXRrgEeAd6V0wKPiOmbKtUcG6OxahXNyUka7cTvxf4237eSiQMHuPUTq4/9\noCXSHBsD6Mnz7JVeH/9eaY6N8dADpwPwwu7dnLNmDRuv37ewfdbsOUqSpPrrrJWOeN/kJHd/bjnv\nWP5d3Hrjd2bez+Qkd98b8MYbnLOm1SF4xdWtc1NH2/+x9tcYHKzt+hLqF1PnONdtTdjL9Xiz2aTR\naBARZGZMv3/Jz9Rm5uMR8Tng68BbwDeAzcD3AFsi4kZgJ3Bte/72iNgCbAfeBG6uVfUqSZIkSarM\nCVV808y8KzPPy8zzM/OG9icbv5aZl2bmYGZelpkTXfPvyMx3ZeYPZebfVxGztJjsqVXppr+FSCqJ\n+avSmcMqWS/yt5KiVpIkSZKkXrColWrA69SqdJ0PdZBKZP6qdOawStaL/LWolSRJkiQVy6JWqgF7\nalU6+7lUMvNXpTOHVbJe5G8V16mVJEmq3NAQHDgAO3ZA+0odmsHy5XDDDVVHoaW0bFkytGUFN1y7\n/9hzT35rCSKSjsyiVqoBe2pVOvu5VKIDB2DjRoD1FUdShs2bq45AR7NYv4Ov/dC3eeiB02c194Pv\nb/K1x89elDh0fLOnVpIkSZLU1yxqpRqwp1als59LJTN/VTpzWCXzOrWSJEmSpL5mUSvVgD21Kp09\ntSqZ+avSmcMqmT21kiRJkqS+ZlEr1YA9tSqd/Vwqmfmr0pnDKpk9tZIkSZKkvmZRK9WAPbUqnf1c\nKpn5q9KZwyqZPbWSJEmSpL5mUSvVgD21Kp39XCqZ+avSmcMqmT21kiRJkqS+ZlEr1YA9tSqd/Vwq\nmfmr0pnDKpk9tZIkSZKkvmZRK9WAPbUqnf1cKpn5q9KZwyqZPbWSJEmSpL5mUSvVgD21Kp39XCqZ\n+avSmcMqmT21kiRJkqS+ZlEr1YA9tSqd/Vwqmfmr0pnDKpk9tZIkSZKkvrbkRW1EvDsiHuv6ej0i\nfiUiTo2IrRExFhEPR8RA12Nuj4hnIuLpiLhsqWOWFps9tSqd/Vwqmfmr0pnDKlmRPbWZuSMzL8zM\nC4EfAfYBXwQ2AVszcxB4tD0mIs4FrgPOBS4H7o4IzzBLkiRJkip/+/GlwLOZ+SJwJTDU3j4EXN2+\nfRVwf2YezMydwLPAxUsdqLSY7KlV6eznUsnMX5XOHFbJjoee2o8A97dvr87M8fbtcWB1+3YD2NX1\nmF3AmqUJT5IkSZJUZydV9Y0jYhnwQeC26fdlZkZEzvDwI963YcMG1q5dC8DAwADr1q2beo925y8A\nSzUe2baN01asYPCCC3q6v9bJ7aV/PrOKr9msVzw9PP69Gg82GgDseO6rvPzqK5yz5kN0DI+MTPXW\nds7cznpck+fnuL/HQ0Nw4ADs2NEav/vdrftLHi9fDt/85jAHD9YjnuNtXPXxXb788DMEdfl5cux4\n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\njgAv7N7NOWvWsPH6fQvb5+QkjfYv12Pl2ULzcK66v99Sf28tnbq9tr2MZ/Pm1r91en5V8/j2r7r9\nrGthuteWh903OclLk5OcsWoVjVWrANh838qjzr373uDDlz7P1x5/DwBXXN06N9V57Jziaq9rmmNj\nrX10/9W0YnWJafqat7O27NQddTG9HlrQvppNHnqowU03BZk5/bOZOGFBe5+f1cA/RsQosA14KDMf\nBj4FvD8ixoCfaY/JzO3AFmA78CXg5lpVr1IP2FOr0h3667FUHvNXpTOHVbJe5O+Sv/04M78FrDvC\n9tdona090mPuAO5Y5NAkSZIkSYWp4kytpGm8Tq1K1+l/kUpk/qp05rBK1ov8taiVJEmSJBXLolaq\nAXtqVTr7uVQy81elM4dVsl7kr0WtJEmSJKlYFrVSDdhTq9LZz6WSmb8qnTmsktlTK0mSJEnqaxa1\nUg3YU6vS2c+lkpm/Kp05rJLZUytJkiRJ6msWtVIN2FOr0tnPpZKZvyqdOayS2VMrSZIkSeprFrVS\nDdhTq9LZz6WSmb8qnTmsktlTK0mSJEnqaxa1Ug3YU6vS2c+lkpm/Kp05rJL1In9PWngY9bF5c9UR\nHDIxfgqrvyenxsuXLyy+7v0tW5aVPtfly+e2fbF1ju2Rvn/Vx2q6t72OJ7/F8mXJ5vtWLmyfB05k\nYHXr9rFeg4Xm4Vx1x7PU31tLp6qf/aVwPD+3OvD4lsXf48eX6WvVYznammXiwIksO3nibfPu+8tT\nABiYxw95Z10zMd7ex+o572LR1CWm6Yd1+bLZv45LrZMPCz1mExMrWT3DPiKzvgdhLiIi6/RcmmNj\nNFatojk5SWNwsGf7A3q2z15pjo0B1C6mXh7/Xul+HR978kkuPP98oNVTO9+ztXV7jupPw8PDnilQ\nscxflW4+Ody9JjnsvslJXpqc5IxVq446p3vu+Pg47Ns3ta5pTk4CHPOxR9tfY3CwtutLqF9Mda4R\nZrMen03+NptNGo0GEUFmxvT7ffuxJEmSJKlYFrVSDdhTq9J5lkslM39VOnNYJfM6tZIkSZKkvmZR\nK9WA16lV6bxGokpm/qp05rBK5nVqJUmSJEl9zaJWqgF7alU6+7lUMvNXpTOHVTJ7aiVJkiRJfc2i\nVqoBe2pVOvu5VDLzV6Uzh1Uye2olSZIkSX3NolaqAXtqVTr7uVQy81elM4dVsqJ7aiPixIh4LCIe\n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\nU7ZmwAAAAABJRU5ErkJggg==\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7fa97d0ae610>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"trace.analysis.frequency.plotClusterFrequencies()"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Take-away"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"In a single plot we can aggregate multiple informations which makes it easy to verify the expected behaviros.\n",
"\n",
"With a set of properly defined plots we are able to condense mucy more sensible information which are easy to ready because they are \"standard\".<br>\n",
"We immediately capture what we are interested to evaluate!\n",
"\n",
"Moreover, all he produced plots are available as high resolution images, ready to be shared and/or used in other reports."
]
},
{
"cell_type": "code",
"execution_count": 132,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\u001b[01;34m../../results/SchedTuneAnalysis/\u001b[00m\r\n",
"├── \u001b[01;35mboost15_cluster_freqs.png\u001b[00m\r\n",
"├── \u001b[01;35mboost15_task_util_task_ramp.png\u001b[00m\r\n",
"├── energy.json\r\n",
"├── output.log\r\n",
"├── platform.json\r\n",
"├── rt-app-task_ramp-0.log\r\n",
"├── test_00.json\r\n",
"├── trace_boost15.dat\r\n",
"├── trace_boost15.raw.txt\r\n",
"├── trace_boost15.txt\r\n",
"├── trace_boost25.dat\r\n",
"├── trace_boost25.raw.txt\r\n",
"├── trace_boost25.txt\r\n",
"├── trace.dat\r\n",
"├── trace_noboost.dat\r\n",
"├── trace_noboost.raw.txt\r\n",
"├── trace_noboost.txt\r\n",
"├── trace.raw.txt\r\n",
"└── trace.txt\r\n",
"\r\n",
"0 directories, 19 files\r\n"
]
}
],
"source": [
"!tree {res_dir}"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Behavioral Analysis"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Is the task starting on a big core?"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"We always expect a new task to be allocated on a big core.\n",
"\n",
"To verify this condition we need to know what is the topology of the target.\n",
"\n",
"This information is **automatically collected by LISA** when the workload is executed.<br>\n",
"Thus it can be used to write **portable tests** conditions."
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Create a SchedAssert for the specific topology"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [],
"source": [
"from bart.sched.SchedMultiAssert import SchedAssert\n",
"\n",
"# Create an object to get/assert scheduling pbehaviors\n",
"sa = SchedAssert(trace_file, topology, execname='task_ramp')"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Use the SchedAssert method to investigate properties of this task"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"PASS: Task starts on big CPU: 1\n"
]
}
],
"source": [
"# Check on which CPU the task start its execution\n",
"if sa.assertFirstCpu(platform['clusters']['big']):#, window=(4,6)):\n",
" print \"PASS: Task starts on big CPU: \", sa.getFirstCpu()\n",
"else:\n",
" print \"FAIL: Task does NOT start on a big CPU!!!\""
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Is the task generating the expected load?"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"We expect 35% load in the between 2 and 4 [s] of the execution"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Identify the start of the first phase"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The task starts execution at [s]: 1.9683\n",
"Window of interest: (1.9682999999999993, 3.9682999999999993)\n"
]
}
],
"source": [
"# Let's find when the task starts\n",
"start = sa.getStartTime()\n",
"first_phase = (start, start+2)\n",
"\n",
"print \"The task starts execution at [s]: \", start\n",
"print \"Window of interest: \", first_phase"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Use the SchedAssert module to check the task load in that period"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"FAIL: Task duty-cycle is 18.11125% in the [2,4] execution window\n"
]
}
],
"source": [
"import operator\n",
"\n",
"# Check the task duty cycle in the second step window\n",
"if sa.assertDutyCycle(10, operator.lt, window=first_phase):\n",
" print \"PASS: Task duty-cycle is {}% in the [2,4] execution window\"\\\n",
" .format(sa.getDutyCycle(first_phase))\n",
"else:\n",
" print \"FAIL: Task duty-cycle is {}% in the [2,4] execution window\"\\\n",
" .format(sa.getDutyCycle(first_phase))"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"This test fails because we have not considered a scaling factor due running at a lower OPP.\n",
"\n",
"To write a portable test we need to account for that condition!"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Take OPP scaling into consideration"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"LITTLEs capacities range: (236, 447)\n",
"LITTLE's min capacity scale: 0.527964205817\n"
]
}
],
"source": [
"# Get LITTLEs capacities ranges:\n",
"littles = platform['clusters']['little']\n",
"little_capacities = cap_df[cap_df.cpu.isin(littles)].capacity\n",
"min_cap = little_capacities.min()\n",
"max_cap = little_capacities.max()\n",
"print \"LITTLEs capacities range: \", (min_cap, max_cap)\n",
"\n",
"# Get min OPP correction factor\n",
"min_little_scale = 1.0 * min_cap / max_cap\n",
"print \"LITTLE's min capacity scale: \", min_little_scale"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Scaled target duty-cycle: 18.9406779661\n",
"1% tolerance scaled duty-cycle: 19.1300847458\n"
]
}
],
"source": [
"# Scale the target duty-cycle according to the min OPP\n",
"target_dutycycle = 10 / min_little_scale\n",
"print \"Scaled target duty-cycle: \", target_dutycycle\n",
"\n",
"\n",
"target_dutycycle = 1.01 * target_dutycycle\n",
"\n",
"print \"1% tolerance scaled duty-cycle: \", target_dutycycle"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Write a more portable assertion"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"PASS: Task duty-cycle is 9.56209172258% in the [2,4] execution window\n"
]
}
],
"source": [
"# Add a 1% tolerance to our scaled target dutycycle\n",
"if sa.assertDutyCycle(1.01 * target_dutycycle, operator.lt, window=first_phase):\n",
" print \"PASS: Task duty-cycle is {}% in the [2,4] execution window\"\\\n",
" .format(sa.getDutyCycle(first_phase) * min_little_scale)\n",
"else:\n",
" print \"FAIL: Task duty-cycle is {}% in the [2,4] execution window\"\\\n",
" .format(sa.getDutyCycle(first_phase) * min_little_scale)"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Is the task migrated once we exceed the LITTLE CPUs capacity?"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Check that the task is switching the cluster once expected"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"PASS: Task switches to big within: (5.8682999999999996, 6.0682999999999989)\n"
]
}
],
"source": [
"# Consider a 100 [ms] window for the task to migrate\n",
"delta = 0.1\n",
"\n",
"# Defined the window of interest\n",
"switch_window=(start+4-delta, start+4+delta)\n",
"\n",
"if sa.assertSwitch(\"cluster\",\n",
" platform['clusters']['little'],\n",
" platform['clusters']['big'],\n",
" window=switch_window):\n",
" print \"PASS: Task switches to big within: \", switch_window\n",
"else:\n",
" print \"PASS: Task DOES NO switches to big within: \", switch_window"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Check that the task is running most of its time on the LITTLE cluster"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"PASS: Task exectuion on LITTLEs is 53.1% (less than 66% of its execution time)\n"
]
}
],
"source": [
"import operator\n",
"\n",
"if sa.assertResidency(\"cluster\", platform['clusters']['little'], 66, operator.le, percent=True):\n",
" print \"PASS: Task exectuion on LITTLEs is {:.1f}% (less than 66% of its execution time)\".\\\n",
" format(sa.getResidency(\"cluster\", platform['clusters']['little'], percent=True))\n",
"else:\n",
" print \"FAIL: Task run on LITTLE for MORE than 66% of its execution time\""
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true,
"hidden": true
},
"source": [
"### Check that the util estimation is properly computed and CPU capacity matches"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [],
"source": [
"start = 2\n",
"last_phase = (start+4, start+6)\n",
"\n",
"analyzer_config = {\n",
" \"SCALE\" : 1024,\n",
" \"BOOST\" : 15,\n",
"}\n",
"\n",
"# Verify that the margin is properly computed for each event:\n",
"# margin := (scale - util) * boost\n",
"margin_check_statement = \"(((SCALE - sched_boost_task:util) * BOOST) // 100) == sched_boost_task:margin\""
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [],
"source": [
"from bart.common.Analyzer import Analyzer\n",
"\n",
"# Create an Assertion Object\n",
"a = Analyzer(trace.ftrace,\n",
" analyzer_config,\n",
" window=last_phase,\n",
" filters={\"comm\": \"task_ramp\"})"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"PASS: Margin properly computed in : (6, 8)\n"
]
}
],
"source": [
"if a.assertStatement(margin_check_statement):\n",
" print \"PASS: Margin properly computed in : \", last_phase\n",
"else:\n",
" print \"FAIL: Margin NOT properly computed in : \", last_phase"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Check that the CPU capacity matches the task boosted value"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [],
"source": [
"# Get the two dataset of interest\n",
"df1 = trace.data_frame.trace_event('cpu_capacity')[['cpu', 'capacity']]\n",
"df2 = trace.data_frame.trace_event('boost_task_rtapp')[['__cpu', 'boosted_util']]\n",
"\n",
"# Join the information from these two\n",
"df3 = df2.join(df1, how='outer')\n",
"df3 = df3.fillna(method='ffill')\n",
"df3 = df3[df3.__cpu == df3.cpu]\n",
"#df3.ix[start+4:start+6,].head()"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"text/plain": [
"19"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(df3[df3.boosted_util >= df3.capacity])"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"##### Do it the TRAPpy way"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Create the TRAPpy class\n",
"trace.ftrace.add_parsed_event('rtapp_capacity_check', df3)\n",
"# Define pivoting value\n",
"trace.ftrace.rtapp_capacity_check.pivot = 'cpu'\n",
"\n",
"# Create an Assertion\n",
"a = Analyzer(trace.ftrace,\n",
" {\"CAP\" : trace.ftrace.rtapp_capacity_check},\n",
" window=(start+4.1, start+6))\n",
"a.assertStatement(\"CAP:capacity >= CAP:boosted_util\")"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Going further on events processing"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### What are the relative residency on different OPPs?"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"We are not limited to the usage of pre-defined functions. We can exploit the full power of PANDAS to process the DataFrames to extract all kind of information we want."
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Use PANDAs APIs to filter and aggregate events"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Residency time per OPP:\n",
"Freq 450000Hz : 59.3%\n",
"Freq 575000Hz : 11.7%\n",
"Freq 700000Hz : 19.5%\n",
"Freq 775000Hz : 8.8%\n",
"Freq 850000Hz : 0.6%\n"
]
}
],
"source": [
"import pandas as pd\n",
"\n",
"# Focus on cpu_frequency events for CPU0\n",
"df = trace.data_frame.trace_event('cpu_frequency')\n",
"df = df[df.cpu == 0]\n",
"\n",
"# Compute the residency on each OPP before switching to the next one\n",
"df.loc[:,'start'] = df.index\n",
"df.loc[:,'delta'] = (df['start'] - df['start'].shift()).fillna(0).shift(-1)\n",
"\n",
"# Group by frequency and sum-up the deltas\n",
"freq_residencies = df.groupby('frequency')['delta'].sum()\n",
"print \"Residency time per OPP:\"\n",
"df = pd.DataFrame(freq_residencies)\n",
"\n",
"df.head()\n",
"\n",
"# Compute the relative residency time\n",
"tot = sum(freq_residencies)\n",
"#df = df.apply(lambda delta : 100*delta/tot)\n",
"for f in freq_residencies.index:\n",
" print \"Freq {:10d}Hz : {:5.1f}%\".format(f, 100*freq_residencies[f]/tot)"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"#### Use MathPlot Lib to generate all kind of plot from collected data"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"data": {
"image/png": "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\nE5/4BBdddBFrr70222+/PQDnnXce22yzDRMnTuSFL3whX/7yl4e99r4LwXRqngBUVT0MnAX8Dnhl\nkp0H/3oN8pAkSZIkLc28efM44IADePvb387MmTM55JBDuOSSS0jC9ddfzxFHHMG5557Lww8/zNFH\nH81+++3H/Pnz/+wce+21F6eddhpTpkzhscce4/rrrwdgo4024sorr2TWrFmcd955nHDCCU9/Nlz6\nLgRX1YPAd4DDkmxeVY8AFwILgP16WpwkSZIkjXFXX301CxYs4Pjjj2eVVVbhoIMO4uUvfzlVxbnn\nnsvRRx/Ny1/+cpJw+OGH85znPIerr776WeepqmcNod57773ZaqutANhtt93YY489+PGPfzys9fdF\nCE6yZ5IPJDk2yUTgouajNyXZoqpmAp8GdkqyUe8qlSRJkqSx7b777mPTTTf9s/e22GILAO68807+\n8R//kUmTJj39uOeee7jvvvuGdO5p06bxqle9ivXXX59Jkybxb//2bzz00EPDWv+oD8FJXgN8gU6n\nd1vgamAhcDmwIXBSkh2A19JZ6OuJHpUqSZIkSWPeJptswr333vtn7915550AbLbZZnzoQx9i5syZ\nTz9mz57Nm970pmedZ/H1mJ588kkOOuggPvCBD/DHP/6RmTNnsvfeew/7glujPgQDLwcuraqzqurd\nwKXAt4Df05kPvOjnUcCxVTWrZ5VKkiRJ0hi30047MX78eD772c8yf/58Lr30Uq699lqScNRRR/Gl\nL32Ja665hqpizpw5XHnllcyePftZ59l444254447ng658+bNY968eTz3uc9l3LhxTJs2jR/84AfD\nXn8/hOBfAasnWRegqk4H/gP4d2BOVZ0F7A8cUFXX9a5MSZIkSRr7Vl11VS699FLOP/981l9/fS6+\n+GIOOuggAHbYYQfOPfdcjj32WNZbbz1e9KIXccEFFyxxF55DDjkEgPXXX58dd9yRtddem89+9rMc\neuihrLfeenzrW99i//33H/b6Mxr3ckqyOfBYVc1MsiGdha++W1VfGnDMucB/VtU3luO8NfgK0Omb\n/a0kSZIkjU3Js3PJSGzn2i9ZaEn/fAa8v8x/UOO7VtUKSnIgcAowK8k1wBXA0cBlzf/o321WiH4U\nWLdnhUqSJEnSCOqXgDrajapOcJINgOnAkcAcYEfgYOBTwN3AOc3P8cAuwIFVdfNynN9OsCRJkqRR\n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\nTkSuQmCC\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x7f8b58536910>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Plot residency time\n",
"import matplotlib.pyplot as plt\n",
"\n",
"fig, axes = plt.subplots(1, 1, figsize=(16, 5));\n",
"df.plot(kind='barh', ax=axes, title=\"Frequency residency\", rot=45);"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"<br><br><br><br>\n",
"Advanced DataFrame usage: filtering by columns/rows, merging tables, plotting data<br>\n",
"[notebooks/tutorial/05_TrappyUsage.ipynb](05_TrappyUsage.ipynb)\n",
"<br><br><br><br>"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Remote target connection and control"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"Using LISA APIs to control a remote device and run custom workloads"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Configure the connection"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"# Setup a target configuration\n",
"conf = {\n",
" \n",
" # Target is localhost\n",
" \"platform\" : 'linux',\n",
" \"board\" : \"juno\",\n",
" \n",
" # Login credentials\n",
" \"host\" : \"192.168.0.1\",\n",
" \"username\" : \"root\",\n",
" \"password\" : \"\",\n",
"\n",
" # Binary tools required to run this experiment\n",
" # These tools must be present in the tools/ folder for the architecture\n",
" \"tools\" : ['rt-app', 'taskset', 'trace-cmd'],\n",
" \n",
" # Comment the following line to force rt-app calibration on your target\n",
" \"rtapp-calib\" : {\n",
" \"0\": 355, \"1\": 138, \"2\": 138, \"3\": 355, \"4\": 354, \"5\": 354\n",
" },\n",
" \n",
" # FTrace events end buffer configuration\n",
" \"ftrace\" : {\n",
" \"events\" : [\n",
" \"sched_switch\",\n",
" \"sched_wakeup\",\n",
" \"sched_wakeup_new\",\n",
" \"sched_overutilized\",\n",
" \"sched_contrib_scale_f\",\n",
" \"sched_load_avg_cpu\",\n",
" \"sched_load_avg_task\",\n",
" \"sched_tune_config\",\n",
" \"sched_tune_tasks_update\",\n",
" \"sched_tune_boostgroup_update\",\n",
" \"sched_tune_filter\",\n",
" \"sched_boost_cpu\",\n",
" \"sched_boost_task\",\n",
" \"sched_energy_diff\",\n",
" \"cpu_frequency\",\n",
" \"cpu_capacity\",\n",
" ],\n",
" \"buffsize\" : 10240\n",
" },\n",
"\n",
" # Where results are collected\n",
" \"results_dir\" : \"SchedTuneAnalysis\",\n",
"\n",
" # Devlib module required (or not required)\n",
" 'modules' : [ \"cpufreq\", \"cgroups\" ],\n",
" #\"exclude_modules\" : [ \"hwmon\" ],\n",
"}"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Setup the connection"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"# Support to access the remote target\n",
"from env import TestEnv\n",
"\n",
"# Initialize a test environment using:\n",
"# the provided target configuration (my_target_conf)\n",
"# the provided test configuration (my_test_conf)\n",
"te = TestEnv(conf)\n",
"target = te.target\n",
"\n",
"print \"DONE\""
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Target control"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Run custom commands"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"# Enable Energy-Aware scheduler\n",
"target.execute(\"echo ENERGY_AWARE > /sys/kernel/debug/sched_features\");\n",
"target.execute(\"echo UTIL_EST > /sys/kernel/debug/sched_features\");\n",
"\n",
"# Check which sched_feature are enabled\n",
"sched_features = target.read_value(\"/sys/kernel/debug/sched_features\");\n",
"print \"sched_features:\"\n",
"print sched_features"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Example CPUFreq configuration"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"target.cpufreq.set_all_governors('sched');\n",
"\n",
"# Check which governor is enabled on each CPU\n",
"enabled_governors = target.cpufreq.get_all_governors()\n",
"print enabled_governors"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"### Example of CGruops configuration"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"schedtune = target.cgroups.controller('schedtune')\n",
"\n",
"# Configure a 50% boostgroup\n",
"boostgroup = schedtune.cgroup('/boosted')\n",
"boostgroup.set(boost=25)\n",
"\n",
"# Dump the configuraiton of each groups\n",
"cgroups = schedtune.list_all()\n",
"for cgname in cgroups:\n",
" cgroup = schedtune.cgroup(cgname)\n",
" attrs = cgroup.get()\n",
" boost = attrs['boost']\n",
" print '{}:{:<15} boost: {}'.format(schedtune.kind, cgroup.name, boost)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Remote workloads execution"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Generate RTApp configurations"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"# RTApp configurator for generation of PERIODIC tasks\n",
"from wlgen import RTA, Periodic, Ramp\n",
"\n",
"# Create a new RTApp workload generator using the calibration values\n",
"# reported by the TestEnv module\n",
"rtapp = RTA(target, 'test', calibration=te.calibration())\n",
"\n",
"# Ramp workload\n",
"ramp = Ramp(\n",
" start_pct=10,\n",
" end_pct=60,\n",
" delta_pct=25,\n",
" time_s=2,\n",
" period_ms=32\n",
")\n",
"\n",
"# Configure this RTApp instance to:\n",
"rtapp.conf(\n",
"\n",
" # 1. generate a \"profile based\" set of tasks\n",
" kind = 'profile',\n",
" \n",
" # 2. define the \"profile\" of each task\n",
" params = {\n",
" \n",
" # 3. Composed task\n",
" 'task_ramp': ramp.get(),\n",
" },\n",
" \n",
" #loadref='big',\n",
" loadref='LITTLE',\n",
" run_dir=target.working_directory\n",
" \n",
");"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Execution and tracing"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"def execute(te, wload, res_dir, cg='/'):\n",
" \n",
" logging.info('# Setup FTrace')\n",
" te.ftrace.start()\n",
"\n",
" if te.emeter:\n",
" logging.info('## Start energy sampling')\n",
" te.emeter.reset()\n",
"\n",
" logging.info('### Start RTApp execution')\n",
" wload.run(out_dir=res_dir, cgroup=cg)\n",
"\n",
" if te.emeter:\n",
" logging.info('## Read energy consumption: %s/energy.json', res_dir)\n",
" nrg_report = te.emeter.report(out_dir=res_dir)\n",
" else:\n",
" nrg_report = None\n",
"\n",
" logging.info('# Stop FTrace')\n",
" te.ftrace.stop()\n",
"\n",
" trace_file = os.path.join(res_dir, 'trace.dat')\n",
" logging.info('# Save FTrace: %s', trace_file)\n",
" te.ftrace.get_trace(trace_file)\n",
"\n",
" logging.info('# Save platform description: %s/platform.json', res_dir)\n",
" plt, plt_file = te.platform_dump(res_dir)\n",
" \n",
" logging.info('# Report collected data:')\n",
" logging.info(' %s', res_dir)\n",
" !tree {res_dir}\n",
" \n",
" return nrg_report, plt, plt_file, trace_file"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true,
"hidden": true
},
"outputs": [],
"source": [
"nrg_report, plt, plt_file, trace_file = execute(te, rtapp, te.res_dir, cg=boostgroup.name)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Regression testing support"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"Writing and running regression tests using the LISA API"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Defined configurations to test and workloads"
]
},
{
"cell_type": "code",
"execution_count": 116,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\r\n",
" /* Devlib modules to enable/disbale for all the experiments */\r\n",
" \"modules\" : [ \"cpufreq\", \"cgroups\" ],\r\n",
" \"exclude_modules\" : [ ],\r\n",
"\r\n",
" /* Binary tools required by the experiments */\r\n",
" \"tools\" : [ \"rt-app\" ],\r\n",
"\r\n",
" /* FTrace configuration */\r\n",
" \"ftrace\" : {\r\n",
" \"events\" : [\r\n",
" \"sched_switch\",\r\n",
" \"sched_contrib_scale_f\",\r\n",
" \"sched_load_avg_cpu\",\r\n",
" \"sched_load_avg_task\",\r\n",
" \"sched_tune_config\",\r\n",
" \"sched_tune_tasks_update\",\r\n",
" \"sched_tune_boostgroup_update\",\r\n",
" \"sched_tune_filter\",\r\n",
" \"sched_boost_cpu\",\r\n",
" \"sched_boost_task\",\r\n",
" \"sched_energy_diff\",\r\n",
" \"cpu_frequency\",\r\n",
" \"cpu_capacity\",\r\n",
" ],\r\n",
" \"buffsize\" : 10240,\r\n",
" },\r\n",
"\r\n",
" /* Set of platform configurations to test */\r\n",
" \"confs\" : [\r\n",
" {\r\n",
" \"tag\" : \"noboost\",\r\n",
" \"flags\" : \"ftrace\",\r\n",
" \"sched_features\" : \"ENERGY_AWARE\",\r\n",
" \"cpufreq\" : { \"governor\" : \"sched\" },\r\n",
" \"cgroups\" : {\r\n",
" \"conf\" : {\r\n",
" \"schedtune\" : {\r\n",
" \"/\" : {\"boost\" : 0 },\r\n",
" \"/stune\" : {\"boost\" : 0 },\r\n",
" }\r\n",
" },\r\n",
" \"default\" : \"/\",\r\n",
" }\r\n",
" },\r\n",
" {\r\n",
" \"tag\" : \"boost15\",\r\n",
" \"flags\" : \"ftrace\",\r\n",
" \"sched_features\" : \"ENERGY_AWARE\",\r\n",
" \"cpufreq\" : { \"governor\" : \"sched\" },\r\n",
"\t \"cgroups\" : {\r\n",
" \"conf\" : {\r\n",
" \"schedtune\" : {\r\n",
" \"/\" : {\"boost\" : 0 },\r\n",
" \"/stune\" : {\"boost\" : 15 },\r\n",
" }\r\n",
" },\r\n",
" \"default\" : \"/stune\",\r\n",
" }\r\n",
" },\r\n",
" {\r\n",
" \"tag\" : \"boost30\",\r\n",
" \"flags\" : \"ftrace\",\r\n",
" \"sched_features\" : \"ENERGY_AWARE\",\r\n",
" \"cpufreq\" : { \"governor\" : \"sched\" },\r\n",
"\t \"cgroups\" : {\r\n",
" \"conf\" : {\r\n",
" \"schedtune\" : {\r\n",
" \"/\" : {\"boost\" : 0 },\r\n",
" \"/stune\" : {\"boost\" : 30 },\r\n",
" }\r\n",
" },\r\n",
" \"default\" : \"/stune\",\r\n",
" }\r\n",
" },\r\n",
" {\r\n",
" \"tag\" : \"boost60\",\r\n",
" \"flags\" : \"ftrace\",\r\n",
" \"sched_features\" : \"ENERGY_AWARE\",\r\n",
" \"cpufreq\" : { \"governor\" : \"sched\" },\r\n",
"\t \"cgroups\" : {\r\n",
" \"conf\" : {\r\n",
" \"schedtune\" : {\r\n",
" \"/\" : {\"boost\" : 0 },\r\n",
" \"/stune\" : {\"boost\" : 60 },\r\n",
" }\r\n",
" },\r\n",
" \"default\" : \"/stune\",\r\n",
" }\r\n",
" }\r\n",
"\r\n",
" ],\r\n",
"\r\n",
" /* Set of workloads to run on each platform configuration */\r\n",
" \"wloads\" : {\r\n",
" \"mixprof\" : {\r\n",
" \"type\": \"rt-app\",\r\n",
" \"conf\" : {\r\n",
" \"class\" : \"profile\",\r\n",
" \"params\" : {\r\n",
" \"r5_10-60\" : {\r\n",
" \"kind\" : \"Ramp\",\r\n",
" \"params\" : {\r\n",
" \"period_ms\" : 16,\r\n",
" \"start_pct\" : 5,\r\n",
" \"end_pct\" : 60,\r\n",
" \"delta_pct\" : 5,\r\n",
" \"time_s\" : 1,\r\n",
" }\r\n",
" }\r\n",
" }\r\n",
" },\r\n",
" \"loadref\" : \"LITTLE\",\r\n",
" }\r\n",
" },\r\n",
"\r\n",
" /* Number of iterations for each workload */\r\n",
" \"iterations\" : 1,\r\n",
"\r\n",
"}\r\n",
"\r\n",
"// vim :set tabstop=4 shiftwidth=4 expandtab\r\n"
]
}
],
"source": [
"stune_smoke_test = '../../tests/stune/smoke_test_ramp.config'\n",
"!cat {stune_smoke_test}"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Write Test Cases"
]
},
{
"cell_type": "code",
"execution_count": 120,
"metadata": {
"collapsed": false,
"hidden": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"# SPDX-License-Identifier: Apache-2.0\r\n",
"#\r\n",
"# Copyright (C) 2015, ARM Limited and contributors.\r\n",
"#\r\n",
"# Licensed under the Apache License, Version 2.0 (the \"License\"); you may\r\n",
"# not use this file except in compliance with the License.\r\n",
"# You may obtain a copy of the License at\r\n",
"#\r\n",
"# http://www.apache.org/licenses/LICENSE-2.0\r\n",
"#\r\n",
"# Unless required by applicable law or agreed to in writing, software\r\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT\r\n",
"# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n",
"# See the License for the specific language governing permissions and\r\n",
"# limitations under the License.\r\n",
"#\r\n",
"\r\n",
"import logging\r\n",
"import os\r\n",
"\r\n",
"from test import LisaTest\r\n",
"\r\n",
"import trappy\r\n",
"from bart.common.Analyzer import Analyzer\r\n",
"\r\n",
"TESTS_DIRECTORY = os.path.dirname(os.path.realpath(__file__))\r\n",
"TESTS_CONF = os.path.join(TESTS_DIRECTORY, \"smoke_test_ramp.config\")\r\n",
"\r\n",
"class STune(LisaTest):\r\n",
" \"\"\"Tests for SchedTune framework\"\"\"\r\n",
"\r\n",
" @classmethod\r\n",
" def setUpClass(cls, *args, **kwargs):\r\n",
" super(STune, cls)._init(TESTS_CONF, *args, **kwargs)\r\n",
"\r\n",
" def test_boosted_utilization_signal(self):\r\n",
" \"\"\"The boosted utilization signal is appropriately boosted\r\n",
"\r\n",
" The margin should match the formula\r\n",
" (sched_load_scale - util) * boost\"\"\"\r\n",
"\r\n",
" for tc in self.conf[\"confs\"]:\r\n",
" test_id = tc[\"tag\"]\r\n",
"\r\n",
" wload_idx = self.conf[\"wloads\"].keys()[0]\r\n",
" run_dir = os.path.join(self.te.res_dir,\r\n",
" \"rtapp:{}:{}\".format(test_id, wload_idx),\r\n",
" \"1\")\r\n",
"\r\n",
" ftrace_events = [\"sched_boost_task\"]\r\n",
" ftrace = trappy.FTrace(run_dir, scope=\"custom\",\r\n",
" events=ftrace_events)\r\n",
"\r\n",
" first_task_params = self.conf[\"wloads\"][wload_idx][\"conf\"][\"params\"]\r\n",
" first_task_name = first_task_params.keys()[0]\r\n",
" rta_task_name = \"task_{}\".format(first_task_name)\r\n",
"\r\n",
" sbt_dfr = ftrace.sched_boost_task.data_frame\r\n",
" boost_task_rtapp = sbt_dfr[sbt_dfr.comm == rta_task_name]\r\n",
" ftrace.add_parsed_event(\"boost_task_rtapp\", boost_task_rtapp)\r\n",
"\r\n",
" # Avoid the first period as the task starts with a very\r\n",
" # high load and it overutilizes the CPU\r\n",
" rtapp_period = first_task_params[first_task_name][\"params\"][\"period_ms\"]\r\n",
" task_start = boost_task_rtapp.index[0]\r\n",
" after_first_period = task_start + (rtapp_period / 1000.)\r\n",
"\r\n",
" boost = tc[\"cgroups\"][\"conf\"][\"schedtune\"][\"/stune\"][\"boost\"] / 100.\r\n",
" analyzer_const = {\r\n",
" \"SCHED_LOAD_SCALE\": 1024,\r\n",
" \"BOOST\": boost,\r\n",
" }\r\n",
" analyzer = Analyzer(ftrace, analyzer_const,\r\n",
" window=(after_first_period, None))\r\n",
" statement = \"(((SCHED_LOAD_SCALE - boost_task_rtapp:util) * BOOST) // 100) == boost_task_rtapp:margin\"\r\n",
" error_msg = \"task was not boosted to the expected margin: {}\".\\\r\n",
" format(boost)\r\n",
" self.assertTrue(analyzer.assertStatement(statement), msg=error_msg)\r\n",
"\r\n",
"# vim :set tabstop=4 shiftwidth=4 expandtab\r\n"
]
}
],
"source": [
"stune_smoke_test = '../../tests/stune/smoke_test_ramp.py'\n",
"!cat {stune_smoke_test}"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Tests execution"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"The execution of a test can be triggered from a LISA shell using nosetest with the test class as a parameter. This command:\n",
"\n",
"```bash\n",
"$ nosetests -v tests/stune/smoke_test_ramp.py\n",
"```\n",
"\n",
"will execute all the tests described in the **smoke_test_ramp.py** module and collect all the products in a timestamp named subfolder of the results folder.\n",
"Tests PASS/FAILURE is reported after the completion of each test execution."
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"## Results reporting"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Detailed results of the experiments which compares also some base configurations with each test configuration can be reported in a tablular format using this command:\n",
"\n",
"```bash\n",
"$ lisa-report --base noboost --tests '(boost15|boost30|boost60)'\n",
"```\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"hidden": true
},
"source": [
"<img src=\"SchedTune_SmokeTestResults.png\"/>"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.9"
},
"toc": {
"toc_cell": false,
"toc_number_sections": true,
"toc_threshold": 6,
"toc_window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 0
}