1 { 2 "cells": [ 3 { 4 "cell_type": "markdown", 5 "metadata": {}, 6 "source": [ 7 "<font size=\"9\">Kernel Functions Profiling</font><br>\n", 8 "<hr>" 9 ] 10 }, 11 { 12 "cell_type": "code", 13 "execution_count": 1, 14 "metadata": { 15 "collapsed": true 16 }, 17 "outputs": [], 18 "source": [ 19 "%load_ext autoreload\n", 20 "%autoreload 2" 21 ] 22 }, 23 { 24 "cell_type": "code", 25 "execution_count": 2, 26 "metadata": { 27 "collapsed": true 28 }, 29 "outputs": [], 30 "source": [ 31 "import logging\n", 32 "from conf import LisaLogging\n", 33 "LisaLogging.setup()" 34 ] 35 }, 36 { 37 "cell_type": "code", 38 "execution_count": 3, 39 "metadata": { 40 "collapsed": false 41 }, 42 "outputs": [ 43 { 44 "name": "stdout", 45 "output_type": "stream", 46 "text": [ 47 "Populating the interactive namespace from numpy and matplotlib\n" 48 ] 49 } 50 ], 51 "source": [ 52 "# Generate plots inline\n", 53 "%pylab inline\n", 54 "\n", 55 "import json\n", 56 "import os\n", 57 "\n", 58 "import re\n", 59 "import collections\n", 60 "import pandas\n", 61 "\n", 62 "# Support to tests execution\n", 63 "from executor import Executor\n", 64 "from env import TestEnv" 65 ] 66 }, 67 { 68 "cell_type": "markdown", 69 "metadata": {}, 70 "source": [ 71 "# Tests configuration" 72 ] 73 }, 74 { 75 "cell_type": "code", 76 "execution_count": 4, 77 "metadata": { 78 "collapsed": false 79 }, 80 "outputs": [ 81 { 82 "name": "stderr", 83 "output_type": "stream", 84 "text": [ 85 "01:43:51 INFO : Target - Using base path: /home/bjackman/sources/lisa\n", 86 "01:43:51 INFO : Target - Loading custom (inline) target configuration\n", 87 "01:43:51 INFO : Target - Loading custom (inline) test configuration\n", 88 "01:43:51 INFO : Target - Devlib modules to load: ['bl', 'cpufreq']\n", 89 "01:43:51 INFO : Target - Connecting linux target:\n", 90 "01:43:51 INFO : Target - username : brendan\n", 91 "01:43:51 INFO : Target - host : 192.168.0.1\n", 92 "01:43:51 INFO : Target - password : \n", 93 "01:43:51 INFO : Target - Connection settings:\n", 94 "01:43:51 INFO : Target - {'username': 'brendan', 'host': '192.168.0.1', 'password': ''}\n", 95 "01:43:58 INFO : Target - Initializing target workdir:\n", 96 "01:43:58 INFO : Target - /home/brendan/devlib-target\n", 97 "01:44:04 INFO : Target - Topology:\n", 98 "01:44:04 INFO : Target - [[0, 3, 4, 5], [1, 2]]\n", 99 "01:44:07 INFO : Platform - Loading default EM:\n", 100 "01:44:07 INFO : Platform - /home/bjackman/sources/lisa/libs/utils/platforms/juno.json\n", 101 "01:44:11 INFO : FTrace - Enabled tracepoints:\n", 102 "01:44:11 INFO : FTrace - sched:*\n", 103 "01:44:11 INFO : FTrace - Kernel functions profiled:\n", 104 "01:44:11 INFO : FTrace - select_task_rq_fair\n", 105 "01:44:11 INFO : FTrace - enqueue_task_fair\n", 106 "01:44:11 INFO : FTrace - dequeue_task_fair\n", 107 "01:44:11 WARNING : Target - Using configuration provided RTApp calibration\n", 108 "01:44:11 INFO : Target - Using RT-App calibration values:\n", 109 "01:44:11 INFO : Target - {\"0\": 358, \"1\": 138, \"2\": 138, \"3\": 357, \"4\": 359, \"5\": 355}\n", 110 "01:44:11 WARNING : TestEnv - Wipe previous contents of the results folder:\n", 111 "01:44:11 WARNING : TestEnv - /home/bjackman/sources/lisa/results/KernelFunctionsProfilingExample\n", 112 "01:44:11 INFO : HWMon - HWMON module not enabled\n", 113 "01:44:11 WARNING : HWMon - Energy sampling disabled by configuration\n", 114 "01:44:11 INFO : TestEnv - Set results folder to:\n", 115 "01:44:11 INFO : TestEnv - /home/bjackman/sources/lisa/results/KernelFunctionsProfilingExample\n", 116 "01:44:11 INFO : TestEnv - Experiment results available also in:\n", 117 "01:44:11 INFO : TestEnv - /home/bjackman/sources/lisa/results_latest\n" 118 ] 119 } 120 ], 121 "source": [ 122 "# Setup a target configuration\n", 123 "target_conf = {\n", 124 "\n", 125 " # Platform and board to target\n", 126 " \"platform\" : \"linux\",\n", 127 " \"board\" : \"juno\",\n", 128 "\n", 129 " # Login credentials\n", 130 " \"host\" : \"192.168.0.1\",\n", 131 " \"username\" : \"brendan\",\n", 132 " \"password\" : \"\",\n", 133 "\n", 134 " # Local installation path\n", 135 " \"tftp\" : {\n", 136 " \"folder\" : \"/var/lib/tftpboot\",\n", 137 " \"kernel\" : \"kern.bin\",\n", 138 " \"dtb\" : \"dtb.bin\",\n", 139 " },\n", 140 "\n", 141 " # RTApp calibration values (comment to let LISA do a calibration run)\n", 142 " \"rtapp-calib\" : {\n", 143 " \"0\": 358, \"1\": 138, \"2\": 138, \"3\": 357, \"4\": 359, \"5\": 355\n", 144 " },\n", 145 "\n", 146 "}\n", 147 "\n", 148 "test_conf = {\n", 149 " # Tools to deploy\n", 150 " \"tools\" : [ \"rt-app\", 'trace-cmd' ],\n", 151 " \n", 152 " # Where results are collected\n", 153 " # NOTE: this folder will be wiped before running the experiments\n", 154 " \"results_dir\" : \"KernelFunctionsProfilingExample\",\n", 155 "\n", 156 " # Modules required by these experiments\n", 157 " \"exclude_modules\" : [ \"hwmon\" ],\n", 158 " \n", 159 " # Kernel functions to profile for all the test\n", 160 " # configurations which have the \"ftrace\" flag enabled\n", 161 " \"ftrace\" : {\n", 162 " \"functions\" : [\n", 163 " \"select_task_rq_fair\",\n", 164 " \"enqueue_task_fair\",\n", 165 " \"dequeue_task_fair\",\n", 166 " ],\n", 167 " \"buffsize\" : 80 * 1024,\n", 168 " },\n", 169 "}\n", 170 "\n", 171 "env = TestEnv(target_conf, test_conf)" 172 ] 173 }, 174 { 175 "cell_type": "code", 176 "execution_count": 9, 177 "metadata": { 178 "collapsed": false 179 }, 180 "outputs": [ 181 { 182 "name": "stderr", 183 "output_type": "stream", 184 "text": [ 185 "01:50:59 INFO : Target - Loading custom (inline) test configuration\n", 186 "01:50:59 INFO : \n", 187 "01:50:59 INFO : ################################################################################\n", 188 "01:50:59 INFO : Executor - Experiments configuration\n", 189 "01:50:59 INFO : ################################################################################\n", 190 "01:50:59 INFO : Executor - Configured to run:\n", 191 "01:50:59 INFO : Executor - 2 target configurations:\n", 192 "01:50:59 INFO : Executor - base, eas\n", 193 "01:50:59 INFO : Executor - 1 workloads (3 iterations each)\n", 194 "01:50:59 INFO : Executor - rta\n", 195 "01:50:59 INFO : Executor - Total: 6 experiments\n", 196 "01:50:59 INFO : Executor - Results will be collected under:\n", 197 "01:50:59 INFO : Executor - /home/bjackman/sources/lisa/results/KernelFunctionsProfilingExample\n" 198 ] 199 } 200 ], 201 "source": [ 202 "# Setup tests executions based on our configuration\n", 203 " \n", 204 "tests_conf = {\n", 205 " # Platform configurations to test\n", 206 " \"confs\" : [\n", 207 " {\n", 208 " \"tag\" : \"base\",\n", 209 " \"flags\" : \"ftrace\",\n", 210 " \"sched_features\" : \"NO_ENERGY_AWARE\",\n", 211 " \"cpufreq\" : {\n", 212 " \"governor\" : \"performance\",\n", 213 " },\n", 214 " # provide a set of files and values to write into them\n", 215 " \"files\" : {\n", 216 " # if filenames start with !/ then we verify that the content\n", 217 " # matches what we wrote and raise an exception if it does not.\n", 218 " # All filenames without an initial decorator are not verified,\n", 219 " # and we do not assert that the write was allowed\n", 220 " # (i,e, the file existed, we have write permission, etc.)\n", 221 " # this means we can use this for sysctls or other files whose\n", 222 " # presence or permissions might depend upon kernel config or\n", 223 " # OS support and we reasonably can proceed for either case.\n", 224 " '/this_file_doesnt_exist_and_we_dont_care' : '1',\n", 225 " '/proc/sys/kernel/sched_is_big_little' : '0',\n", 226 " '/proc/sys/kernel/sched_initial_task_util' : '1023',\n", 227 " '/proc/sys/kernel/sched_use_walt_cpu_util' : '0',\n", 228 " '/proc/sys/kernel/sched_use_walt_task_util' : '0',\n", 229 " '/proc/sys/kernel/sched_cstate_aware' : '1',\n", 230 " '/proc/sys/kernel/sched_walt_cpu_high_irqload' : '10000000',\n", 231 " '/proc/sys/kernel/sched_init_task_load_pct' : '15',\n", 232 " '!/proc/sys/kernel/sched_latency_ns' : '10000000',\n", 233 " '!/proc/sys/kernel/sched_migration_cost_ns' : '500000',\n", 234 " },\n", 235 " },\n", 236 " {\n", 237 " \"tag\" : \"eas\",\n", 238 " \"flags\" : \"ftrace\",\n", 239 " \"sched_features\" : \"ENERGY_AWARE\",\n", 240 " \"cpufreq\" : {\n", 241 " \"governor\" : \"performance\",\n", 242 " },\n", 243 " \"files\" : {\n", 244 " '/proc/sys/kernel/sched_is_big_little' : '1',\n", 245 " '/proc/sys/kernel/sched_initial_task_util' : '1023',\n", 246 " '/proc/sys/kernel/sched_use_walt_cpu_util' : '0',\n", 247 " '/proc/sys/kernel/sched_use_walt_task_util' : '0',\n", 248 " '/proc/sys/kernel/sched_cstate_aware' : '1',\n", 249 " '/proc/sys/kernel/sched_walt_cpu_high_irqload' : '10000000',\n", 250 " '/proc/sys/kernel/sched_init_task_load_pct' : '15',\n", 251 " '!/proc/sys/kernel/sched_latency_ns' : '10000000',\n", 252 " '!/proc/sys/kernel/sched_migration_cost_ns' : '500000',\n", 253 " },\n", 254 " },\n", 255 " ],\n", 256 " \n", 257 " # Workloads to run (on each platform configuration)\n", 258 " \"wloads\" : {\n", 259 " \"rta\" : {\n", 260 " \"type\" : \"rt-app\",\n", 261 " \"conf\" : {\n", 262 " \"class\" : \"profile\",\n", 263 " \"params\" : {\n", 264 " \"p20\" : {\n", 265 " \"kind\" : \"Periodic\",\n", 266 " \"params\" : {\n", 267 " \"duty_cycle_pct\" : 20,\n", 268 " },\n", 269 " \"tasks\" : \"cpus\",\n", 270 " },\n", 271 " },\n", 272 " },\n", 273 " },\n", 274 " },\n", 275 " \n", 276 " # Number of iterations for each configuration/workload pair\n", 277 " \"iterations\" : 3,\n", 278 "}\n", 279 "\n", 280 "executor = Executor(env, tests_conf)" 281 ] 282 }, 283 { 284 "cell_type": "markdown", 285 "metadata": {}, 286 "source": [ 287 "# Tests execution" 288 ] 289 }, 290 { 291 "cell_type": "code", 292 "execution_count": 10, 293 "metadata": { 294 "collapsed": false, 295 "scrolled": true 296 }, 297 "outputs": [ 298 { 299 "name": "stderr", 300 "output_type": "stream", 301 "text": [ 302 "01:51:01 INFO : \n", 303 "01:51:01 INFO : ################################################################################\n", 304 "01:51:01 INFO : Executor - Experiments execution\n", 305 "01:51:01 INFO : ################################################################################\n", 306 "01:51:01 INFO : \n", 307 "01:51:01 INFO : ================================================================================\n", 308 "01:51:01 INFO : TargetConfig - configuring target for [base] experiments\n", 309 "01:51:03 INFO : SchedFeatures - Set scheduler feature: NO_ENERGY_AWARE\n", 310 "01:51:04 INFO : CPUFreq - Configuring all CPUs to use [performance] governor\n", 311 "01:51:05 INFO : WlGen - Setup new workload rta\n", 312 "01:51:05 INFO : RTApp - Workload duration defined by longest task\n", 313 "01:51:05 INFO : RTApp - Default policy: SCHED_OTHER\n", 314 "01:51:05 INFO : RTApp - ------------------------\n", 315 "01:51:05 INFO : RTApp - task [task_p200], sched: using default policy\n", 316 "01:51:05 INFO : RTApp - | calibration CPU: 1\n", 317 "01:51:05 INFO : RTApp - | loops count: 1\n", 318 "01:51:05 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 319 "01:51:05 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 320 "01:51:05 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 321 "01:51:05 INFO : RTApp - ------------------------\n", 322 "01:51:05 INFO : RTApp - task [task_p201], sched: using default policy\n", 323 "01:51:05 INFO : RTApp - | calibration CPU: 1\n", 324 "01:51:05 INFO : RTApp - | loops count: 1\n", 325 "01:51:05 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 326 "01:51:05 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 327 "01:51:05 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 328 "01:51:05 INFO : RTApp - ------------------------\n", 329 "01:51:05 INFO : RTApp - task [task_p202], sched: using default policy\n", 330 "01:51:05 INFO : RTApp - | calibration CPU: 1\n", 331 "01:51:05 INFO : RTApp - | loops count: 1\n", 332 "01:51:05 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 333 "01:51:05 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 334 "01:51:05 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 335 "01:51:05 INFO : RTApp - ------------------------\n", 336 "01:51:05 INFO : RTApp - task [task_p203], sched: using default policy\n", 337 "01:51:05 INFO : RTApp - | calibration CPU: 1\n", 338 "01:51:05 INFO : RTApp - | loops count: 1\n", 339 "01:51:05 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 340 "01:51:05 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 341 "01:51:05 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 342 "01:51:05 INFO : RTApp - ------------------------\n", 343 "01:51:05 INFO : RTApp - task [task_p204], sched: using default policy\n", 344 "01:51:05 INFO : RTApp - | calibration CPU: 1\n", 345 "01:51:05 INFO : RTApp - | loops count: 1\n", 346 "01:51:05 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 347 "01:51:05 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 348 "01:51:05 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 349 "01:51:05 INFO : RTApp - ------------------------\n", 350 "01:51:05 INFO : RTApp - task [task_p205], sched: using default policy\n", 351 "01:51:05 INFO : RTApp - | calibration CPU: 1\n", 352 "01:51:05 INFO : RTApp - | loops count: 1\n", 353 "01:51:05 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 354 "01:51:05 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 355 "01:51:05 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 356 "01:51:06 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 357 "01:51:06 INFO : Executor - Experiment 0/6, [base:rta] 1/3\n", 358 "01:51:06 WARNING : Executor - FTrace events collection enabled\n", 359 "01:51:17 INFO : WlGen - Workload execution START:\n", 360 "01:51:17 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 361 "01:51:30 INFO : Executor - Collected FTrace binary trace:\n", 362 "01:51:30 INFO : Executor - <res_dir>/rtapp:base:rta/1/trace.dat\n", 363 "01:51:31 INFO : Executor - Collected FTrace function profiling:\n", 364 "01:51:31 INFO : Executor - <res_dir>/rtapp:base:rta/1/trace_stat.json\n", 365 "01:51:31 INFO : --------------------------------------------------------------------------------\n", 366 "01:51:31 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 367 "01:51:31 INFO : Executor - Experiment 1/6, [base:rta] 2/3\n", 368 "01:51:31 WARNING : Executor - FTrace events collection enabled\n", 369 "01:51:43 INFO : WlGen - Workload execution START:\n", 370 "01:51:43 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 371 "01:51:52 INFO : Executor - Collected FTrace binary trace:\n", 372 "01:51:52 INFO : Executor - <res_dir>/rtapp:base:rta/2/trace.dat\n", 373 "01:51:53 INFO : Executor - Collected FTrace function profiling:\n", 374 "01:51:53 INFO : Executor - <res_dir>/rtapp:base:rta/2/trace_stat.json\n", 375 "01:51:53 INFO : --------------------------------------------------------------------------------\n", 376 "01:51:53 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 377 "01:51:53 INFO : Executor - Experiment 2/6, [base:rta] 3/3\n", 378 "01:51:53 WARNING : Executor - FTrace events collection enabled\n", 379 "01:52:05 INFO : WlGen - Workload execution START:\n", 380 "01:52:05 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 381 "01:52:19 INFO : Executor - Collected FTrace binary trace:\n", 382 "01:52:19 INFO : Executor - <res_dir>/rtapp:base:rta/3/trace.dat\n", 383 "01:52:20 INFO : Executor - Collected FTrace function profiling:\n", 384 "01:52:20 INFO : Executor - <res_dir>/rtapp:base:rta/3/trace_stat.json\n", 385 "01:52:20 INFO : --------------------------------------------------------------------------------\n", 386 "01:52:20 INFO : \n", 387 "01:52:20 INFO : ================================================================================\n", 388 "01:52:20 INFO : TargetConfig - configuring target for [eas] experiments\n", 389 "01:52:22 INFO : SchedFeatures - Set scheduler feature: ENERGY_AWARE\n", 390 "01:52:23 INFO : CPUFreq - Configuring all CPUs to use [performance] governor\n", 391 "01:52:24 INFO : WlGen - Setup new workload rta\n", 392 "01:52:24 INFO : RTApp - Workload duration defined by longest task\n", 393 "01:52:24 INFO : RTApp - Default policy: SCHED_OTHER\n", 394 "01:52:24 INFO : RTApp - ------------------------\n", 395 "01:52:24 INFO : RTApp - task [task_p200], sched: using default policy\n", 396 "01:52:24 INFO : RTApp - | calibration CPU: 1\n", 397 "01:52:24 INFO : RTApp - | loops count: 1\n", 398 "01:52:24 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 399 "01:52:24 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 400 "01:52:24 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 401 "01:52:24 INFO : RTApp - ------------------------\n", 402 "01:52:24 INFO : RTApp - task [task_p201], sched: using default policy\n", 403 "01:52:24 INFO : RTApp - | calibration CPU: 1\n", 404 "01:52:24 INFO : RTApp - | loops count: 1\n", 405 "01:52:24 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 406 "01:52:24 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 407 "01:52:24 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 408 "01:52:24 INFO : RTApp - ------------------------\n", 409 "01:52:24 INFO : RTApp - task [task_p202], sched: using default policy\n", 410 "01:52:24 INFO : RTApp - | calibration CPU: 1\n", 411 "01:52:24 INFO : RTApp - | loops count: 1\n", 412 "01:52:24 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 413 "01:52:24 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 414 "01:52:24 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 415 "01:52:24 INFO : RTApp - ------------------------\n", 416 "01:52:24 INFO : RTApp - task [task_p203], sched: using default policy\n", 417 "01:52:24 INFO : RTApp - | calibration CPU: 1\n", 418 "01:52:24 INFO : RTApp - | loops count: 1\n", 419 "01:52:24 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 420 "01:52:24 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 421 "01:52:24 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 422 "01:52:24 INFO : RTApp - ------------------------\n", 423 "01:52:24 INFO : RTApp - task [task_p204], sched: using default policy\n", 424 "01:52:24 INFO : RTApp - | calibration CPU: 1\n", 425 "01:52:24 INFO : RTApp - | loops count: 1\n", 426 "01:52:24 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 427 "01:52:24 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 428 "01:52:24 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 429 "01:52:24 INFO : RTApp - ------------------------\n", 430 "01:52:24 INFO : RTApp - task [task_p205], sched: using default policy\n", 431 "01:52:24 INFO : RTApp - | calibration CPU: 1\n", 432 "01:52:24 INFO : RTApp - | loops count: 1\n", 433 "01:52:24 INFO : RTApp - + phase_000001: duration 1.000000 [s] (10 loops)\n", 434 "01:52:24 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", 435 "01:52:24 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", 436 "01:52:24 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 437 "01:52:24 INFO : Executor - Experiment 0/6, [base:rta] 1/3\n", 438 "01:52:24 WARNING : Executor - FTrace events collection enabled\n", 439 "01:52:37 INFO : WlGen - Workload execution START:\n", 440 "01:52:37 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 441 "01:52:47 INFO : Executor - Collected FTrace binary trace:\n", 442 "01:52:47 INFO : Executor - <res_dir>/rtapp:base:rta/1/trace.dat\n", 443 "01:52:48 INFO : Executor - Collected FTrace function profiling:\n", 444 "01:52:48 INFO : Executor - <res_dir>/rtapp:base:rta/1/trace_stat.json\n", 445 "01:52:48 INFO : --------------------------------------------------------------------------------\n", 446 "01:52:48 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 447 "01:52:48 INFO : Executor - Experiment 1/6, [base:rta] 2/3\n", 448 "01:52:48 WARNING : Executor - FTrace events collection enabled\n", 449 "01:53:00 INFO : WlGen - Workload execution START:\n", 450 "01:53:00 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 451 "01:53:12 INFO : Executor - Collected FTrace binary trace:\n", 452 "01:53:12 INFO : Executor - <res_dir>/rtapp:base:rta/2/trace.dat\n", 453 "01:53:13 INFO : Executor - Collected FTrace function profiling:\n", 454 "01:53:13 INFO : Executor - <res_dir>/rtapp:base:rta/2/trace_stat.json\n", 455 "01:53:13 INFO : --------------------------------------------------------------------------------\n", 456 "01:53:13 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 457 "01:53:13 INFO : Executor - Experiment 2/6, [base:rta] 3/3\n", 458 "01:53:13 WARNING : Executor - FTrace events collection enabled\n", 459 "01:53:25 INFO : WlGen - Workload execution START:\n", 460 "01:53:25 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 461 "01:53:35 INFO : Executor - Collected FTrace binary trace:\n", 462 "01:53:35 INFO : Executor - <res_dir>/rtapp:base:rta/3/trace.dat\n", 463 "01:53:36 INFO : Executor - Collected FTrace function profiling:\n", 464 "01:53:36 INFO : Executor - <res_dir>/rtapp:base:rta/3/trace_stat.json\n", 465 "01:53:36 INFO : --------------------------------------------------------------------------------\n", 466 "01:53:36 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 467 "01:53:36 INFO : Executor - Experiment 3/6, [eas:rta] 1/3\n", 468 "01:53:36 WARNING : Executor - FTrace events collection enabled\n", 469 "01:53:48 INFO : WlGen - Workload execution START:\n", 470 "01:53:48 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 471 "01:53:57 INFO : Executor - Collected FTrace binary trace:\n", 472 "01:53:57 INFO : Executor - <res_dir>/rtapp:eas:rta/1/trace.dat\n", 473 "01:53:58 INFO : Executor - Collected FTrace function profiling:\n", 474 "01:53:58 INFO : Executor - <res_dir>/rtapp:eas:rta/1/trace_stat.json\n", 475 "01:53:58 INFO : --------------------------------------------------------------------------------\n", 476 "01:53:58 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 477 "01:53:58 INFO : Executor - Experiment 4/6, [eas:rta] 2/3\n", 478 "01:53:58 WARNING : Executor - FTrace events collection enabled\n", 479 "01:54:10 INFO : WlGen - Workload execution START:\n", 480 "01:54:10 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 481 "01:54:22 INFO : Executor - Collected FTrace binary trace:\n", 482 "01:54:22 INFO : Executor - <res_dir>/rtapp:eas:rta/2/trace.dat\n", 483 "01:54:23 INFO : Executor - Collected FTrace function profiling:\n", 484 "01:54:23 INFO : Executor - <res_dir>/rtapp:eas:rta/2/trace_stat.json\n", 485 "01:54:23 INFO : --------------------------------------------------------------------------------\n", 486 "01:54:23 INFO : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", 487 "01:54:23 INFO : Executor - Experiment 5/6, [eas:rta] 3/3\n", 488 "01:54:23 WARNING : Executor - FTrace events collection enabled\n", 489 "01:54:35 INFO : WlGen - Workload execution START:\n", 490 "01:54:35 INFO : WlGen - /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/rta_00.json 2>&1\n", 491 "01:54:45 INFO : Executor - Collected FTrace binary trace:\n", 492 "01:54:45 INFO : Executor - <res_dir>/rtapp:eas:rta/3/trace.dat\n", 493 "01:54:46 INFO : Executor - Collected FTrace function profiling:\n", 494 "01:54:46 INFO : Executor - <res_dir>/rtapp:eas:rta/3/trace_stat.json\n", 495 "01:54:46 INFO : --------------------------------------------------------------------------------\n", 496 "01:54:46 INFO : \n", 497 "01:54:46 INFO : ################################################################################\n", 498 "01:54:46 INFO : Executor - Experiments execution completed\n", 499 "01:54:46 INFO : ################################################################################\n", 500 "01:54:46 INFO : Executor - Results available in:\n", 501 "01:54:46 INFO : Executor - /home/bjackman/sources/lisa/results/KernelFunctionsProfilingExample\n" 502 ] 503 } 504 ], 505 "source": [ 506 "# Execute all the configured test\n", 507 "executor.run()" 508 ] 509 }, 510 { 511 "cell_type": "code", 512 "execution_count": null, 513 "metadata": { 514 "collapsed": false 515 }, 516 "outputs": [], 517 "source": [ 518 "res_dir = \"/home/derkling/Code/lisa/results/KernelFunctionsProfilingExample\"\n", 519 "out_dir = \"/home/derkling/Code/lisa/results/KernelFunctionsProfilingExample/rtapp:eas:rta/2/trace.dat\"\n", 520 "out_dir.replace(res_dir, \"<res_dir>\")\n", 521 "print executor.te.res_dir" 522 ] 523 }, 524 { 525 "cell_type": "code", 526 "execution_count": 11, 527 "metadata": { 528 "collapsed": false, 529 "scrolled": false 530 }, 531 "outputs": [ 532 { 533 "name": "stderr", 534 "output_type": "stream", 535 "text": [ 536 "01:56:21 INFO : Content of the output folder /home/bjackman/sources/lisa/results/KernelFunctionsProfilingExample\n" 537 ] 538 }, 539 { 540 "name": "stdout", 541 "output_type": "stream", 542 "text": [ 543 "\u001b[01;34m/home/bjackman/sources/lisa/results/KernelFunctionsProfilingExample\u001b[00m\r\n", 544 " \u001b[01;34mrtapp:base:rta\u001b[00m\r\n", 545 " \u001b[01;34m1\u001b[00m\r\n", 546 " output.log\r\n", 547 " rta_00.json\r\n", 548 " rt-app-task_p200-0.log\r\n", 549 " rt-app-task_p201-1.log\r\n", 550 " rt-app-task_p202-2.log\r\n", 551 " rt-app-task_p203-3.log\r\n", 552 " rt-app-task_p204-4.log\r\n", 553 " rt-app-task_p205-5.log\r\n", 554 " trace.dat\r\n", 555 " trace_stat.json\r\n", 556 " \u001b[01;34m2\u001b[00m\r\n", 557 " output.log\r\n", 558 " rta_00.json\r\n", 559 " rt-app-task_p200-0.log\r\n", 560 " rt-app-task_p201-1.log\r\n", 561 " rt-app-task_p202-2.log\r\n", 562 " rt-app-task_p203-3.log\r\n", 563 " rt-app-task_p204-4.log\r\n", 564 " rt-app-task_p205-5.log\r\n", 565 " trace.dat\r\n", 566 " trace_stat.json\r\n", 567 " \u001b[01;34m3\u001b[00m\r\n", 568 " output.log\r\n", 569 " rta_00.json\r\n", 570 " rt-app-task_p200-0.log\r\n", 571 " rt-app-task_p201-1.log\r\n", 572 " rt-app-task_p202-2.log\r\n", 573 " rt-app-task_p203-3.log\r\n", 574 " rt-app-task_p204-4.log\r\n", 575 " rt-app-task_p205-5.log\r\n", 576 " trace.dat\r\n", 577 " trace_stat.json\r\n", 578 " kernel.config\r\n", 579 " kernel.version\r\n", 580 " platform.json\r\n", 581 " \u001b[01;34mrtapp:eas:rta\u001b[00m\r\n", 582 " \u001b[01;34m1\u001b[00m\r\n", 583 " output.log\r\n", 584 " rta_00.json\r\n", 585 " rt-app-task_p200-0.log\r\n", 586 " rt-app-task_p201-1.log\r\n", 587 " rt-app-task_p202-2.log\r\n", 588 " rt-app-task_p203-3.log\r\n", 589 " rt-app-task_p204-4.log\r\n", 590 " rt-app-task_p205-5.log\r\n", 591 " trace.dat\r\n", 592 " trace_stat.json\r\n", 593 " \u001b[01;34m2\u001b[00m\r\n", 594 " output.log\r\n", 595 " rta_00.json\r\n", 596 " rt-app-task_p200-0.log\r\n", 597 " rt-app-task_p201-1.log\r\n", 598 " rt-app-task_p202-2.log\r\n", 599 " rt-app-task_p203-3.log\r\n", 600 " rt-app-task_p204-4.log\r\n", 601 " rt-app-task_p205-5.log\r\n", 602 " trace.dat\r\n", 603 " trace_stat.json\r\n", 604 " \u001b[01;34m3\u001b[00m\r\n", 605 " output.log\r\n", 606 " rta_00.json\r\n", 607 " rt-app-task_p200-0.log\r\n", 608 " rt-app-task_p201-1.log\r\n", 609 " rt-app-task_p202-2.log\r\n", 610 " rt-app-task_p203-3.log\r\n", 611 " rt-app-task_p204-4.log\r\n", 612 " rt-app-task_p205-5.log\r\n", 613 " trace.dat\r\n", 614 " trace_stat.json\r\n", 615 " kernel.config\r\n", 616 " kernel.version\r\n", 617 " platform.json\r\n", 618 "\r\n", 619 "8 directories, 66 files\r\n" 620 ] 621 } 622 ], 623 "source": [ 624 "# Check content of the output folder\n", 625 "res_dir = executor.te.res_dir\n", 626 "logging.info('Content of the output folder %s', res_dir)\n", 627 "!tree {res_dir}" 628 ] 629 }, 630 { 631 "cell_type": "markdown", 632 "metadata": {}, 633 "source": [ 634 "# Load function profiling data" 635 ] 636 }, 637 { 638 "cell_type": "code", 639 "execution_count": 12, 640 "metadata": { 641 "collapsed": false, 642 "scrolled": false 643 }, 644 "outputs": [], 645 "source": [ 646 "def autodict():\n", 647 " return collections.defaultdict(autodict)\n", 648 "\n", 649 "def parse_perf_stat(res_dir):\n", 650 " TEST_DIR_RE = re.compile(r'.*/([^:]*):([^:]*):([^:]*)')\n", 651 " profiling_data = autodict()\n", 652 "\n", 653 " for test_idx in sorted(os.listdir(res_dir)):\n", 654 " test_dir = os.path.join(res_dir, test_idx)\n", 655 " if not os.path.isdir(test_dir):\n", 656 " continue\n", 657 " match = TEST_DIR_RE.search(test_dir)\n", 658 " if not match:\n", 659 " continue\n", 660 " wtype = match.group(1)\n", 661 " tconf = match.group(2)\n", 662 " wload = match.group(3)\n", 663 "\n", 664 " #logging.info('Processing %s:%s:%s', wtype, tconf, wload)\n", 665 " trace_stat_file = os.path.join(test_dir, '1', 'trace_stat.json')\n", 666 " if not os.path.isfile(trace_stat_file):\n", 667 " continue\n", 668 " with open(trace_stat_file, 'r') as fh:\n", 669 " data = json.load(fh)\n", 670 " for cpu_id, cpu_stats in sorted(data.items()):\n", 671 " for fname in cpu_stats:\n", 672 " profiling_data[cpu_id][tconf][fname] = cpu_stats[fname]\n", 673 "\n", 674 " return profiling_data\n", 675 " \n", 676 "profiling_data = parse_perf_stat(res_dir)\n", 677 "#logging.info(\"Profiling data:\\n%s\", json.dumps(profiling_data, indent=4))\n", 678 "#profiling_data" 679 ] 680 }, 681 { 682 "cell_type": "markdown", 683 "metadata": {}, 684 "source": [ 685 "## Build Pandas DataFrame from profiling data" 686 ] 687 }, 688 { 689 "cell_type": "code", 690 "execution_count": 13, 691 "metadata": { 692 "collapsed": false 693 }, 694 "outputs": [], 695 "source": [ 696 "def get_df(profiling_data):\n", 697 " cpu_ids = []\n", 698 " cpu_frames = []\n", 699 " for cpu_id, cpu_data in sorted(profiling_data.items()):\n", 700 " cpu_ids.append(cpu_id)\n", 701 " conf_ids = []\n", 702 " conf_frames = []\n", 703 " for conf_id, conf_data in cpu_data.iteritems():\n", 704 " conf_ids.append(conf_id)\n", 705 " function_data = pandas.DataFrame.from_dict(conf_data, orient='index')\n", 706 " conf_frames.append(function_data)\n", 707 " df = pandas.concat(conf_frames, keys=conf_ids)\n", 708 " cpu_frames.append(df)\n", 709 " df = pandas.concat(cpu_frames, keys=cpu_ids)\n", 710 " #df.head()\n", 711 " return df\n", 712 "\n", 713 "stats_df = get_df(profiling_data)\n", 714 "#stats_df" 715 ] 716 }, 717 { 718 "cell_type": "markdown", 719 "metadata": {}, 720 "source": [ 721 "## Plot profiling data per function and CPU" 722 ] 723 }, 724 { 725 "cell_type": "code", 726 "execution_count": 14, 727 "metadata": { 728 "collapsed": false 729 }, 730 "outputs": [], 731 "source": [ 732 "def plot_stats(df, fname, axes=None):\n", 733 " func_data = df.xs(fname, level=2)\n", 734 " func_stats = func_data.xs(['avg', 's_2'], axis=1)\n", 735 " #func_stats\n", 736 " func_avg = func_stats.unstack(level=1)['avg']\n", 737 " func_std = func_stats.unstack(level=1)['s_2'].apply(numpy.sqrt)\n", 738 " func_avg.plot(kind='bar', title=fname, yerr=func_std, ax=axes);\n", 739 "\n", 740 "#plot_stats(stats_df, 'select_task_rq_fair')" 741 ] 742 }, 743 { 744 "cell_type": "code", 745 "execution_count": 15, 746 "metadata": { 747 "collapsed": false, 748 "scrolled": false 749 }, 750 "outputs": [ 751 { 752 "name": "stderr", 753 "output_type": "stream", 754 "text": [ 755 "01:56:33 INFO : Plotting stats for [dequeue_task_fair] function\n", 756 "01:56:33 INFO : Plotting stats for [enqueue_task_fair] function\n", 757 "01:56:33 INFO : Plotting stats for [select_task_rq_fair] function\n", 758 "/usr/lib/pymodules/python2.7/matplotlib/collections.py:548: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison\n", 759 " if self._edgecolors == 'face':\n" 760 ] 761 }, 762 { 763 "data": { 764 "image/png": "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\n5I477siaNWvyyU9+Mknyta99LbfffnseeeSRjIyM5JZbbslhhx027fUKmwAAAD3gzjvvzJNPPplL\nL7008+bNy+LFi/POd74zn/nMZ3LKKafktNNOy5w5c3LcccdlxYoVWbt2bZLkgAMOyOjoaL7zne9k\n+/btOeGEE3LUUUdNe73zpv0KAAAAtG3Dhg3ZtGlTBgYGxvY9//zzOf300/PII4/koosuyt13351n\nnnkmP/vZz3LqqacmSc4888ysXLky73nPe7Jhw4a8/vWvz1VXXZW+vr5prVfPJgAAQA849thjs3jx\n4gwPD489tmzZkttuuy3nn39+li5dmu9973sZGRnJ5Zdfnu3bt4+de8EFF+Suu+7KQw89lPXr1+fK\nK6+c9nqFTQAAgB5w2mmnpa+vLx/96Eezbdu2PP/883nggQdy55135umnn05fX1/mz5+fhx9+ONdd\nd92OWWJz11135dvf/naee+65zJ8/PwceeGDmzp077fUKmwAAALvR1zeQamWP6XlU7e/ZnDlzcttt\nt+Xee+/NkiVL8tKXvjQrVqzI6OhorrrqqqxatSr9/f1ZsWJFli9fPnbeli1bsmLFigwODmbRokU5\n/PDDc/HFF7f9fdkT62wCALvVaDTSaDTGtuv1epKkXq+PbQPMFpOtJcner7MpbAIAU+aPMGC283tu\ncnsbNg2jBQAAoDhhEwAAgOKETQAAAIoTNgEAAChO2AQAAKA4YRMAAIDihE0AAACKEzYBAAB6wKJF\ni7JmzZpOlzFlwiYAAMBu9B/an1qtNm2P/kP7p1THjuN7xbxOFwAAANDNRkdGk6FpbH9odPoa7yA9\nmwAAAD1i3bp1ecUrXpHBwcG8/e1vz7PPPpvh4eGcffbZOeKIIzI4OJhzzjknjz/++Ng5N910U44/\n/vj09/dnyZIlWbVq1dhzN954Y5YuXZrBwcGcddZZ2bhxY7FahU0AAIAe0Gw2s2rVqqxevTrf//73\ns379+nz4wx9Os9nMO97xjmzcuDEbN27MQQcdlJUrVyZJtm7dmgsvvDBf/epXs2XLltxxxx151ate\nlSS59dZb85GPfCRf/OIX8+STT+a1r31tzjvvvGL1CpsAAAA9oFarZeXKlTn66KMzMDCQD33oQ7n5\n5pszODiY173udTnwwANzyCGH5IMf/GDWrl07dt6cOXNy//33Z9u2bTnyyCOzdOnSJMn111+fSy65\n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\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAABCtpXKAAAgAElEQVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMB1uSvJf9/Kc\ng5J8JclTST47heMfSHL6Xl4DAHZpXqcLAIBZrJ7kfyY5pkBbzdZjb/xmkiOSDCbZPoXjf35viwKA\nyczpdAEAwJTV9vL445Ksz9SC5p7MLdAGAADAtFuY5PNJfpTk75Jc0No/lOTPk/yPJFtSDe38F+PO\nOznJ37Se+0zrsWN46VuT3D7hOtuTLGlt/5MkVyXZkOSJJNclObDAubtycJJtSZ5PMtqq96gkpyW5\nI8lwkk1Jrk1ywLjzrk7ywyQjSf42ydLW/k+Ne519Sb6V5JrdXP+yJM8m+Wnr+m9rvZZvJnkyyY+T\n/GmSBePOeTTJma3toSSfS9UzO5Lk7bu5FgDsRM8mAJ0wJ9W9hPekCp2/kuR9SZa1nj8nyc2pgtCX\nk/xRa/9LknwpVRAdSHJLktdn6sNL/+8k/yzJSa1/j07yB9N07tYkZ6UKlH1J+lOF1J8luTDJYUle\nk+q1/4fWOf8myWuT/PNUr/2NSTaPa7PZOm9NqmD8vt1c/z8nuSJVGO9LFVZrSS5P8nNJXp5qeO/Q\nhPbH+41U3+MFSVbt5loAAABd4ZdS9RCOd0mSG1OFpNXj9i9N8kxr+/Qkj08476+S/JfW9lszee9k\nLcnTeaGnMqnC3t8VOHcy9SSP7eGY9yX5Qmv7zCTfTfX9mfgfwp9K8idJ7k/yH/fQ5g5DqXomJ3Nu\nql7iHX6QF/dsNqZ4HQDYiQmCAOiE41L1aA6P2zc3yf+XKoT+cNz+Z1INV53TOmdi2JwYWifz0iTz\nk9w9bl8tUxvl0865E70syR+mGho8P9Vn8V2t576Zqhf3E6m+R19I8vuphsHWkvx6a/u/7cN1k+TI\nJB9P8supejvn5MU9pxP9/T5eBwAMowWgIzam6kUbGPfoT3L2Hs77h1TDV8c7btz21lQBboejxm0/\nmeoeyqXjrnlo67rtnjuZXQ3vvS7JQ6mG4i5I8qG8+PP42iSntq71siQXj2vrj5N8LclfTqh1qte/\nItU9pD/fuvbvZvd/C+zt7LcAMEbYBKAT1qXqofs/U60FOTdVADp1D+fdkeqex/emmlTn9Ul+cdzz\n9yV5Rar7Kg/Mi+9H3J4qrF2TqqcyqYLrsgLnTuaHqe6xHB9KD0n12p9JcmKS38sLoe7UVENoD2g9\n/4+pwmHywky0K1MNtf1Kdj9B0fhzxl97a6rJio7OC0EWAIoTNgHohO2pejFfleq+xx8nuSEvzIw6\nsUdtx9c/TRUw35rkJ0l+K9VQ0x2han2q+ze/kSqQ3T6hrQ8k+V6S/5VqhtWvp+o9bPfcyTycaqKj\nv0s1XPWoVMNi35Qq8N2QagKfHfpb+zanmhn2ySRXjvse7KhnRaohrl9KNUvuZCauzXlZklNa9X8l\n1WzAk/Ve7su6ngBQ1IWpJit4oLUNADNp/JIgAECXaLdn8+eTvDPVEKaTUv0v9fHtFgUAe2HiUFEA\noAu0GzZPTPLtvHBPydpUw5sAYKZ0erjnB1Pdgznx8RczdP0HJ7n+eTN0fQCYFiemuq9lMNWseHek\nmlIdAACA/Vi762w+nOT/SbX49tYk96Sa9GHMSSed1LzvvvvavAwAAABd6r5Uk/69SOn7XK5ItXba\n9eP2NZtNk9ntydDQUIaGhjpdBrOI9xSleU9RmvcUpXlPUZL309TVarVkF9my3Z7NJDkiyY+SHJvk\ndanWBwMAAGA/ViJsfi7VgtXPJfkPqdYNAwAAYD9WImyeXqCN/V69Xu90Ccwy3lOU5j1Fad5TlOY9\nRUneT+2bibXJ3LMJAAAwS03nPZsAAACzwuDgYIaHhztdRlcaGBjI5s2bp3y8nk0AAICWWq0W+WXX\nJvveTNazOWcGagIAAGA/I2wCAABQnLAJAABAccImAAAAxQmbAAAAu9HfP5harTZtj/7+wU6/xGlh\nNloAAICWXc24Ws22Op2ZpjdmwDUbLQAAAB0nbAIAAPSITZs25Q1veEOOOOKILFmyJNdee22SZN26\ndXnNa16TgYGBLFy4MBdccEGee+65sfMuuuiiHHnkkVmwYEFe+cpX5sEHH5z2WoVNAACAHrB9+/ac\nc845Ofnkk7Np06asWbMm11xzTVavXp158+bl4x//eH7yk5/kjjvuyJo1a/LJT34ySfK1r30tt99+\nex555JGMjIzklltuyWGHHTbt9QqbAAAAPeDOO+/Mk08+mUsvvTTz5s3L4sWL8853vjOf+cxncsop\np+S0007LnDlzctxxx2XFihVZu3ZtkuSAAw7I6OhovvOd72T79u054YQTctRRR017vfOm/QoAAAC0\nbcOGDdm0aVMGBgbG9j3//PM5/fTT88gjj+Siiy7K3XffnWeeeSY/+9nPcuqppyZJzjzzzKxcuTLv\nec97smHDhrz+9a/PVVddlb6+vmmtV88mAABADzj22GOzePHiDA8Pjz22bNmS2267Leeff36WLl2a\n733vexkZGcnll1+e7du3j517wQUX5K677spDDz2U9evX58orr5z2eoVNAACAHnDaaaelr68vH/3o\nR7Nt27Y8//zzeeCBB3LnnXfm6aefTl9fX+bPn5+HH34411133Y4lSXLXXXfl29/+dp577rnMnz8/\nBx54YObOnTvt9QqbAAAAu9HXN5BqGcnpeVTt79mcOXNy22235d57782SJUvy0pe+NCtWrMjo6Giu\nuuqqrFq1Kv39/VmxYkWWL18+dt6WLVuyYsWKDA4OZtGiRTn88MNz8cUXt/192ZOdFt6cBs1eWKB0\nbzQajTQajbHter2eJKnX62PbAABA76nVaplt+aWUyb43rR7UnbKlsNkmb0YAAJg9/H0/ub0Nm2aj\nnSX0tgIAAN1Ez2abuvF/PrqxJgAA6AX+lp7c3vZsmiAIAACA4oRNAAAAihM2AQAAKE7YBAAAoDhh\nEwAAgOKETQAAgN3oP7Q/tVpt2h79h/ZPqY5FixZlzZo10/xqy7HOJgAAwG6MjowmQ9PY/tDolI7b\nEU57hZ5NAAAAihM2AQAAesS6devyile8IoODg3n729+eZ599NsPDwzn77LNzxBFHZHBwMOecc04e\nf/zxsXNuuummHH/88env78+SJUuyatWqseduvPHGLF26NIODgznrrLOycePGYrUKmwAAAD2g2Wxm\n1apVWb16db7//e9n/fr1+fCHP5xms5l3vOMd2bhxYzZu3JiDDjooK1euTJJs3bo1F154Yb761a9m\ny5YtueOOO/KqV70qSXLrrbfmIx/5SL74xS/mySefzGtf+9qcd955xeoVNgEAAHpArVbLypUrc/TR\nR2dgYCAf+tCHcvPNN2dwcDCve93rcuCBB+aQQw7JBz/4waxdu3bsvDlz5uT+++/Ptm3bcuSRR2bp\n0qVJkuuvvz6XXHJJTjjhhMyZMyeXXHJJ7r333jz22GNF6hU2AQAAesQxxxwztn3sscdm06ZN2bZt\nW9797ndn0aJFWbBgQc4444yMjIyk2Wzm4IMPzmc/+9lcf/31WbhwYc4+++x897vfTZJs2LAhF154\nYQYGBjIwMJDDDjssSV40BLcdwiYAAECPGH9P5caNG7Nw4cJ87GMfy/r167Nu3bqMjIxk7dq1aTab\naTabSZJly5Zl9erVeeKJJ3LiiSfmXe96V5IqrN5www0ZHh4ee2zdujWvfvWri9QqbAIAAPSAZrOZ\nT3ziE3n88cezefPmXH755Vm+fHlGR0dz0EEHZcGCBdm8eXMuu+yysXN+9KMf5dZbb83WrVtzwAEH\n5OCDD87cuXOTJOeff36uuOKKPPTQQ0mSkZGR3HLLLcXqLbHO5iVJfifJ9iT3J3lbkmcLtAsAANBx\nfQv6prwW5r62PxW1Wi1vfvObs2zZsmzatCnnnntuLr300gwPD+dNb3pTDj/88Bx99NF5//vfny9/\n+ctJku3bt+fqq6/OW97yltRqtZx88sm57rrrkiTnnntunn766SxfvjwbNmzIggULsmzZsrzxjW8s\n8rraXRF0UZJvJnl5qoD52SR/meR/jDumuaP7djaq1WrpttfXjTUBAEAv8Lf05Cb73tRqtWQX2bLd\nns0tSZ5LMj/J861/y9xNCgAAQM9q957NzUk+lmRjkk1JnkryjXaLAgAAoLe127N5fJL3pRpOO5Lk\nliRvTvJn4w8aGhoa267X66nX621eFgAAgE5oNBppNBp7PK7dezZ/O8m/TvLO1te/m+TVSd4z7hj3\nbM6wbqwJAAB6gb+lJ7e392y2O4z24VTh8qBW47+a5KE22wQAAKDHtRs270vy6SR3Jfnb1r4b2mwT\nAACAHtfuMNqpMIx2hnVjTQAA0AsGBwczPDzc6TK60sDAQDZv3rzT/smG0QqbberGYNeNNQEAALPT\ndN2zCQAAADsRNgEAAChO2AQAAKA4YRMAAIDihE0AAACKEzYBAAAoTtgEAACgOGETAACA4oRNAAAA\nihM2AQAAKE7YBAAAoDhhEwAAgOKETQAAAIoTNgEAAChO2AQAAKA4YRMAAIDihE0AAACKEzYBAAAo\nTtgEAACgOGETAACA4oRNAAAAihM2AQAAKE7YBAAAoDhhEwAAgOKETQAAAIoTNgEAAChO2AQAAKA4\nYRMAAIDihE0AAACKEzYBAAAoTtgEAACgOGETAACA4oRNAAAAims3bJ6Q5J5xj5Ek7223KAAAAHpb\nrWBbc5I8nuS0JI+N299sNpsFL9NdarVauu31dWNNAADA7FSr1ZJdZMuSw2h/Ncn38+KgCQAAwH6o\nZNhcnmRVwfYAAADoUfMKtfOSJOck+cCunhwaGhrbrtfrqdfrhS4LAADATGo0Gmk0Gns8rtQ9m/8u\nye8lOWsXz7lnc4Z1Y00AAMDsNN33bJ6X5OZCbQEAANDjSvRsHpxkQ5LFSUZ38byezRnWjTUBAACz\n02Q9myWXPpmMsDnDurEmAABgdpqJpU8AAAAgibAJAADANBA2AQAAKK7UOpsAADNm/BpvjUZjbA1v\n63kDdA8TBLWpGyfj6caaAGC6+NwD6CwTBAEAADBjhE0AAACKEzYBAAAoTtgEAACgOGETAACA4oRN\nAAAAihM2AQAAKE7YBAAAoDhhEwAAgOKETQAAAIoTNgEAAChO2AQAAKA4YRMAAIDihE0AAACKEzYB\nAAAoTtgEAACguHmdLgAA6G6NRiONRmNsu16vJ0nq9frYNgBMVJuBazSbzeYMXKYzarVauu31dWNN\nAMwO3fgZ0401AexParVasotsaRgtAAAAxQmbAAAAFOeeTQAAZpT7gGH/4J7NNnXjfSLdWBMAs0M3\nfsZ0Y01MnZ8f9D73bAIAADBjhE0AAACKEzYBAAAoTtgEAACgOGETAACA4oRNAID/zd7dR1lWl3ei\n/56mMQhUNd2iKAToxtyoeBPBm0XMROXEybCYuzCDcTKDLzfGGIhrhGF0xqUY73D6ToyZREe9edHl\nRPM2QXPNjK8zoxiGzZCJI5KIQRFBL2+Kmphuuo5IvEjX/WOfLoru6u7TnKfq7FP1+ax1Vu9zep9n\nP1V7rzr1rf3bvw1AOWETAACAcsImAAAA5SrC5glJ/iTJF5PckuRZBTUBAACYYZsLarwjyX9J8o9H\n9Y4rqAkAAMAM6034/i1JPpvkjEOss7i4uDjhZrqr1+ula19fF3sCYH3o4mdMF3tifPYfzL5er5es\nkC0nHUa7I8nfJPndJH+Z5N8nOXbCmgAAAMy4SYfRbk7yzCSXJvlMkrcneX2Sf718pcFgsLTc7/fT\n7/cn3CwAAADT0DRNmqY57HqTDqN9YpJPpT3DmSTPThs2L1i2jmG0a6yLPQGwPnTxM6aLPTE++w9m\n38GG0U56ZvMbSe5J8oNJbkvyk0m+MGFNAABYU8vP1DRNszQSz6g8ePQmPbOZJM9I8jtJHpPkK0le\nnmTPsv93ZnONdbEnANaHLn7GdLEnxtfF/dfFnqDLDnZmsyJsHo6wuca62BMA60MXP2O62BPj6+L+\n62JP0GWrNRstAAAAHEDYBAAAoJywCQAAQDlhEwAAgHLCJgAAAOWETQAAAMoJmwAAAJQTNgEAACgn\nbAIAAFBO2AQAAKCcsAkAAEA5YRMAAIBym6fdAAAAwCSapknTNEvL/X4/SdLv95eWWXu9NdjG4uLi\n4hpsZjp6vV669vV1sScA1ocufsZ0sSfG18X918WeGJ/9t/Z6vV6yQrY0jBYAAIBywiYAAADlhE0A\nAADKCZsAAACUEzYBAAAoJ2wCAABQTtgEAACg3OZpN0Br/oT5DPcMy+qN7nUzsbktc1m4b6GkFgAA\nsHHUJJJDW1zPN1Wtumlsr9dLBpP3k6StU1hrPe8/AI5MF2+W3sWeGF8X918Xe2J89t/aG53oOiBb\nGkYLAABAOWETAACAcsImAAAA5YRNAAAAym3I2Wjn57dlONxdVq9q5lcAAID1YkOGzTZoVs1Q1Suq\nJbACAADrh2G0AAAAlBM2AQAAKCdsAgAAUE7YBAAAoJywCQAAQDlhEwAAgHIVtz65M8lCkoeSPJjk\nnIKaAAAAzLCKsLmYpJ9kV0EtAAAA1oGqYbS9ojoAAACsAxVhczHJnya5McnFBfUAAACYcRXDaH88\nydeTPD7JJ5PcmuT65SsMBoOl5X6/n36/X7BZAAAA1lrTNGma5rDrVQ9/vTLJt5O8ddlri4uLi8Wb\nmUyv10t7QrakWlGtXjIoKJO0dQprdW3/ATA9vV6vc58LXeyJ8XVx/3WxJ8Zn/629Nl8dmC0nHUZ7\nbJK50fJxSc5LcvOENQEAAJhxkw6jPSnJB5fV+qMkV09YEwAAgBk3adi8I8lZFY0AAACwflTd+gQA\nAACWVMxGCwAAwDLLZ2xtmmbpjhwb6e4c1bPRrsRstOPWGRSUScxGC8Cq6eIsj13sifF1cf91sSfG\n18X918WeKq3WbLQAAABwAGETAACAcsImAAAA5YRNAAAAygmbAAAAlBM2AQAAKOc+mwCwAczPb8tw\nuLuk1miK+4nNzW3NwsKukloAdI+wCQAbQBs0i+4LXXSv6uFwLW73DcC0GEYLAABAOWETAACAcsIm\nAAAA5YRNAAAAygmbAAAAlBM2AQAAKCdsAgAAUE7YBAAAoJywCQAAQDlhEwAAgHLCJgAAAOWETQAA\nAMoJmwAAAJTbPO0GAIANalPS6/VKSlXVmdsyl4X7FkpqAWx0wiYAMB17kwwK6gyK6iQZDoY1hQAw\njBYAAIB6wiYAAADlhE0AAADKCZsAAACUEzYBAAAoZzZaAACOyPz8tgyHu8vqld26Zm5rFhZ2ldQC\nJidsAgBwRNqguVhUrVdWazisCa1ADcNoAQAAKCdsAgAAUK4qbB6V5LNJPlpUDwAAgBlWFTYvT3JL\n6gbvAwAAMMMqwub3J/nfk/xO2iu8AQAA2OAqZqN9W5LXJpkvqAUAAI/OprrbqJTdjmXLXBbuWyip\nBbNm0rB5QZK/Tnu9Zv9gKw0Gg6Xlfr+ffv+gqwIAwKOzN8mgoM6gqE6S4WBYUwg6pGmaNE1z2PUm\nDZt/L8lPpR1Ge0zas5t/kORnl6+0PGwCAAAwu/Y/gbhz584V15v0ms03JDk1yY4kFyX5b9kvaAIA\nALDxVN9n02y0AAAAlEwQtM91owcAAAAbXPWZTQAAABA2AQAAqCdsAgAAUE7YBAAAoJywCQAAQDlh\nEwAAgHKVtz4BoAOapknTNEvL/X4/SdLv95eWAQBWm7AJrEhgmV3L91Gv11vajwAAa0nYBFYksAAA\nMAnXbAIAAFBO2AQAAKCcsAkAAEA5YRMAAIBywiYAAADlhE0AAADKufUJAAAwVfPz2zIc7i6r1+v1\nJq4xN7c1Cwu7CrrZuIRNAABgqtqguVhUrVdSazicPLBudIbRAgAAUE7YBAAAoJywCQAAQDlhEwAA\ngHLCJgAAAOWETQAAAMoJmwAAAJQTNgEAACgnbAIAAFBO2AQAAKCcsAkAAEA5YRMAAIBywiYAAADl\nhE0AAADKCZsAAACUEzYBAAAoJ2wCAABQbtKweUySTye5KcktSd48cUcAAADMvM0Tvv/vkvxEku+M\nav1ZkmeP/gUAAGCDqhhG+53Rv49JclSSXQU1AQAAmGEVYXNT2mG030xybdrhtAAAAGxgFWFzb5Kz\nknx/kucm6RfUBAAAYIZNes3mcnuS/OckP5KkWf4fg8Fgabnf76ff7xduFgAAgLXSNE2apjnsepOG\nzROTfC/JfUkem+QfJNm5/0rLwyYAAACza/8TiDt3HhABk0weNp+U5PfTDsfdlOQPk1wzYU0AoFOa\nPDxo6dwkg9FyP66eAeBgJg2bNyd5ZkUjAEBX9SNUAnCkKiYIAgAAgEcQNgEAAChXORstABzU8pnr\nmqZZmljALOUAsD4JmwCsieWhstfrjTVlOgAwuwyjBQAAoJwzm9ABhhcCALDeCJvQAYYXAgB0zKb2\n97IqVbXmtsxl4b6FklqrTdgEAADY394kg6Jag7paw8GwptAacM0mAAAA5YRNAAAAygmbAAAAlBM2\nAQAAKCdsAgAAUE7YBAAAoJywCQAAQDlhEwAAgHLCJgAAAOWETQAAAMoJmwAAAJQTNgEAACgnbAIA\nAFBO2AQAAKDc5mk3QJE7ktw5Wj49ybWj5e1JdkyhHwAAYEMTNteLHREqAQCAzjCMFgAAgHLCJgAA\nAOWETQAAAMoJmwAAAJQzQRBAB83Pb8twuLukVq/XK6kzN7c1Cwu7SmoBAOufsAnQQW3QXCyo1Cuq\nkwyHNaEVANgYhE1Yp+ZPmM9wz7CsXsXZsbktc1m4b6GgGwAAuk7YhHVquGeYDIqKDVJSazioC78A\nAHSbCYIAAAAoJ2wCAABQTtgEAACg3KTXbJ6a5A+SPCHtdIfvTvJ/T9oUAACsqTuS3DlaPj3JtaPl\n7Ul2TKEfWAcmDZsPJnl1kpuSHJ/kL5J8MskXJ6wLAABrZ0eESig2adj8xuiRJN9OGzJPjrAJAMBB\nNaNHkpybh6c8748ewHpQeeuT7UnOTvLpwpod1cQPSACAR6sfvzPB+lcVNo9P8idJLk97hvMRBoPB\n0nK/30+/3y/a7LT04wckAACwETVNk6ZpDrteRdg8Osl/TPIfknxopRWWh00AAABm1/4nEHfu3Lni\nepPe+qSX5D1Jbkny9glrAQAAsE5MGjZ/PMlLk/xEks+OHudP2hQAAACzbdJhtH+WyQMrAAAA64yg\nCAAAQDlhEwAAgHKV99kEAFgbdyS5c7R8epJrR8vbk+yYQj8AHEDYBABmz44IlQAdZxgtAAAA5YRN\nAAAAygmbAAAAlBM2AQAAKCdsAgAAUE7YBAAAoJywCQAAQDlhEwAAgHKbp90AADNiU9Lr9crKVdSa\n2zKXhfsWCroBAKoJmwCMZ2+SQVGtQU2t4WA4eREAYFUYRgsAAEA5ZzahwPz8tgyHu8vqVQ5VBACA\naRA2oUAbNBeLqvWKagmsAABMj2G0AAAAlBM2AQAAKCdsAgAAUM41mwAAwIxrRo8kOTcP31+rP3ow\nDcImAAAw4/oRKrvHMFoAAADKCZsAAACUEzYBAAAoJ2wCAABQTtgEAACgnLAJAABAOWETAACAcsIm\nAAAA5YRNAAAAygmbAAAAlBM2AQAAKCdsAgAAUE7YBAAAoFxF2Hxvkm8mubmgFgAAAOtARdj83STn\nF9QBAABgnagIm9cn2V1QBwAAgHXCNZsAAACU27wWGxkMBkvL/X4//X5/LTYLAABAsaZp0jTNYddb\n87AJAADA7Nr/BOLOnTtXXM8wWgAAAMpVhM33JfnzJD+Y5J4kLy+oCQAAwAyrGEb7ooIaAAAArCOG\n0QIAAFBO2AQAAKCcsAkAAEA5YRMAAIBywiYAAADlhE0AAADKVdz6BIBOaUaPJDk3yWC03B89AABW\nn7AJrOyOJHeOlk9Pcu1oeXuSHVPohyPQj1AJAEybsAmsbEeESgAAHjXXbAIAAFDOmU0AAIBqLkkS\nNgEAAMq5JMkwWgAAAOoJmwAAAJQTNgEAACgnbAIAAFBO2AQAAKCcsAkAAEA5YRMAAIBywiYAAADl\nhE0AAADKCZsAAACU2zztBgDYIO5Icudo+fQk146WtyfZMYV+AIBVJWwCsDZ2RKgEgA1E2IROaEaP\nJDk3yWC03B89AABgtgib0An9CJUAAKwnJggCAACgnLAJAABAOWETAACAcsImAAAA5YRNAAAAygmb\nAAAAlBM2AQAAKCdsAgAAUE7YBAAAoFxF2Dw/ya1Jbk/yuoJ6AAAAzLhJw+ZRSX4zbeA8M8mLkjxt\n0qYAAACYbZOGzXOSfDnJnUkeTPL+JP9owpoAAADMuEnD5ilJ7ln2/Kuj1wAAANjAehO+/4Vph9Be\nPHr+0iQ/muSyZevclOQZE24HAACAbvpckrP2f3HzhEW/luTUZc9PTXt2c7kDNgoAAACHsjnJV5Js\nT/KYtGcxTRAEAADAxP5hki+lnSjoiin3AgAAAAB01NOS/P0kx+/3+vlT6AUA1tJzkvzLJOdNuxF4\nNJ6W5PVJfmP0eF0MP2Z1vHzaDTCT/nnaESsfSnJXkguX/d9np9IR68Gz096TO0n6Sf5V2j9oQJU/\nmHYDzKwbli1fnPbSwCuT/I8YucmMeV3aA/j1aWfvfWnag/imOJipd8/hV4EDfD4Pn9HcnuTGJP9i\n9FzY5NF4c5L/meQzSX5ttPx/JvnvSV47xb6YXR9N8pHRv/se9y97HY7E8s+2G5M8frR8XNrPRJgZ\ntyc5eoXXH5P2ulc4Ujcf4vHdKfbF7PrCfs+PT/KJJG9L+4cxOFK3pJ1U8NgkwyRbRq8/NslfTasp\nZtpnk/xRkp9Icm7as+VfHy2fO722mFF/lWRbksflwD+q+txjptya9kzB/ranHbYGR+qbSc5Oewzt\n/8N4ZvkAACAASURBVLh3Oi0x467NgbetOjrtELW9a98O68BNB1le6TmM46gkr0nyp2k/A5Pkjum1\nw4y7M+3xc0eS/zfJk0avz8XPKGbM+WnPYH48yb8fPT6e9hYy/3CKfTG73pv2QvaVvG8tG2HdODXJ\nE1d4vZf2ujs4Up9Oe1YzSTYte/2EJH+59u2wjnx/kg8k+a24dIR6xybZMe0mZllv2g1sUEclOSfJ\nKUkWk3wt7fjw702zKQBYJcck+bsVXj8x7RmEm9e2HdahC5L8vSRvmHYjAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAMBu2J9mbZNOU+3g0Bkn+cIrbf0GSe5IMkzzjMOu+JMknVr0jAACAjtiemrB5Z5Ln\nreH2kuTKTDdsfiXJ86e4fQA2oFn86zAATGIxSe8I1j+SdVezxlETbPu0JLcU9LC5oAYAG4SwCcC0\nvC7JV5MsJLk17dnGXpLXJ/lykm8l+eMkWw/y/i1J3pPk3lGdf5NHfq5dnDZgLST5QpKz055dPC3J\nR9MOKf1Xh+jvv4/+vW+07o8meXKS/zbq7W+S/IdRH4f6mvZ3dJL3JfmT0fLBDEbr/GGSPUlelmRH\nkutG9a9O8ps59BnT7xv1flSSzyW5ffT6vu/xvu/Nhcve83NJrl/2fG+SfzZ675cOsS0AAICpe0qS\nu5M8cfT8tCRnJLk8yZ8nOTltEHtXkqtG62zPI4e1fjDJO5M8Nsnjk3w6ySWj//uZtKHvfxs9f/Jo\nG0lyR8YbRnt6DhxG++Qkf3/U24lpg9/bDvM1JQ9fs3lMkv+c5L05/NnOQZL/L8lPjZ4fk+RTSd4y\n2v5z0obFPxjja9m7rJck+cfL+vwnSb6d5KTR85/LgWHzE0lOSBteAQAAOusHknwzDwe3fW7JI4Pg\nk9IGrk15ZNg8KcnfpQ1g+7wo7VnHpA1Hlx1k2+OGzeXbO5gLk/zlaPlgX1PSXrP54bTh9O1jbDtp\nw2az7PlpSR5MG673+aOMdy3o/mFzf5/Nw6H253Jg2OyPsQ0AeATXXgAwDV9O8i/SBqqnpw2H/zJt\nwPtg2oCzz/fy8Fm3fU5PG+i+vuy1TWnPLCbJ96edFKfaSUnekeTZSeZG29w1+r+VvqbXjHrsJXlW\n2s/di45ge19dtnxykt1JHlj22l1JTj3CryFJfjbJq9N+v5Pk+CSPO8T69zyKbQCwwblmE4BpeV/a\noaCnp52059+mDYvnp71Oc9/j2DwyVCZt+Plu2oC0b70tSX5o2f//wEG2uzhmfyut9ytJHkryv462\n93/kkZ+lK31N+1yd5FeTXJPkCWNuf3kPX8/D3499Th+jzv5OT/LuJK9Ksm1U8/M59LDecb9nALBE\n2ARgGn4w7VDW70sbGv8u7RnMd6UNdPuur3x8Hh7eudzX04a3f5eHzzA+OclzR///O2kn/3lm2hD1\nA8tqfnO07uH8TdozrMvXPT7J/WmvlTwlyWsP8zU9tF/NX097Deo1OfSZxOTA8HdXkhuT7Ex7VvfZ\nSS7IkQfB40bv+Vba79vL04ZnACglbAIwDd+X5M1pA93X0062c0XaIaofSRskF9JOiHPOsvctD1Y/\nm+Qxaa/z3JXkA3l40ps/SfKmtMFuIcl/ysOz2r45yRvTDkl9zSF6/M6oxv8Y1T8nbdB7ZtrZYT+a\n5D8u6+lgX9O+vvet98tJPpTkT9NOunMw+5/ZTJIXp50Vd1eSf512cqBxbquyvM4tSd6a9nv7jbRB\n888OsV1nNQFYVacmuTbt9OifT/LPR69vS/LJJLel/cXgUB+aAECtKzPeBEEAsObGPbP5YNqJBJ6e\ndoKDVyV5Wtr7dH0y7dCha0bPAYC1Mc5ZTQCYKR9K8pNpb1i9b4bAJ46eA8CseEmS4QqPm9do+//1\nINsf94+3V6YdSvvig9RZq68DAEpsTztJwVza61326e33HAAAgA3qSO+zeXzayRAuT/sX0+VWmsgg\nz3jGMxY/97nPPbruAAAA6LrPJTlr/xeP5FqPo5N8LO2Qn7ePXrs1ST/tbHZPSjuJ0FP3e9/i4qKJ\n7A5nMBhkMBhMuw3WEccU1RxTVJvkmGqaJk3TLC33+/0kSb/fX1pm4/FzikqOp/H1er1khWw57pnN\nXpL3pJ0u/e3LXv9IkpelvWn1y9JeywkAsKqWh8per7cUPAHojnHD5o8neWmSv0ry2dFrVyT51ST/\nT5JXJLkzyT8p7g8AAIAZNG7Y/LMc/DYpP1nUy4ZmyA/VHFNUc0xRzTFFNccUlRxPk1uL+3O5ZhMA\nWDW9Xi9+1wCYnkmv2QQAAFj3tm3blt273dFxJVu3bs2uXbvGXt+ZTQBgpjmzCVTyM+XgDva9OdiZ\nzYNdhwkAAACPmrAJAABAOddsAgCH1DTN0n0sm6ZZmqFx+b0uAWB/rtkEAMbWxWuZutgTMLv8TDk4\n12wCAAAUmp/fll6vt2qP+flt0/4SV4UzmwDA2Lr4F/8u9gTMrpV+prRn7lbz58xs/BxzZhMAAGCd\nuvfee/PCF74wT3jCE3LGGWfkN37jN5IkN9xwQ37sx34sW7duzcknn5zLLrssDz744NL7Xv3qV+ek\nk07Kli1b8sM//MP5whe+sOq9CpsAAAAzYO/evXn+85+fs88+O/fee2+uueaavP3tb8/VV1+dzZs3\n5x3veEf+9m//Np/61KdyzTXX5Ld/+7eTJJ/4xCdy/fXX5/bbb8+ePXvygQ98II973ONWvV9hEwAA\nYAZ85jOfybe+9a288Y1vzObNm7Njx478wi/8Qt7//vfnmc98Zs4555xs2rQpp59+ei655JJcd911\nSZKjjz46w+EwX/ziF7N379485SlPyROf+MRV79etTwAAAGbAXXfdlXvvvTdbt25deu2hhx7Kc5/7\n3Nx+++159atfnb/4i7/Id77znXzve9/Lj/zIjyRJnve85+XSSy/Nq171qtx111356Z/+6bzlLW/J\n3NzcqvbrzCYAAMAMOO2007Jjx47s3r176bGwsJCPfexjeeUrX5kzzzwzX/7yl7Nnz5686U1vyt69\ne5fee9lll+XGG2/MLbfckttuuy2//uu/vur9CpsAAAAz4Jxzzsnc3Fx+7dd+LQ888EAeeuihfP7z\nn89nPvOZfPvb387c3FyOPfbY3HrrrXnnO9+5b5bY3Hjjjfn0pz+dBx98MMcee2yOOeaYHHXUUave\nr7AJAABwCHNzW9Pe2WN1Hm39w9u0aVM+9rGP5aabbsoZZ5yRxz/+8bnkkksyHA7zlre8JVdddVXm\n5+dzySWX5KKLLlp638LCQi655JJs27Yt27dvz4knnpjXvva1E39fDsd9NgGAsXXxnpZd7AmYXX6m\nHJz7bAIAADB1wiYAAADlhE0AAADKCZsAAACUEzYBAAAoJ2wCAABQTtgEAACgnLAJAABAOWETAABg\nBmzfvj3XXHPNtNsYm7AJAABwCPMnzKfX663aY/6E+bH62Lf+rNg87QYAAAC6bLhnmAxWsf5guHrF\np8iZTQAAgBlxww035OlPf3q2bduWn//5n893v/vd7N69OxdccEGe8IQnZNu2bXn+85+fr33ta0vv\n+b3f+708+clPzvz8fM4444xcddVVS//33ve+N2eeeWa2bduW888/P3fffXdZr8ImAADADFhcXMxV\nV12Vq6++Ol/5yldy22235Zd/+ZezuLiYV7ziFbn77rtz991357GPfWwuvfTSJMn999+fyy+/PB//\n+MezsLCQT33qUznrrLOSJB/+8Ifz5je/OR/84AfzrW99K895znPyohe9qKxfYRMAAGAG9Hq9XHrp\npTnllFOydevW/NIv/VLe9773Zdu2bXnBC16QY445Jscff3ze8IY35Lrrrlt636ZNm3LzzTfngQce\nyEknnZQzzzwzSfKud70rV1xxRZ7ylKdk06ZNueKKK3LTTTflnnvuKelX2AQAAJgRp5566tLyaaed\nlnvvvTcPPPBAfvEXfzHbt2/Pli1bcu6552bPnj1ZXFzMcccdlz/+4z/Ou971rpx88sm54IIL8qUv\nfSlJctddd+Xyyy/P1q1bs3Xr1jzucY9LkkcMwZ2EsAkAADAjll9Teffdd+fkk0/OW9/61tx22225\n4YYbsmfPnlx33XVZXFzM4uJikuS8887L1VdfnW984xt56lOfmosvvjhJG1bf/e53Z/fu3UuP+++/\nP8961rNKehU2AQAAZsDi4mJ+67d+K1/72teya9euvOlNb8pFF12U4XCYxz72sdmyZUt27dqVnTt3\nLr3nr//6r/PhD384999/f44++ugcd9xxOeqoo5Ikr3zlK/Mrv/IrueWWW5Ike/bsyQc+8IGyft36\nBAAA4BDmtsyt6u1J5rbMjbVer9fLS17ykpx33nm59957c+GFF+aNb3xjdu/enRe/+MU58cQTc8op\np+Q1r3lNPvKRjyRJ9u7dm7e97W152ctell6vl7PPPjvvfOc7kyQXXnhhvv3tb+eiiy7KXXfdlS1b\ntuS8887Lz/zMz5R8XWtxR9DFfadvAYDZ1uv10rXP9S72BMwuP1MO7mDfm16vl6yQLQ2jBQAAoJyw\n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\n", 765 "text/plain": [ 766 "<matplotlib.figure.Figure at 0x7f086d8887d0>" 767 ] 768 }, 769 "metadata": {}, 770 "output_type": "display_data" 771 } 772 ], 773 "source": [ 774 "def plot_all_functions(df):\n", 775 " functions = df.index.get_level_values(2).unique()\n", 776 " fcount = len(functions)\n", 777 "\n", 778 " fig, pltaxes = plt.subplots(fcount, 1, figsize=(16, 8*fcount))\n", 779 "\n", 780 " fig_id = 0\n", 781 " for fname in functions:\n", 782 " logging.info(\"Plotting stats for [%s] function\", fname)\n", 783 " if fcount > 1:\n", 784 " axes = pltaxes[fig_id]\n", 785 " else:\n", 786 " axes = pltaxes\n", 787 " plot_stats(df, fname, axes)\n", 788 " fig_id = fig_id + 1\n", 789 " \n", 790 "plot_all_functions(stats_df)" 791 ] 792 } 793 ], 794 "metadata": { 795 "kernelspec": { 796 "display_name": "Python 2", 797 "language": "python", 798 "name": "python2" 799 }, 800 "language_info": { 801 "codemirror_mode": { 802 "name": "ipython", 803 "version": 2 804 }, 805 "file_extension": ".py", 806 "mimetype": "text/x-python", 807 "name": "python", 808 "nbconvert_exporter": "python", 809 "pygments_lexer": "ipython2", 810 "version": "2.7.6" 811 } 812 }, 813 "nbformat": 4, 814 "nbformat_minor": 0 815 } 816