• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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