diff --git a/ipynb/examples/trace_analysis/TraceAnalysis_TasksLatencies.ipynb b/ipynb/examples/trace_analysis/TraceAnalysis_TasksLatencies.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..d1e5a250f5dd466f4c7ff088e42fbeaf9f3b396c --- /dev/null +++ b/ipynb/examples/trace_analysis/TraceAnalysis_TasksLatencies.ipynb @@ -0,0 +1,1128 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Trace Analysis Examples\n", + "
\n", + "Tasks Latencies\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Import Required Modules" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "run_control": { + "marked": false + } + }, + "outputs": [], + "source": [ + "import logging\n", + "reload(logging)\n", + "logging.basicConfig(\n", + " format='%(asctime)-9s %(levelname)-8s: %(message)s',\n", + " datefmt='%I:%M:%S')\n", + "\n", + "# Enable logging at INFO level\n", + "logging.getLogger().setLevel(logging.INFO)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "run_control": { + "marked": false + } + }, + "outputs": [], + "source": [ + "# Generate plots inline\n", + "%matplotlib inline\n", + "\n", + "import json\n", + "import os\n", + "\n", + "# Support to access the remote target\n", + "import devlib\n", + "from env import TestEnv\n", + "\n", + "# Support for workload generation\n", + "from wlgen import RTA, Ramp\n", + "\n", + "# Support for trace analysis\n", + "from trace import Trace\n", + "from trace_analysis import TraceAnalysis\n", + "\n", + "# Support for plotting\n", + "import numpy\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import trappy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Target Configuration" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false, + "run_control": { + "marked": false + } + }, + "outputs": [], + "source": [ + "# Setup target configuration\n", + "my_conf = {\n", + "\n", + " # Target platform and board\n", + " \"platform\" : 'linux',\n", + " \"board\" : 'juno',\n", + " \"host\" : '192.168.0.1',\n", + "\n", + " # Folder where all the results will be collected\n", + " \"results_dir\" : \"TraceAnalysis_TaskLatencies\",\n", + "\n", + " # Define devlib modules to load\n", + " \"exclude_modules\" : [ 'hwmon' ],\n", + "\n", + " # FTrace events to collect for all the tests configuration which have\n", + " # the \"ftrace\" flag enabled\n", + " \"ftrace\" : {\n", + " \"events\" : [\n", + " \"sched_switch\",\n", + " \"sched_wakeup\",\n", + " \"sched_load_avg_cpu\",\n", + " \"sched_load_avg_task\",\n", + " ],\n", + " \n", + " \"buffsize\" : 100 * 1024,\n", + " },\n", + "\n", + " # Tools required by the experiments\n", + " \"tools\" : [ 'trace-cmd', 'rt-app' ],\n", + " \n", + " # Comment this line to calibrate RTApp in your own platform\n", + " \"rtapp-calib\" : {\"0\": 360, \"1\": 142, \"2\": 138, \"3\": 352, \"4\": 352, \"5\": 353},\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:23:42 INFO : Target - Using base path: /home/derkling/Code/lisa\n", + "10:23:42 INFO : Target - Loading custom (inline) target configuration\n", + "10:23:42 INFO : Target - Devlib modules to load: ['bl', 'cpufreq']\n", + "10:23:42 INFO : Target - Connecting linux target:\n", + "10:23:42 INFO : Target - username : root\n", + "10:23:42 INFO : Target - host : 192.168.0.1\n", + "10:23:42 INFO : Target - password : \n", + "10:23:42 INFO : Target - Connection settings:\n", + "10:23:42 INFO : Target - {'username': 'root', 'host': '192.168.0.1', 'password': ''}\n", + "10:23:46 INFO : Target - Initializing target workdir:\n", + "10:23:46 INFO : Target - /root/devlib-target\n", + "10:23:50 INFO : Target - Topology:\n", + "10:23:50 INFO : Target - [[0, 3, 4, 5], [1, 2]]\n", + "10:23:52 INFO : Platform - Loading default EM:\n", + "10:23:52 INFO : Platform - /home/derkling/Code/lisa/libs/utils/platforms/juno.json\n", + "10:23:53 INFO : FTrace - Enabled tracepoints:\n", + "10:23:53 INFO : FTrace - sched_switch\n", + "10:23:53 INFO : FTrace - sched_wakeup\n", + "10:23:53 INFO : FTrace - sched_load_avg_cpu\n", + "10:23:53 INFO : FTrace - sched_load_avg_task\n", + "10:23:53 WARNING : Target - Using configuration provided RTApp calibration\n", + "10:23:53 INFO : Target - Using RT-App calibration values:\n", + "10:23:53 INFO : Target - {\"0\": 360, \"1\": 142, \"2\": 138, \"3\": 352, \"4\": 352, \"5\": 353}\n", + "10:23:53 INFO : EnergyMeter - HWMON module not enabled\n", + "10:23:53 WARNING : EnergyMeter - Energy sampling disabled by configuration\n", + "10:23:53 INFO : TestEnv - Set results folder to:\n", + "10:23:53 INFO : TestEnv - /home/derkling/Code/lisa/results/TraceAnalysis_TaskLatencies\n", + "10:23:53 INFO : TestEnv - Experiment results available also in:\n", + "10:23:53 INFO : TestEnv - /home/derkling/Code/lisa/results_latest\n" + ] + } + ], + "source": [ + "# Initialize a test environment using:\n", + "te = TestEnv(my_conf, wipe=False, force_new=True)\n", + "target = te.target" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Workload Execution" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def experiment(te):\n", + "\n", + " # Create and RTApp RAMP task\n", + " rtapp = RTA(te.target, 'ramp', calibration=te.calibration())\n", + " rtapp.conf(kind='profile',\n", + " params={\n", + " 'ramp' : Ramp(\n", + " start_pct = 60,\n", + " end_pct = 20,\n", + " delta_pct = 5,\n", + " time_s = 0.5).get()\n", + " })\n", + "\n", + " # FTrace the execution of this workload\n", + " te.ftrace.start()\n", + " rtapp.run(out_dir=te.res_dir)\n", + " te.ftrace.stop()\n", + "\n", + " # Collect and keep track of the trace\n", + " trace_file = os.path.join(te.res_dir, 'trace.dat')\n", + " te.ftrace.get_trace(trace_file)\n", + " \n", + " # Collect and keep track of the Kernel Functions performance data\n", + " stats_file = os.path.join(te.res_dir, 'trace.stats')\n", + " te.ftrace.get_stats(stats_file)\n", + "\n", + " # Dump platform descriptor\n", + " te.platform_dump(te.res_dir)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:23:53 INFO : WlGen - Setup new workload ramp\n", + "10:23:53 INFO : RTApp - Workload duration defined by longest task\n", + "10:23:53 INFO : RTApp - Default policy: SCHED_OTHER\n", + "10:23:53 INFO : RTApp - ------------------------\n", + "10:23:53 INFO : RTApp - task [ramp], sched: using default policy\n", + "10:23:53 INFO : RTApp - | calibration CPU: 1\n", + "10:23:53 INFO : RTApp - | loops count: 1\n", + "10:23:53 INFO : RTApp - + phase_000001: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 60 %\n", + "10:23:53 INFO : RTApp - | run_time 60000 [us], sleep_time 40000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000002: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 55 %\n", + "10:23:53 INFO : RTApp - | run_time 55000 [us], sleep_time 45000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000003: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 50 %\n", + "10:23:53 INFO : RTApp - | run_time 50000 [us], sleep_time 50000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000004: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 45 %\n", + "10:23:53 INFO : RTApp - | run_time 45000 [us], sleep_time 55000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000005: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 40 %\n", + "10:23:53 INFO : RTApp - | run_time 40000 [us], sleep_time 60000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000006: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 35 %\n", + "10:23:53 INFO : RTApp - | run_time 35000 [us], sleep_time 65000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000007: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 30 %\n", + "10:23:53 INFO : RTApp - | run_time 30000 [us], sleep_time 70000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000008: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 25 %\n", + "10:23:53 INFO : RTApp - | run_time 25000 [us], sleep_time 75000 [us]\n", + "10:23:53 INFO : RTApp - + phase_000009: duration 0.500000 [s] (5 loops)\n", + "10:23:53 INFO : RTApp - | period 100000 [us], duty_cycle 20 %\n", + "10:23:53 INFO : RTApp - | run_time 20000 [us], sleep_time 80000 [us]\n", + "10:23:57 INFO : WlGen - Workload execution START:\n", + "10:23:57 INFO : WlGen - /root/devlib-target/bin/rt-app /root/devlib-target/ramp_00.json 2>&1\n" + ] + } + ], + "source": [ + "experiment(te)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Parse Trace and Profiling Data" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false, + "run_control": { + "marked": false + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:24:05 INFO : Content of the output folder /home/derkling/Code/lisa/results/TraceAnalysis_TaskLatencies\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[01;34m/home/derkling/Code/lisa/results/TraceAnalysis_TaskLatencies\u001b[00m\r\n", + "├── output.log\r\n", + "├── platform.json\r\n", + "├── ramp_00.json\r\n", + "├── rt-app-ramp-0.log\r\n", + "├── \u001b[01;35mtask_latencies_1236_1236__ramp,_rt-app.png\u001b[00m\r\n", + "├── \u001b[01;35mtask_latencies_1295_1295__ramp,_rt-app.png\u001b[00m\r\n", + "├── \u001b[01;35mtask_latencies_1644_1644__ramp,_rt-app.png\u001b[00m\r\n", + "├── trace.dat\r\n", + "├── trace.raw.txt\r\n", + "└── trace.txt\r\n", + "\r\n", + "0 directories, 10 files\r\n" + ] + } + ], + "source": [ + "# Base folder where tests folder are located\n", + "res_dir = te.res_dir\n", + "logging.info('Content of the output folder %s', res_dir)\n", + "!tree {res_dir}" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false, + "run_control": { + "marked": false + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:24:05 INFO : LITTLE cluster max capacity: 447\n" + ] + } + ], + "source": [ + "with open(os.path.join(res_dir, 'platform.json'), 'r') as fh:\n", + " platform = json.load(fh)\n", + "#print json.dumps(platform, indent=4)\n", + "logging.info('LITTLE cluster max capacity: %d',\n", + " platform['nrg_model']['little']['cpu']['cap_max'])" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false, + "run_control": { + "marked": false + } + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:24:05 INFO : Parsing FTrace format...\n", + "10:24:06 INFO : Collected events spans a 6.641 [s] time interval\n", + "10:24:06 INFO : Set plots time range to (0.000000, 6.641493)[s]\n", + "10:24:06 INFO : Registering trace analysis modules:\n", + "10:24:06 WARNING : No performance data found in:\n", + "10:24:06 WARNING : /home/derkling/Code/lisa/results/TraceAnalysis_TaskLatencies\n", + "10:24:06 INFO : perf\n", + "10:24:06 INFO : latency\n", + "10:24:06 INFO : eas\n", + "10:24:06 INFO : tasks\n", + "10:24:06 INFO : cpus\n", + "10:24:06 INFO : functions\n", + "10:24:06 INFO : status\n", + "10:24:06 INFO : frequency\n" + ] + } + ], + "source": [ + "trace_file = os.path.join(res_dir, 'trace.dat')\n", + "trace = Trace(platform, trace_file, events=my_conf['ftrace']['events'])" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": true + }, + "source": [ + "# Trace visualization" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "run_control": { + "marked": false + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "
\n", + "\n", + "\n", + "\n", + " \n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "trappy.plotter.plot_trace(trace.ftrace)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Latency DataFrames" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:24:06 WARNING : The [sched_switch] events contain 'prev_state' value [4096.0]\n", + "10:24:06 WARNING : The [sched_switch] events contain 'prev_state' value [1.0]\n", + "10:24:06 WARNING : The [sched_switch] events contain 'prev_state' value [0.0]\n", + "10:24:06 WARNING : The [sched_switch] events contain 'prev_state' value [64.0]\n", + "10:24:06 WARNING : which are not currently mapped into a task state.\n", + "10:24:06 WARNING : Check mappings in:\n", + "10:24:06 WARNING : /home/derkling/Code/lisa/libs/utils/analysis/latency_analysis.py::LatencyAnalysis _taskState()\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
target_cpu__cpucurr_statenext_statet_startt_delta
Time
1.046629NaN2A40961.0466290.000035
1.046664NaN24096A1.0466640.000020
1.046684NaN2A40961.0466840.000039
1.046723NaN24096A1.0467230.000033
1.046756NaN2A11.0467560.059737
\n", + "
" + ], + "text/plain": [ + " target_cpu __cpu curr_state next_state t_start t_delta\n", + "Time \n", + "1.046629 NaN 2 A 4096 1.046629 0.000035\n", + "1.046664 NaN 2 4096 A 1.046664 0.000020\n", + "1.046684 NaN 2 A 4096 1.046684 0.000039\n", + "1.046723 NaN 2 4096 A 1.046723 0.000033\n", + "1.046756 NaN 2 A 1 1.046756 0.059737" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Report full set of task status informations available from the trace\n", + "trace.data_frame.latency_df('ramp').head()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
__comm__cpu__pidnext_commnext_pidnext_prioprev_commprev_pidprev_prioprev_state
Time
0.000003<idle>20sudo1415120swapper/201200
0.000004trace-cmd11416swapper/10120trace-cmd141612064
0.000875<idle>10sh1379120swapper/101200
0.000877sudo21415swapper/20120sudo141512064
0.001094<idle>20kworker/u12:01320120swapper/201200
\n", + "
" + ], + "text/plain": [ + " __comm __cpu __pid next_comm next_pid next_prio \\\n", + "Time \n", + "0.000003 2 0 sudo 1415 120 \n", + "0.000004 trace-cmd 1 1416 swapper/1 0 120 \n", + "0.000875 1 0 sh 1379 120 \n", + "0.000877 sudo 2 1415 swapper/2 0 120 \n", + "0.001094 2 0 kworker/u12:0 1320 120 \n", + "\n", + " prev_comm prev_pid prev_prio prev_state \n", + "Time \n", + "0.000003 swapper/2 0 120 0 \n", + "0.000004 trace-cmd 1416 120 64 \n", + "0.000875 swapper/1 0 120 0 \n", + "0.000877 sudo 1415 120 64 \n", + "0.001094 swapper/2 0 120 0 " + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = trace.data_frame.trace_event('sched_switch')\n", + "df.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
wakeup_latency
Time
1.1470420.000251
1.2467610.000007
1.3469920.000013
1.4470480.000016
1.5470640.000022
\n", + "
" + ], + "text/plain": [ + " wakeup_latency\n", + "Time \n", + "1.147042 0.000251\n", + "1.246761 0.000007\n", + "1.346992 0.000013\n", + "1.447048 0.000016\n", + "1.547064 0.000022" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Report WAKEUP events and their duration\n", + "trace.data_frame.latency_wakeup_df('ramp').head()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
preempt_latency
Time
1.3494510.000167
1.4494590.000027
3.4494620.000023
4.4494620.000033
5.4494600.000028
\n", + "
" + ], + "text/plain": [ + " preempt_latency\n", + "Time \n", + "1.349451 0.000167\n", + "1.449459 0.000027\n", + "3.449462 0.000023\n", + "4.449462 0.000033\n", + "5.449460 0.000028" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Report PREEMPTION events and their duration\n", + "trace.data_frame.latency_preemption_df('ramp').head()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Latency Plots" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:24:07 WARNING : The [sched_switch] events contain 'prev_state' value [4096.0]\n", + "10:24:07 WARNING : The [sched_switch] events contain 'prev_state' value [1.0]\n", + "10:24:07 WARNING : The [sched_switch] events contain 'prev_state' value [0.0]\n", + "10:24:07 WARNING : The [sched_switch] events contain 'prev_state' value [64.0]\n", + "10:24:07 WARNING : which are not currently mapped into a task state.\n", + "10:24:07 WARNING : Check mappings in:\n", + "10:24:07 WARNING : /home/derkling/Code/lisa/libs/utils/analysis/latency_analysis.py::LatencyAnalysis _taskState()\n", + "10:24:07 INFO : Found: 45 WAKEUP latencies\n", + "10:24:07 INFO : Found: 5 PREEMPT latencies\n", + "10:24:07 INFO : Total: 50 latency events\n", + "10:24:07 WARNING : Event [sched_overutilized] not found, plot DISABLED!\n" + ] + }, + { + "data": { + "image/png": "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\nAgAAAABKQUIKAAAAACgFCSkAAAAAoBQkpAAAAACAUpCQAgAAAABKQUIKAAAAAChFJRLSWq2mer1e\ndhgAAAAAgA6p1+uq1WqDjuOIGJ1oWgVgR9kxAAAAAAC6w7Yiws2GVaKGFAAAAAAw/pCQAgAAAABK\nQUIKAAAAACgFCSkAAAAAoBQkpAAAAACAUpCQAgAAAABKQUIKAAAAACgFCSkAAAAAoBQkpAAAAACA\nUpCQAgAAAABKQUIKAAAAACgFCSkAAAAAoBQTyw4AADB6bJcdAlApEVF2CAAwrpGQAsA4wwk4kHCB\nBgDKV4kmu7VaTfV6vewwAAAAAAAdUq/XVavVBh3HZV8ptx1lxwAA44VtakiBjN8DAIyOvL9t2iyl\nEjWkAAAAAIDxh4QUAAAAAFAKElIAwJhQq9V00EEHlR0GAAAYBhJSAMCYQI+p6HfmmWfqNa95Tdlh\nAADaQEIKABjQiQ7Py+o0fcx3TlPxlfPss892bdoAgLGLhBQAMKCsnOeMM87QnnvuOfB+s8020zvf\n+c6B91OmTNH111+vD3/4w5o6dapWX311bbfddvrDH/7QdHqLFi3Sfvvtp7e//e1atGiR5s6dq7e9\n7W1ad911tckmm+jkk08eGPeQQw7R5z73uUL8dU2ZMmXg/bRp0/SlL31JW221ldZaay29+93v1tNP\nPz38hRypklZOq+Wv1+vacMMN9ZWvfEXrr7++DjvsMEWEvvSlL+nFL36x1l57be2zzz5asGDBwLSu\nuuoqvfrVr9aaa66pbbbZRpdddtnAsL6+Pn3uc5/TTjvtpEmTJmnPPffUQw89pAMOOECrr766tt9+\ne91zzz0D40+YMEEnn3yyNt10U62zzjr65Cc/qYjQLbfcog984AO68sorNWnSJK211lojKjIAQHeR\nkAIAStfX16fLL79ckjR37lwtWrRIV111lSTpH//4h/71r3/p5S9/ubbffntdf/31WrBggfbff3+9\n4x3v0DPPPLPEtJ566intvffeWnnllXXBBRdoueWW05vf/GZtu+22mjt3rn7729/qxBNP1CWXXCIp\nNfUdqrnvD37wA11yySW68847ddttt+nYY4/tQilUV7Plt6158+ZpwYIFmj17tk499VSddNJJuuii\ni/T73/9e999/v9Zcc0198IMflCTNmTNHe+yxh4466igtWLBAxx9/vN72trfp4YcfHpjP+eefr3PP\nPVdz5szRnXfeqR133FGHHXaY5s+fry222EIzZ85cIq4LL7xQf/nLX/TXv/5VP/vZz3T66adriy22\n0Le//W3tuOOOWrhwoebPnz+qZQUAGJ6JZQcAAChXvb644qx4vt/Xl/5GYxobb7yxJk2apGuvvVa3\n3nqrdt99d11//fW69dZbdcUVV+i1r32tJOmAAw4Y+M5HP/pRHXvssbr11lu19dZby7Yee+wx7b77\n7tp222114oknSpKuvvpqPfTQQ/rsZz87MK/3vOc9mjVrlnbbbTdJgzf3ta0PfehD2mCDDSRJRx55\npA4//HAdc8wxbZXNiFRg5bRa/l133VUTJkzQzJkztfzyy2v55ZfXqaeeqlNOOUWTJ0+WJB199NHa\naKONdM455+jcc8/VG9/4Rs2YMUOStOuuu2q77bbTL37xCx188MGyrUMPPVQbb7yxJOkNb3iDbrnl\nFu28886SpHe84x1L1GRL0qc+9SmtscYaWmONNfSRj3xE55133kBNLQCgN5CQAsA415iX1GrlTGP6\n9Omq1+u64447NH36dK2xxhq67LLLdOWVV2r69OmSpOOPP16nn3665s6dO5CAPvTQQ5JSUnnVVVfp\n2Wef1axZswame88992ju3Llac801Bz577rnnBpLcdhSb8E6dOlVz584d/gIui4qsnFbLv84662iF\nFVYYGHb33XfrLW95iyZMWNwAa+LEiZo3b57uueceXXDBBbr44osHhj377LMDCackvehFLxp4vdJK\nK2nddddd4v3jjz/eVlwAgN5BQgoAqITp06froosu0t13360jjzxSa6yxhs4991xdddVVOvzww3X5\n5Zfrq1/9qn73u99pq622kiSttdZaA7VhtrXbbrvpZS97mXbZZRfV63Wtu+66mjp1qjbeeGPddttt\nTee7yiqr6Iknnhh4/8ADDyw1zuzZs5d43V8DOF60Wv7Gps5Tp07VGWecoR133HGpaUydOlUHHXSQ\nvvOd77Q1z3Z6TZ49e7a22GKLgdf9tbj0uAwAvYN7SAEAA9ptBdqNaUyfPl2XXnqpnnrqKU2ePFn/\n/u//rl//+teaP3++tt12Wy1cuFATJ07U2muvrWeeeUaf//zn9dhjjw18vz8x/cQnPqH9999fu+yy\nix5++GG98pWv1KRJk/SVr3xFTz75pJ577jnddNNNuuaaayRJ22yzjX75y19qwYIFeuCBBwaa+han\n+z//8z+aM2eO5s+fry984Qvad999l20hR6KklTOc5X//+9+vI444YiCBffDBB3XRRRdJkg488EBd\nfPHFuuTvx33tAAAgAElEQVSSS/Tcc8/pqaeeUr1e15w5c5aYV7PXrRx//PF65JFHdO+99+qkk07S\nPvvsIynVtN53331atGjRsJcXADC6SEgBAAPKTEg322wzTZo0aeD5kauttpo23XRT7bTTTrKtGTNm\naMaMGdp88801bdo0rbzyypo6derA94udE332s5/V3nvvrV133VULFy7Uz3/+c1133XXaZJNNtM46\n6+h973vfQDJ70EEH6eUvf7mmTZumGTNmaN99912ihs229t9/f+22227adNNNtdlmmw3cjzqqSlo5\nrZY/Ipaqifzwhz+sPffcU7vttptWW2017bjjjrr66qslSRtuuKF+9rOf6Ytf/OJAzfXXvva1JRLP\nxnJvnH7j+7322kuveMUrtO2222qPPfbQu9/9bknSLrvsoq222krrrbfeEs1+AQDV47Jv/LcdZccA\nAOOFbTp8GaaNN95Yp5122hL3Oo4nVV3+CRMm6I477tAmm2yyzNPg9wAAoyPvb5veT0ENKQAAAACg\nFCSkAACg59BxEQCMDTTZBYBxhCaKwGL8HgBgdNBkFwAAAABQOSSkAAAAAIBSkJACAAAAAEoxsewA\nAACji85gAABAVXQ1IXU66zlW0iRJ10TE2d2cHwBgcHTgAgAAqqTbTXb3lrSBpGck3dfleQGjpl6v\nlx0CUHn8ToD28FsB2sNvZWzqdkK6uaQ/RsTHJX2gy/MCRg07RGBo/E6A9vBbAdrDb2VsaishtX26\n7Xm2b2z4fIbtv9u+3fan8mcH2T7B9mSlWtFH8ujPdzRyAAAAAEBPa7eG9AxJM4of2F5O0in58y0l\n7Wd7i4g4JyL+OyLmSvqJpN1tnySp3rmwAQAAAAC9zu12cGF7mqSLI2Lr/H5HSUdHxIz8/tOSFBFf\nGlYANj1sAAAAAMAYFhFNu/kfSS+7G0i6t/D+Pkk7DHcirQIDAAAAAIxtI+nUiJpNAAAAAMAyG0lC\nOkfSlML7KeLRLgAAAACANo0kIb1G0ma2p9leQdI+ki7qTFgAAAAAgLGu3ce+nCfpCkmb277X9qER\n8aykD0n6jaSbJZ0fEbd0L1SgXLan2L7U9t9s32T7v8qOCagi2yvZ/pPt62zfbPu4smMCqsz2crav\ntX1x2bEAVWX7bts35N/K1WXHg85pu5ddYLyzvZ6k9SLiOturSvqLpL25EAMszfYLIuIJ2xMl/UHS\nxyPiD2XHBVSR7Y9KeoWkSRGxZ9nxAFVk+y5Jr4iI+WXHgs4aSZNdYFyJiAci4rr8+nFJt0iaXG5U\nQDVFxBP55QqSlpPECQTQhO0NJb1R0vck8eQBYHD8RsYgElJgGeTn8m4r6U/lRgJUk+0Jtq+TNE/S\npRFxc9kxARV1gqRPSHq+7ECAigtJ/2f7GtvvLTsYdA4JKTBMubnujyR9ONeUAmgQEc9HxDaSNpT0\nWtt9JYcEVI7tPST9MyKuFTU/wFB2iohtJb1B0gdtv6bsgNAZJKTAMNheXtKPJZ0bEReWHQ9QdRHx\nqKRfSNqu7FiACnq1pD3zvXHnSdrZ9tklxwRUUkTcn/8/KOmnkrYvNyJ0Cgkp0CbblnSapJsj4sSy\n4wGqyvbattfIr1eW9HpJ15YbFVA9EXFEREyJiI0l7SvpdxFxcNlxAVVj+wW2J+XXq0jaTdKN5UaF\nTplYdgBAD9lJ0oGSbrDdf3L9mYj4dYkxAVW0vqSzbE9QuvB5TkT8tuSYgF7Aow+A5l4k6aepbkAT\nJX0/Ii4pNyR0Co99AQAAAACUgia7AAAAAIBSkJACAAAAAEpBQgoAAAAAKAUJKQAAAACgFCSkAAAA\nAIBSkJACAAAAAEpBQgoAwAjZfqHta/Pf/bbvy68X2j6l7PgAAKgqnkMKAEAH2T5a0sKI+HrZsQAA\nUHXUkAIA0HmWJNt9ti/Or2u2z7L9e9t3236r7eNt32D7V7Yn5vFeYbtu+xrbv7a9XpkLAgBAN5GQ\nAgAwejaW9DpJe0o6V9L/RsTLJD0p6U22l5d0sqS3RcR2ks6Q9IWyggUAoNsmlh0AAADjREj6VUQ8\nZ/smSRMi4jd52I2SpknaXNJWkv7PtiQtJ2luCbECADAqSEgBABg9z0hSRDxve1Hh8+eVjsmW9LeI\neHUZwQEAMNpostvjbH/G9nfLjqMbbD9ve5Nl/O4Btn8z9JgjY/sQ25cX3i+0Pa1D0x5Yt7an5fLo\nyG/W9tQcqzsxvcJ0++NcaPs9nZw2ymf7sLxul/m3Oc6183u7VdI6tl8lSbaXt71ld8NCVeX7js8Z\nZPhNtl87mjGVwfY6tm+xvWIXpn2m7WMGGd6x43on5Hifsf2PLkx7pu3HO3m+Uaah1m0H5zPo73SI\n7w61/Q0cb3OfA+9f1jirrOc3tm7LHU/ssgzfq9s+rBsxFUXEcRHx3m7Pp8qaJWsR8f2I2H20Y4mI\nSRFx92Dj5E5O7m1jWh1bt3k73rkw7dk51m51s716RHwvz3t52z+yfVdeT9NbxLhCPuG4t/DZOrbP\nsz3H9iO2/2B7+8Lw1+UOYRbYnm/7krF88t54AWS0RcRpETGprPn3mCj8b/ZaDa8lKSJikaS3S/qy\n7eskXStpx24GOtZU/bg9TIPuoyPipRHx+8HG6fQFzZJ8WtIZEfF0/we2d7X915xA3Wv7HY1fsn1w\nXvbB1mvj73LJgW0c10fK9jG2b7S9yKmX7sGEpC9FRMcvCkbE0Uq3DPScFsfHQddtB41kHsOJ8XhJ\nR+S+BsYUmuwObVk3Zp6nM/o6WttXJtvLRcRzHZxkqNzy+b2kEyRdoNa/jU9I+qekVQqfrSrpT5I+\nkoe9R9IvbE+LiH9J+pukN0TEnLyDPlbS6ZJeNdwAbU+MiGeH+73R4twDK6ovImYWXl8m6bLGz/P7\n1Vp853pJTS/coC1j6bjdyf12V44BXTheNU5/RUkHS3p54bMtJX0/f/6/klaXtGbD99aUdISkmzT0\nui37/OF2pWPg+9XedtjNeDs27W5vG500wnOAkZZZW9+PiAds/12pU7wfj3CeldLLV8tKZXsN2z+3\n/c9cM3Ox7Q3ysC9Ieo2kU3JTj5Py5y+x/b+2H7b99+LVvFxl/808zcdsX1VsEmd7q8J3H7D9mfz5\nEs0EbL/K9hW5xui6Ym1Uvnp0Z57+P2zv32LZJtg+wvYdedxrbG/Q7Cpr8Ypynv4fbX89z/8O26+2\nfajt2bbn2T642XcL329a+2P7TU4PmX80T6t4BbH/6vAjOd5XFadl+1u2v9owvZ/Z/u/8erLtH+d1\n+Q/bhzeLIY/7QtsX5Tj+JGnThuHFphVvtP23HNN9tj9q+wWSfiVpct42HrO9fl6PP7J9ju1HJR3S\nuG6zw5xqC+fa/lhhvks0+XChFjZPY6qki/M8P964LnMZXJS3r9tdaG6b4/ih0+MqHnNqIvaKVmXU\nKCIWRcRJEfFHSU0PTLY3lnSApONU2DFHxF0RcWJEzIvku5JWUOr4RRHxz4iYk0efoHQf3v3txuZU\nk/JJ2zdIWmh7OdufLmz7f7O9d2H84W7jZ9r+tlPN7WN5m5/aZmzFeT0kaZakb0naMa/H+S2+13Lf\nlIfXbR9n+095O77Q6cStWJPy3mbbGdDLBvtteHSO25+2vZ7tf9leqzDe/8sxLdck7JC0Qqv9rwut\nX2xv73S8fjTP7/g8WvEYudD2Dk4+m78/L09/tcJ0D7Z9j+2HCuP1z6fxePUu26+0fWXeL861fbIL\ntTh5v/IBp+PLY7Y/b3vT/J1HbM9y61qfHSQ9EhHFzr0+K+nbEfGbiHg+IhZERGMT1uMkfUPSwy2m\nW7R2q/20lzyuD7XOT8jl+ahT6522ahsj4uyI+LWkhVqG5CbHfEw+Zix0Op6vbfv7OZarbW800jjz\nd3ezfWteb9+0fZmbnwc+JOlop9ZPx+ft6QGnc7KVCtPbw+l8dUH+7taFYXfb/pjt6wvbyVLNtm1v\nodbHx7UGWV/P2/5P27cr3S4xVDyfcjqfe8xpf9Df8myo3+kWeR0tyMPePEj5fiL/hu6z/e4mo9Ql\nvanV93tWRPA3yJ+kuyTt3OTztSS9RdJKSrU4P5T008LwSyW9u/B+FUn3SnqX0onzNpIelLRFHn6m\npIckbafUq+K5ks7LwyYpnWT/t9LJ+KqSts/DjpZ0Tn69QZ7GjPx+1/z+hXn+j0raLA97kaQtWyzz\nJyTdUBh367y805RO+Cc0W05Jh0halJfRko6RdJ/SIwyWl/R6SY9JekGLMjpE0uWF989L2iS/ni5p\nq0I8D0jaK7/fqElcA9NSOsmYXRi2pqQnJK2X18VflA5uEyVtLOlOSbu1KJtZ+W9lpWYt90n6fYuY\n75e0U369uqRtC8tyb8N0a0qdneyZ36/UsG77y/77ed4vVaox3CUPP0PS5wvT6yvOQw3bceO6VDph\nOUVp+3p5nvbrCrE9KWlGXq9flHRli/JZahtpGH6vpNc2+fznkvZqjLvJeNvkWCYVPpsqaYFSsnuD\npBcWhn1a0sWDTO9uSX9V+u2smD97u6T18ut3Snpc0ouWcRs/M7//91y2J6qwjQ+x7+mf1weVttOV\n8nwH/b6G3jfVc8xbSnqBpB+1u5012875469qf437u8LnZR+3X5mH/ULS+wvzOUHSN1osS02D7H+L\nyyrpSkkH5NcvkLRDft3sGPlupVq5aXk5fyzp7DxsS6XE6NV5v/ZVpePTzoWYGo9X/0/S9rmcNpJ0\ns6QPF+b3vKSf5nLYUtLTkn6X57+aUmuXg1uUwQcl/bzhszslfV5pnz9X0jmS1iwM317S1bnMlliv\nTaZ/pgbZT2vJ4/pg63x3SddIWi2//zflY8kwtt1zJB09xDhnSDqm4bO6pNuUzmH6y/N2STvnOM+S\ndHo7cWqQ47iktZXOJffO6/q/8rbQeB5YPG6dIOlCSWvk9X+RpC/m8beVNE/SK/O6Olhpm16+sH1f\npXS+tmberv6jRbksdXwcbH0V1u1vcmwrDhZPLqfZWnx+MLWwXdTU4neav3uH0vnIRKXHfj0mafPC\n+vx8fj1D6fy2//j8AzUcbyW9VdJfRnOfOhp/1JAuo4iYHxE/jYinIuJxpY1vesNoxatce0i6KyLO\ninQ17zpJP5FUvOfhJxFxTaTmDd9XOvj1f3duRJwQEc9ExOMRcXWTeRwo6ZeRrrIpIv5PaafzJqWr\nN89L2tr2ypFqnG5usXiHSToyIm7P07kxIprWxjTRv4yhdLCfrPRDWxQR/6u043pxm9MaEBGXRcTf\n+uNRSgr7y3uoq4l/kBS2X5Pfv13SFRHxgNJOZ+2IODYino2IuyR9T9K+jRNxunr9VklHRcSTOZ6z\nBpn/M5K2sr1aRDwaEdcOEe8VEXFRXsanWow3M8/7JqWd2H7FEFtMd1C2pyideHwqb1/XK5XBwYXR\nLo+IX+f1eq4KTadGyvZbJDkifjbEeKspHaxrEbGw//NI98OuqXSgvF6pyW7/sC9FRMsrkUq/i5Mi\nYk7ke5Mi4kd521BE/FDpoL5D4TvD3cZ/HhF/iIhnJB2pdAV3A7VnbkR8M+8zWm0TSy7Q0PumUDrx\nvDkinpD0OUnvtJfo4Gqw7QzoSRU4bv85Dztb6Xjdf1zZV2nf1kq7+99nJG1me+2IeCIi/tRkmfod\nIOlrEXF3pNsfPiNp3xzP2yVdFBFXRLqn+Sgt3Yx0ieNVRPw1Iq7O5XSPpO9o6bL9Si6Hm5Uec/Sr\nPP/HlFoObdtiudZQSpCLpiiV4VslbaZ0Ae1kaaBMvynpQ7nM2tHufjrUep0vUroQsYXtCRFxa/+x\nZBSE0j22dxXK87aI+F2O8wItLt+RxPlGSTdFxIV5XZ+klEAVDRy3lC48vFfSRyPikfy7O06Lz7He\nJ+nUiPhzJGfn7xRvuzkpIh6IiAWSLtbi8m7UbDsfbH31Oy7H9vQg8ewo6VmlpHUr28vnc49irXyr\n3+mrJK2Sz0eejYhLlS7CNzuuvlPpwkH/8fnoJuMsVPpNjCkkpMvI9gtsn5qbEzyqdI/Q6g0ndcUd\n4UaSdsjV9QtsL5C0v1JNZf+48wrjP6l0JUlKO952elPbSNI7Guaxk9LVnCck7aN0f8Lc3Hzh31pM\nZ4rS1cdl0bgMiogHGz5bVcPk1MToUqdmTY9I+g+lmt8h5Z3DLC3+8e+vtFOSUplNbiizz0hat8mk\n1lG6ulXskGj2ILN+m9LO++7cVGOo+xrvG2K4msx7chvfGcpkSfPzSUlx2sWDcXG9PiFpJXeggwzb\nq0j6iqQPDzHeykoHoisi4svNxskHq49LerMLTc/asEQHU05N1a4tbA8v1ZLb2nC28VBhveYynq/2\n19ugnV95cW/JC20/lj9rZ9/UuB0tr5TQtxreie0MKFWFjts/k7SlU8+tr5f0aERcM0jo7e5/D1O6\nneEWpyaagzXrW1/SPYX3s5WOby/Kw4r7rSe1dLPXJY5XtjfP5xX357L9gpY+RjeWVauyazRfKYEq\nekIpAbsj71e/qHS8laT/lHRDLL5wLw1+MW+4++mmcUfE75RaGn1T0ry8rY1mJ3DFuJ5Sat1SfN+J\nOCdr6XOVxvfF48c6SjV9fyn8hn6lxcebjSR9rOE3tqGWLPtiwrss55BDbWfFeFvFs35E3KnUn0VN\nqdzOs71+i/kUf6eTtfSx/B41377W19DnmJMkPdLk855GQrrsPqa0498+IlZXuhJoLd7pNV6Vmy3p\nsohYs/A3KSI+2Ma8Zktqpze12UpN7xrn8RVJiohLImI3paYPf5fU6nEx96p5LWZ/wvKCwmfrtRFX\nK//Skh3YDDatHyg1+dgwItaQ9G0t3n7buQJ6nqS3O91Dsb0W3ww+W+kKeLHMVouIPZpM40GlK2TF\newBb3g+Yr8jtrbRDvlCpNq1VvNHk82bjNc67//7Jf2nw9TJYGc1VuseiuJOeqvYS5JHaTOkAcLnt\n+5XWy/r5pGaqNNChxYVKza7/Y4jpLa/UEuDpIcYrGiibvH18R6m50VqRal5v0rJ3WGClE9P+6a+q\n1GxwbstvtIit2ftY3FvypFjcQc5Q+yZp6e1okVKzplbD5wjofZU4bkdq7XCBUg3fgUo1pq20W8On\nnJztHxHrSPqypB/li3nNpjFXqWlmv6lKx7cHlJoab9g/IE+jMblsnOa3lJpTvjiX7ZHq3DnmDcr9\nBjR81srOkt6SjyP3K7UA+przfcEtjGQ/PSAiTo6I7ZSaXG6udAvUsCezDN8Z1jRGEOdcLbltuPi+\nybwfUkoCtyz8htYoHK9mS/pCw29s1Yg4fxmWa1nLrfi9QeOJiPMi4jVK5y2h9DsbylxJUxoufG2k\n5sfV+zX0OeYWkq5rY749hYS0PSvYXqnwN1HpCsuTkh516pygsVp9npbs8Obnkja3faDTYzCWd+oE\n4CV5+GAnvL9QOkn/sO0VbU9y4dEXBecq1Q7t5tQ5y0pOndtsYHtd23vlGqlFSglMq57PvifpGNsv\ndvIy22vlWqA5kg7K0393wzIO13WS3mp7ZdsvVrq628qqkhZExDN52ffX4p3Ig0pJSMtYIjW1eigv\n269zkxYp3WOy0Kljm5Xzcr3U9nZNpvGcUnOtWh53S6V7FpaS1+8BtlfP31uoxeU9T9ILG2rxmq3/\nZp99Ns97K6V7Nfp32tdJeqPtNW2vp3QVr6hxeywu172SrpB0XN6+XqZ0f9G5zcZfFnm6/Z0YFF/f\nqHQwe3n+e0+O9eWS7nPq5OJHSlcbD2ky3bfkK/MTbK8j6etKzdaHk5AWraK0XT0kaYLtQ5VqSEfi\njbZ3sr2C0j2nV0buiMmp5rxZk5xWHpC0oQfv8n2ofZMlHejUycILlO7DuiC3JOjXajsDekXVj9tn\nSzpUqbfMwZrrtn0xLMe5Tn77qBbfqtPsGHmepP926shsVaUaxlm5meWPlc4ldsz7rVobcayqdJx7\nIpfPB9oJucXrRn+WtIbtYo3SGZIOtb1x3o99WqkVjZT2WS9ROo5so3TrUk0pSW4VR8v99CAxLznA\n3s6pNdfySsesp5SP+06d/dw1yHcn5uPicpKWz9vsYOfozZKvtspzsDjb8AulW7/2yr+pD2qQyoS8\nPX1X0on922Y+J90tj/JdSe936pDLtldx6sSyVS3oYNtJs+PjcC8mt4wnn2vs7HSR/Gm1X25/Uirn\nT+Z9SJ9Sk/5ZhRj74/yhUqeW/cfnZucH05VqmceUriakTr3Tfcuph86qPdtrOH6ptDH1/x2ldNP7\nykonrlcobRzFHcQ3lGrk5ts+Mbeb302p3fwcpasgxyndQC8NUkMW6X6510t6c/7ebUqdvyzxvYi4\nT6ljmCOUmmrMVroibKV1/d953g8rdfTT6oDxdaUfxSVKB7XvKt2YLqV7AT6Rl3tLSX9siLedWr5+\nJyjd8zJP6eBybsP4xdf/KenzTs0SP6fCCXJujvwFSX/M5b1Di1h+oHTl9AeF7z6vtGPYRql51YNK\nNWStmnx+SOnA+4DSvYqnDxLzgZLucmq+9D6le3YUEX9XOhn4R453/RbxNn4WSk3M7pD0f5K+Guk+\nYSmd0Fyv1EnPr5V2dMXvHqeUZCyw/dEmse6ndLV8rlLSfVRu1tMsjsbvNtN4ELhV6bczWakDgX/Z\nnhoRz0XqKfefEfFP5c6J8vvnla5sv0lp++/vIXKh7Z3ydDfIy/uYUudEC1S4SODUW/Qvh4h18UKl\ne5u+ptQ5yANKyegfGpZ7OGURStvb0Uq/u22V7x3LNmyYfuN3G6f9O6XOKh6w/c+lvyJp6H1TKG0v\nZyrtT1ZQ6piiqNV21n9FHKi6Kh+3FanX8eeVOicZrGn+cPY5u0u6yfZCpePrvhHxdMMxckFOjE9X\n2g/8XunY94Skw3Nsf8uvZykdExYqnVP0X+hrFtPHlS4UP6Z0DG08BrVqGTTYcirH84zS/urAwmdn\nKCX1f1I67j2pvB+L1GdD/3FlntJ5xmNR6HugSRzfV+v99FBx9r9fTWnZ5+eYHlLqEEpKNbCt9vVS\nulj+hNK2dmR+feAg47e6X3KkcQ4qIh5Wuof6K/l7Wygl/INtG59SOp5clc+H/leLe8r/i9J55Sk5\nntuV+q9otY233E7U/Pg41O+nsdVRq3ikdP/ocUrnifcrNTv+zFDzydvvmyW9IX/3FEkHRcRtjd+N\n1AfMiXlZbpP02+J08/niFkqtxsYUR9v3e49gJukqz6yIeGfXZwagNE5NXv+udOXw4xFxWskhlcr2\nGZLui4jPNRm2odJ+8d9HOaZLlZr2n95k2DSlk9OJ+YJA4/BDlS5YrajUBOvurgaLEXHqsOxspXvi\nQ9J3IuIk2zWl1gj99z5/Jp8IYRTZ/j9JP2j2W6ySXFu1QKk57j1Djd+lGNaWdLmkbUbQAqY0tn8j\n6b8i4tYOTOs7SheRH4iIzUYc3JLTPlqLe4ZeJYZIEvL5/b2S9o/0zGV0kdOjnO6IiG+XHUundT0h\ndXrWzn9K+m5E/KSrMwOACrF9ptJjbJZKSMuSE9Jzm10sGCohRW9xar6/XkRcl5OKvyg9ruGdkhZG\nxNdLDXAcs/1KpdYiU2LJDuUqIZ+7/VapJu5rSo+safv50xi7cnPbq5VqpT+h1Npuk168UIDqaKvJ\nru3TnR6ge2PD5zOcHgx7u+1P5c8Ocnrg7mRJioiLI+INanGvHQCMYYM1LypTNzqGQMVEelTCdfn1\n45Ju0eLes2l6XRLbZyk1W/xIFZPRbE+lZspzlO49XepRaBi3dlRqgvug0i01e5OMYqTaqiF1en7j\n40rPrts6f7ac0n1huyrtsP4sab+IuKXwvelKz4haSdItEXFix5cAAAAMKtd+XyZpK6W+BQ5V6iPg\nGkkfi4gx9xgBAEBvaLvJbj6YXVxISHeUdHREzMjvPy1JEfGlrkQKAACGLTfXrUs6NiIutL2uFt8/\neozSM/Z6ueNBAEAPmziC726gJR/eep+kHYY7Eds0DwMAdFRE0CRV6RFUSo/xODciLpSk3KN1//Dv\nafHjMorf49gMAOioVsfmkSSkHTtYjUZPv+NBrVZTrVYrO4wxgbLsHMqycyjL9vBkmiQ/ouc0STcX\nb5mxvX5E3J/fvkXpecBLOfrS4Twid3yqn1lX3yF9ZYdRaZRReyinoVFG7alqOc183cyWw0aSkM5R\neq5SvylKtaTDVqvV1NfXp76+vhGEAwAYz+r1uur1etlhVMlOSs8yvMH2tfmzIyTtZ3sbpQvLd0n6\nj5LiAwBgRAnpNZI2y/eWzpW0j9JzkYaNK/4AgJHqv7A5c2brq7DjSUT8Qc170//VaMcCAEAr7T72\n5TxJV0ja3Pa9tg+NiGclfUjpOVo3Szq/2MPucNRqNa5qdwA1zJ1DWXYOZdk5lOXg6vU6FzgxqqZt\nM63sECqPMmoP5TQ0yqg9vVhObfey27UA7Cg7BgDA2GGbTo1GyHaM5j2krWq1jz6a+1gBYCyY+bqZ\nXenUCAAAoEMak0+aXgPAeNBWk91uo8kuAGCkaLILAEDvqUQNKScQAICRolMjAAB6TyVqSAEAAAAA\n408lElKa7AIARoomuwAA9B6a7AIAxgSa7AIA0HsqUUMKAAAAABh/KpGQ0mQXADBSNNkFAKD30GQX\nADAm0GQXAIDeU4kaUgAAAADA+ENCCgAAAAAoRSUSUu4hBQCMFPeQAgDQe7iHFAAwJnAPKQAAvacS\nNaQAAAAAgPGHhBQAAAAAUAoSUgAAAABAKUhIAQAYg2xPsX2p7b/Zvsn2/2/v7qPkKusEj39/iQQJ\nIDkQCZBEG4QoOEgwbuAMjBQZGfEN9DgHxh3xZXwbZ3R0dncGdVE6x90ZxzkDrDLrcUfABBCRo2ic\nAQUjFQI6IpKQIG+JQ++GAIn4GiKQkPz2j3s7KZrupLqrum9V9fdzzj1171P33vrl4dK3fvU893n+\nqiw/OCJujogHI+KmiJhRdaySpMmrIxJSR9mVJLXKUXafYzvw15n5cuBk4C8j4ljgY8DNmTkPWF5u\nS4Fdmp4AABjjSURBVJJUiY5JSGu1WtVhSJK6WK1WMyFtkJmPZebqcv0J4D5gNnAWsKTcbQnw5moi\nlCSpQxJSSZI0fiKiDzgR+BEwKzM3lW9tAmZVFJYkSSakkqTecfXVVUfQeSLiAODrwEcyc0vje5mZ\nQFYSmCRJwPOqDkCSpHa47DL41KeqjqKzRMQ+FMnolZn5zbJ4U0QclpmPRcThwObhjq1/ub5rvW9+\nH33z+8Y5WklSrxhYPcDA6oGm9jUhlSR1vUsvhc9+Fup1mDev6mg6Q0QEcBlwb2Ze0vDWMuCdwD+U\nr98c5nBq76qNd4iSpB419IfMFUtWjLivCakkqav94z/CF74AK1bAkUdWHU1HOQV4O7AmIlaVZR8H\nPgN8LSLeAwwA51QTniRJJqSSpC6VCZ/+dPHc6K23wpw5VUfUWTLzNkYeK+I1ExmLJEkj6YiEdHDa\nF6d+kSQ1IxM+8Qn4138tktFZs4p5SJ3TWpKk7tIxCakkSc3IhI9+FG67DW65BWbOLMoHf9hcvHhx\ntQFKkqSmdURCKklSM3buhA9+ENasgeXLYcaMqiOSJEmtMCGVJHWNiy6Cn/4UbroJDjyw6mgkSVKr\nRhrsQJKkjrNsGXzykyajkiT1ChNSSVJX2LoV7roLTj216kgkSVK7mJBKkrrCypWwYAHsv3/VkUiS\npHYxIZUkdYXvfx/+8A+rjkKSJLXTuCekEbF/RPw4It4w3p8lSepdy5fDokVVRyFJktppIlpI/xa4\ndgI+R5LUo375S1i3DhYurDoSSZLUTuM67UtEnAHcCzx/PD9HktTbbrmlGMxo2rSqI5EkSe3UVAtp\nRFweEZsiYu2Q8jMj4v6IWBcR55dl50XExRFxBHAacDLwn4H3RUS0+x8gSep9Pj8qSVJvaraF9Arg\n88DSwYKImApcCrwG2Aj8OCKWZeaVwJXlbheU+74T+HlmZrsClyRNHsuXw3vfW3UU1YiI4zNz7d73\nlCSp+zTVQpqZK4FfDSleCKzPzIHM3A58FTh7hOOXZOYNLUUqSZqUNm6Exx+HE06oOpLKfKEcHPAv\nIuKgqoORJKmdWnmGdDawoWH7YeCksZyov79/13qtVqNWq7UQliSplyxfDqefDlNG+Am1Xq9Tr9cn\nNKaJlJmnRsQ84M+AuyLiDuCKzLyp4tAkSWpZKwlp27rfNiakkiQ1Wr58z8+PDv0hc/HixeMf1ATL\nzAcj4gLgTuBzwPyImAJ8IjO/Xm10kiSNXSvTvmwE5jZsz6VoJR21/v7+nv51W5I0NpnND2hUr9d7\n8gfOiDghIi4G7gMWAW/MzGOB04GLKw1OkqQWtZKQ3gkcExF9ETENOBdYNpYT9ff3201XkvQc69YV\nr0cfvfd9a7VaTyakFC2iq4ATMvMvMvMugMx8hHLwQEmSulWz075cA/wAmBcRGyLi3Zn5DPAh4LsU\nc41em5n3jSUIW0glScMZ7K7bzKRhvdpCCrwBuDozfwfFKPcRsT9AZi7d04HDTdsWEf0R8XBErCqX\nM8c1ekmS9qCpZ0gz820jlN8I3NhqED36BUKS1KLly+HsYcdvf67BZ0l78BnS71FMsfZEuT2d4sfg\n32/i2OdM20YxBsRFmXlRO4OUJGksWumyK0nSuNm5E+p1WLSo6kgq9/zMHExGycwtFEnpXo0wbRtA\nE23OkiSNv45ISO2yK0ka6u67YeZMmD27uf17uMvu1ohYMLgREa8CnmzxnB+OiLsj4rKImNHiuSRJ\nGrOOSUgd1EiS1Ghv070M1cODGn0U+FpE3BYRtwHXAh9u4XxfAI4E5gOPAv/UeoiSJI1NK/OQSpI0\nbpYvh/e9r+ooqpeZP46IY4GXUjz/+UBmbm/hfJsH1yPiS8C3h9uv/uX6rvW++X30ze8b60dKkiaZ\ngdUDDKweaGrfjkhIB1tIbSWVJAFs2wa33w5XX938MfV6vZcf/3gVRavm84BXRsReR9gdSUQcnpmP\nlptvAdYOt1/tXbWxnF6SpOf8kLliyYoR9+2YhFSSpEF33AHHHAMHH9z8Mb06ym5EXAUcBawGdjS8\ntdeEtJy27TRgZkRsAC4EahExn6K19SHgA20PWpKkJnVEQipJUqPRPj/a4xYAx2VmjvbAEaZtu7z1\nkCRJao+OGdSoh7tZSZJGaSwJaQ+PsnsPcHjVQUiSNB46ooW0R79ASJLGYOtWuOsuOPXU0R3Xq112\ngRcC90bEHcDTZVlm5lkVxiRJUlt0REIqSdKg226DBQtg//2rjqRj9JevCUTDuiRJXc+EVJLUUZYv\nh0WLqo6ic2RmPSL6gKMz83sRMR3v35KkHtERz5BKkjTIAY2eLSLeD1wHfLEsmgNcX11EkiS1T0ck\npA5qJEkC+OUvYd06WLhw9Mf28KBGfwmcCvwWIDMfBA6tNCJJktqkYxLSWq1WdRiSpIrdcksxmNG0\naaM/tlar9WpC+nRmDg5mREQ8D58hlST1iI5ISCVJAp8fHcGKiPjvwPSIOIOi++63K45JkqS2cFAE\nSVKlnnoKrr8eLrsM1qyB22+vOqKO8zHgPcBa4APADcCXKo1IkqQ2MSGVJFXi7ruLJPQrX4FXvhLe\n/344+2zYd9+qI+ssmbkD+D/lIklST+mIhHTwGVKfI5Wk3vab38A11xSJ6KZN8O53w513Ql9f6+eu\n1+s9OUBeRDw0THFm5lETHowkSW3WMQmpJKl77dwJAwOwfj1s3jzy8vjj8LrXwac/DWecAVOnti+G\nwR82Fy9e3L6Tdob/1LD+fOCPgUMqikWSpLbqiIRUktQ9tmyBe+4putzefXfx3OfatTBjBsybB4cd\nBoceWizz5u1eP/RQmDUL9tuv6n9Bd8nMx4cUXRIRdwGfrCIeSZLayYRUkrTLU0/BY4/Bo48WS+P6\no4/CAw8Ur8cdB694BZxwApx7brF+8MFVR9+bImIBu6d5mQK8Cmhj27IkSdUxIZXU0554An7726qj\n6AxPP10kk488UiyN64PbW7cWrZiHH14shx1WvC5cWKwfc0yxPM+7x0T6J3YnpM8AA8A5lUUjSVIb\n+ZVCPWP79t1fqnfsqDoaTZTM4rnEjRuHX555Bg46CCKqjrR606btTjSPOKJYTj999/bhh8Mhh1hX\nnSYza1XHIEnSeDEh7RGbN8MPflAMLNLrnnyySDQefrhYNmwoXn/xi90tO/vsU3WUmkiHHAKzZxdL\nrbZ7ffZsk1F1v4j4r+xuId1VXL5mZl40wSFJktQ2JqRd7MknYdkyWLq0mEj+lFMmx/x9++4Lc+bA\nS14Cp51WrM+ZUySjdiOU1IMWUIy0u4wiEX0j8GPgwSqDmggjjZh84YUXTnAkkqTx0hFf352HtHk7\nd8LKlUUSev318KpXwXnnwbXXwgEHVB2dJFWnV+chBeYCr8zMLQARcSFwQ2b+6d4OjIjLgTcAmzPz\n+LLsYOBa4MWUz6Nm5q/HKfYWDZd49ty0PpI0qXVMQqrh7dxZPBP5s5/BTTfBVVfBC15QJKFr1xZd\nEiVJPT0P6aHA9obt7WVZM64APg8sbSj7GHBzZn42Is4vtz/WjkAlSRqtjkhIJ7unn4aHHiqSzp/9\nDP7jP3avP/RQ8QzcS14CJ58M3/pWMc2CJGnSWArcERHfoOiy+2ZgSTMHZubKiOgbUnwWcFq5vgSo\nY0IqSaqICekE2batSDTXrYP165/9+uijMHcuHH00HHVUkXzWasXrkUfaFVeSJrPM/J8R8R3g1LLo\nXZm5qoVTzsrMTeX6JmBWSwFKktSCnklId+4sRlp94IHnLhs2FFNDVGnqVOjr2z2H37HHwpveVKy/\n+MWOCitJ2qPpwJbMvDwiXhgRR2bmQ62eNDMzIiq+Q0qSJrOuTUh37ChGlv3a1+C224qWxoMOgpe+\ntFhe9jJ4/euL9Re9qEgIq+bUE5Kk0YqIfoqRdl8KXA5MA64CThnjKTdFxGGZ+VhEHA5sHm6n+pfr\nu9b75vfRN79vjB8nSZpsBlYPMLB6oKl9uyoh3bkTfvjDIgm97jo49FA45xz4l38pEs8XvKDqCCVJ\naru3ACcCPwHIzI0RcWAL51sGvBP4h/L1m8PtVHtXrYWPkCRNZkN/yFyxZMWI+3Z8QpoJd9xRTGty\n3XVFK+g558D3v1+0gkqS1OOezsydUXaziYj9mz0wIq6hGMBoZkRsAD4FfAb4WkS8h3Lal7ZHLElS\nk8Y1IY2IGvBp4B7gq5k5cmo8jO3bYdEi2LwZzj0XvvMdePnLxyNSSZI61nUR8UVgRkS8H/gz4EvN\nHJiZbxvhrde0KzhJklox3i2kO4EtwL7Aw6M9+O/+rhhh9tZbff5SkjT5RNEsei3wMor76Tzgk5l5\nc6WBSZLUJuOdkK7MzFsj4lDgIuDtzR74k5/AP/8zrFplMipJmtRuyMzfA26qOhBJktptSjM7RcTl\nEbEpItYOKT8zIu6PiHURcX5Zdl5EXBwRR2Tummzl1xStpE156il4xzvgkktg9uxmj5IkqbeU99Gf\nRMTCqmORJGk8NNtCegXweWDpYEFETAUupXgOZSPw44hYlplXAleW+7wFeC0wozy+KRdcAMcdB28b\n6ckXSZImj5OBt0fE/wW2lmWZma+oMCZJktqiqYQ0M1dGRN+Q4oXA+swcAIiIrwJnA/c1HHc9cP1o\nArr1VvjKV2DNGrvqSpImr4h4UWb+P4ofdhPwrihJ6jmtPEM6G9jQsP0wcNJYTtTf3w/Atm1wxRU1\nvvjFGjNnthCZJGnSqNfr1Ov1qsMYD98CTszMgYj4ema+teqAJElqt1YS0tz7Ls0ZTEj//M/hzDPh\nrLPadWZJUq+r1WrUarVd24sXL64umPFzVNUBSJI0HlpJSDcCcxu25zKGqV2gSEinT69x44011qxp\nISJJ0qTVwy2lPaNHfyyQJLWglYT0TuCY8tnSR4BzgTENQ/SRj/Rz/PGwdCkcdFALEUmSJq3BltIe\nSnpeERFbyvX9GtahGNToBVUE1boLhynrmf9mkqRRaiohjYhrgNOAQyJiA/CpzLwiIj4EfBeYClyW\nmfft6TwjefWr+1m4sMaiRbWxHC5JUs+1kGbm1KpjkCRpvDU7yu6wLZ+ZeSNwY6tBbNvWz1VXtXoW\nSdJk1oMtpJIk9bwpVQcAsGQJTJ9edRSSJEmSpInUyjOkbfOd7/Tz1FPPHiVRkqTR6LUuu5IkTQYd\nkZAOTvsiSdJY2WVXkqTu0xFddiVJkiRJk09HJKT9/f12s5IktaRer9vjRpKkLmOXXUlST7DLriRJ\n3acjWkglSZIkSZNPRySkdtmVJLXKLruSJHUfu+xKknqCXXZHJyIGgN8CO4Dtmbmw2ogkSZNRRySk\nkiRpwiVQy8xfVh2IJGny6oguu5IkqRJRdQCSpMnNhFSSpMkpge9FxJ0R8b6qg5EkTU4d0WW3v79/\n17M/kiSNRb1ed4C80TklMx+NiBcCN0fE/Zm5cvDN+pfru3bsm99H3/y+iY9QktSVBlYPMLB6oKl9\nOyYhlSSpFQ5qNDqZ+Wj5+vOIuB5YCOxKSGvvqlUUmSSp2w39IXPFkhUj7muXXUmSJpmImB4RB5br\n+wN/BKytNipJ0mTUES2kkiRpQs0Cro8IKL4LXJ2ZN1UbkiRpMjIhlSRpksnMh4D5VcchSVJHdNnt\n7+93IApJUkvq9bpjEkiS1GU6ooXULxCSpFY5qJEkSd2nI1pIJUmSJEmTjwmpJEmSJKkSJqSSJEmS\npEqYkEqSJEmSKmFCKkmSJEmqhAmpJEmSJKkSHZGQOg+pJKlVzkMqSVL3cR5SSVJPcB5SSZK6T0e0\nkEqSJEmSJp+OaCGVJElq1nCt4BdeeGEFkUiSWmVCKkmSuszQ5NNu2pLUreyyK0mSJEmqhAmpJEmS\nJKkSdtmVJEljsnXrVnbs2PGc8ilTpnDAAQdUEJEkqduMa0IaEQH8D+BA4M7MXDqenydJkibO1Vdf\ny+afP07E7q8TmTvY8czvJjyWkab7cbAjTTZ7mvrK/x96Ty/87RvvFtI3A7OBx4GHx/mzJEnSBHpm\nB+x45lzgxQ2lPwf+N88deAjGd/Chif48qZP5/8Pk0t0DvY33M6TzgNsz878BHxznz5r06vV61SH0\nDOuyfazL9rEu1S4RcWZE3B8R6yLi/Krj6VYDqweqDqHjWUfNsZ72zjpq0q8Gqo5g1JpKSCPi8ojY\nFBFrh5Q/54YWEedFxMURcQRFq+ivy913tjVyPYdfVtvHumwf67J9rEu1Q0RMBS4FzgSOA94WEcdW\nG1V38gvy3llHzbGe9s46atKvB6qOYNSabSG9guLGtctIN7TMvDIz/zozHwG+Abw2Ij4H1NsXtiRJ\nGqOFwPrMHMjM7cBXgbMrjkmSNEk19QxpZq6MiL4hxbtuaAARMXhDu6/huCeB97YjUEmS1BazgQ0N\n2w8DJ43lRFMC9tnne8SU/XaVZW5j+7bWApQkTR6Rmc3tWCSk387M48vtPwZem5nvK7ffDpyUmR8e\nVQARzQUgSVKTMjOqjqFTRcRbgTP3dP/23ixJareR7s2tjLLblpuVXxokSZpQG4G5DdtzGTISvvdm\nSdJEaWWU3b3e0CRJUse5EzgmIvoiYhpwLrCs4pgkSZNUKwmpNzRJkrpMZj4DfAj4LnAvcG1m3rfn\noyRJGh9NPUMaEdcApwGHAJuBT2XmFRHxOuASYCpwWWb+/XgGK0mSJEnqHU21kGbm2zLziMzcNzPn\nZuYVZfmNmfnSzDx6LMmoE3OP3XBzw0bEwRFxc0Q8GBE3RcSMKmPsBhExNyJuiYifRsQ9EfFXZbl1\nOUoR8fyI+FFErI6IeyPi78ty63KMImJqRKyKiG+X29alRtTMPTUiPle+f3dEnLi3Y/d0zUXEx8v9\n74+IP2ooXxARa8v3/td4/XvHqoPqqV6WrSqXmeP1bx6tiayjsvyWiNgSEZ8f8hleS83Vk9dSUX5G\nRNwZEWvK19MbjvFaaq6eqrmWMrOShaJVdT3QB+wDrAaOrSqebluAPwBOBNY2lH0W+Nty/XzgM1XH\n2ekLcBgwv1w/AHgAONa6HHN9Ti9fnwf8O3CqddlSff4X4GpgWbltXboMuzRzTwVeD9xQrp8E/Pve\njh3pmqOYf3x1uX9fefxgr6s7gIXl+g0UI/pWXkcdWE+3AK+suk46oI6mA6cAHwA+P+RzvJaaqyev\npWJ9PnBYuf5y4GGvpVHXUyXXUivPkLbKiblbkJkrgV8NKT4LWFKuLwHePKFBdaHMfCwzV5frT1DM\nozsb63JMMvN35eo0ij+Sv8K6HJOImENxA/oSMDjiqXWpkTRzT911/WTmj4AZEXHYXo4d6Zo7G7gm\nM7dnMR/5euCkiDgcODAz7yj3W0pnXacdUU8Nn9WJoxlPaB1l5u8y83bg6cYP8FoCmqinBl5Lmasz\n87Gy/F5gv4jYx2sJaKKeGj5rwq+lKhPS4Sbmnl1RLL1iVmZuKtc3AbOqDKbbRDHX7onAj7AuxyQi\npkTEaoo6uyUzf4p1OVYXA38D7Gwosy41kmbuqSPtc8Qejh3pmjuCZ4+s33iuxvKNw8RRpU6opyMa\ntpeU3eIuGOW/YzxNdB0NGjqoyWy8lpqpp0FeS8/2VuAnZZLmtdRcPQ2a8GupyoTUSbfHURbt7tZx\nkyLiAODrwEcyc0vje9Zl8zJzZ2bOB+YAr258LqF837psQkS8EdicmasY4ZdK61JDNHstNPPLdwx3\nvh655jqpnv40M3+P4hGcP4iI85qMbbx1Uh11sk6qJ6+lxh0jXg58hqJ7czfopHqq5FqqMiF1HtP2\n21Q23w92ddlccTxdoeym8HXgysz8ZllsXbYgM38D/BuwAOtyLH4fOCsiHgKuARZFxJVYlxpZM/fU\nofvMKfcZrnxjuT7SNbenc80Z4VydoBPqaSNAZj5Svj4BfIWi610nmOg62lMcXktN/J33WtpdR+Xj\nLt8AzsvMhxo+w2tp7/VU2bVUZULqPKbttwx4Z7n+TuCbe9hXQEQEcBlwb2Ze0vCWdTlKETGzYQS3\n/YAzgFVYl6OWmZ/IYkTzI4E/Ab6fmedhXWpkzdxTlwHvAIiIk4Ffl9259nTsSNfcMuBPImJaRBwJ\nHAPcUT6X9NuIOKn8+3oenXWddkQ9RTGC9szyM/YB3gTsGjW/YhNdR4Oe1fqTmY/itbTXevJa2l1H\n5XeQfwPOz8wfDn6A1xLQRD1Vei01M/LReC3A6yhGNV0PfLzKWLptoWg1eQTYRtF3/N3AwcD3gAeB\nm4AZVcfZ6QvFKLA7KUYlW1UuZ1qXY6rL44G7yrpcA/xNWW5dtlavp7F7lF3r0mXEZbh7KkVXrA80\n7HNp+f7dNIykONL9eE/XHPCJcv/7gdc2lC+g+BKzHvhc1fXSifUE7E/xRfJu4B6KZ8aj6rqpsI4G\ngF8AWyi+07zMa6m5eqIYfddrqSi/AHiC3d/nVgEzvZaaqycq/Ls0OPS4JEmSJEkTqsouu5IkSZKk\nScyEVJIkSZJUCRNSSZIkSVIlTEglSZIkSZUwIZUkSZIkVcKEVJIkSZJUCRNSSZIkSVIl/j9NWonu\nXcppEgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot latency events for a specified task\n", + "latency_stats_df = trace.analysis.latency.plotLatency('ramp')" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
countmeanstdmin50%95%99%max
latency500.0000290.0000380.0000070.0000220.0000310.000210.000251
\n", + "
" + ], + "text/plain": [ + " count mean std min 50% 95% 99% \\\n", + "latency 50 0.000029 0.000038 0.000007 0.000022 0.000031 0.00021 \n", + "\n", + " max \n", + "latency 0.000251 " + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Plot statistics on task latencies\n", + "latency_stats_df.T" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot latency events for a specified task\n", + "trace.analysis.latency.plotLatencyBands('ramp')" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "10:25:42 INFO : Set plots time range to (3.445000, 3.450000)[s]\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Zoom into a spefific time frame\n", + "trace.setXTimeRange(3.445, 3.45)\n", + "trace.analysis.latency.plotLatencyBands('ramp')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.9" + }, + "toc": { + "toc_cell": false, + "toc_number_sections": true, + "toc_threshold": 6, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/libs/utils/analysis/latency_analysis.py b/libs/utils/analysis/latency_analysis.py new file mode 100644 index 0000000000000000000000000000000000000000..ba9a9a5d3052e4c24e59292d62f346bafb735ebb --- /dev/null +++ b/libs/utils/analysis/latency_analysis.py @@ -0,0 +1,409 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2015, ARM Limited and contributors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +""" Latency Analysis Module """ + +import matplotlib.gridspec as gridspec +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import pylab as pl +import re + +from collections import namedtuple +from analysis_module import AnalysisModule +from devlib.utils.misc import memoized +from trappy.utils import listify + +# Configure logging +import logging + +# Tuple representing all IDs data of a Task +TaskData = namedtuple('TaskData', ['pid', 'names', 'label']) + +class LatencyAnalysis(AnalysisModule): + """ + Support for plotting Latency Analysis data + + :param trace: input Trace object + :type trace: :mod:`libs.utils.Trace` + """ + + def __init__(self, trace): + super(LatencyAnalysis, self).__init__(trace) + +############################################################################### +# DataFrame Getter Methods +############################################################################### + + @memoized + def _dfg_latency_df(self, task): + + if not self._trace.hasEvents('sched_wakeup'): + logging.warn('Events [sched_wakeup] not found, ' + 'cannot compute CPU active signal!') + return None + if not self._trace.hasEvents('sched_switch'): + logging.warn('Events [sched_switch] not found, ' + 'cannot compute CPU active signal!') + return None + + # Get task data + td = self._getTaskData(task) + if not td: + return None + + wk_df = self._dfg_trace_event('sched_wakeup') + sw_df = self._dfg_trace_event('sched_switch') + + # Filter Task's WAKEUP events + task_wakeup = wk_df[wk_df.pid == td.pid][['success', 'target_cpu', 'pid']] + + # Filter Task's START events + task_events = (sw_df.prev_pid == td.pid) | (sw_df.next_pid == td.pid) + task_switches_df = sw_df[task_events]\ + [['__cpu', 'prev_pid', 'next_pid', 'prev_state']] + + # Unset prev_state for switch_in events, i.e. + # we don't care about the status of a task we are replacing + task_switches_df.prev_state = task_switches_df.apply( + lambda r : np.nan if r['prev_pid'] != td.pid + else self._taskState(int(r['prev_state'])), + axis=1) + + # Rename prev_state + task_switches_df.rename(columns={'prev_state' : 'curr_state'}, inplace=True) + + # Fill in Running status + task_switches_df.curr_state = task_switches_df.curr_state.fillna(value='A') + + # Join Wakeup and SchedSwitch events + task_latency_df = task_wakeup.join(task_switches_df, how='outer', + lsuffix='_wkp', rsuffix='_slp') + # Remove not required columns + task_latency_df = task_latency_df[['target_cpu', '__cpu', 'curr_state']] + # Set Wakeup state on each Wakeup event + task_latency_df.curr_state = task_latency_df.curr_state.fillna(value='W') + + # Sanity check for all task states to be mapped to a char + numbers = 0 + for value in task_switches_df.curr_state.unique(): + if type(value) is not str: + logging.warning("The [sched_switch] events contain 'prev_state' value [%s]", + value) + numbers += 1 + if numbers: + verb = 'is' if numbers == 1 else 'are' + logging.warning(" which %s not currently mapped into a task state.", + verb) + logging.warning("Check mappings in:") + logging.warning(" %s::%s _taskState()", __file__, + self.__class__.__name__) + + # Forward annotate task state + task_latency_df['next_state'] = task_latency_df.curr_state.shift(-1) + + # Forward account for previous state duration + task_latency_df['t_start'] = task_latency_df.index + task_latency_df['t_delta'] = ( + task_latency_df['t_start'].shift(-1) + - task_latency_df['t_start'] + ) + + return task_latency_df + + + # Select Wakeup latency + def _dfg_latency_wakeup_df(self, task): + task_latency_df = self._dfg_latency_df(task) + if task_latency_df is None: + return None + df = task_latency_df[ + (task_latency_df.curr_state == 'W') & + (task_latency_df.next_state == 'A')][['t_delta']] + df.rename(columns={'t_delta' : 'wakeup_latency'}, inplace=True) + return df + + # Select Wakeup latency + def _dfg_latency_preemption_df(self, task): + task_latency_df = self._dfg_latency_df(task) + if task_latency_df is None: + return None + df = task_latency_df[ + (task_latency_df.curr_state.isin([0, 'R', 'R+'])) & + (task_latency_df.next_state == 'A')][['t_delta']] + df.rename(columns={'t_delta' : 'preempt_latency'}, inplace=True) + return df + + +############################################################################### +# Plotting Methods +############################################################################### + + def plotLatency(self, task, kind='all', tag=None, threshold_ms=1): + """ + Generate a set of plots to report the WAKEUP and PREEMPT latencies the + specified task has been subject to. A WAKEUP latencies is the time from + when a task becomes RUNNABLE till the first time it gets a CPU. + A PREEMPT latencies is the time from when a RUNNABLE task is suspended + because of the CPU is assigned to another task till when the task + enters the CPU again. + + :param task: the task to report latencies for + :type task: int or list(str) + + :param kind: the kind of latencies to report (WAKEUP and/or PREEMPT") + :type kind: str + + :param tag: a string to add to the plot title + :type tag: str + + :param threshold_ms: the minimum acceptable [ms] value to report + graphically in the generated plots + :type threshold_ms: int or float + """ + + if not self._trace.hasEvents('sched_switch'): + logging.warn('Event [sched_switch] not found, ' + 'plot DISABLED!') + return + if not self._trace.hasEvents('sched_wakeup'): + logging.warn('Event [sched_wakeup] not found, ' + 'plot DISABLED!') + return + + # Get task data + td = self._getTaskData(task) + if not td: + return None + + # Load wakeup latencies (if required) + wkp_df = None + if 'all' in kind or 'wakeup' in kind: + wkp_df = self._dfg_latency_wakeup_df(td.pid) + if wkp_df is not None: + wkp_df.rename(columns={'wakeup_latency' : 'latency'}, inplace=True) + logging.info("Found: %5d WAKEUP latencies", len(wkp_df)) + + # Load preempt latencies (if required) + prt_df = None + if 'all' in kind or 'preempt' in kind: + prt_df = self._dfg_latency_preemption_df(td.pid) + if prt_df is not None: + prt_df.rename(columns={'preempt_latency' : 'latency'}, inplace=True) + logging.info("Found: %5d PREEMPT latencies", len(prt_df)) + + if wkp_df is None and prt_df is None: + logging.warning("No Latency info for task [{}]".format(td.label)) + return + + # Join the two data frames + df = wkp_df.append(prt_df) + ymax = 1.1 * df.latency.max() + logging.info("Total: %5d latency events", len(df)) + + df = pd.DataFrame(sorted(df.latency), columns=['latency']) + + # Setup plots + gs = gridspec.GridSpec(2, 2, height_ratios=[2,1], width_ratios=[1,1]) + plt.figure(figsize=(16, 8)) + + plot_title = "Task [{}] latencies".format(kind.upper()) + if tag: + plot_title = "{} [{}]".format(plot_title, tag) + plot_title = "{}, threshold @ {} [ms]".format(plot_title, threshold_ms) + + # Latency events duration over time + axes = plt.subplot(gs[0,0:2]) + axes.set_title(plot_title) + try: + wkp_df.rename(columns={'latency': 'wakeup'}, inplace=True) + wkp_df.plot(style='b+', logy=True, ax=axes) + except: pass + try: + prt_df.rename(columns={'latency' : 'preempt'}, inplace=True) + prt_df.plot(style='r+', logy=True, ax=axes) + except: pass + axes.axhline(threshold_ms / 1000., linestyle='--', color='g') + self._trace.analysis.status.plotOverutilized(axes) + axes.legend(loc='lower center', ncol=2) + + # Cumulative distribution of all latencies + axes = plt.subplot(gs[1,0]) + df.latency.plot(ax=axes, logy=True, legend=False, + title='Latencies cumulative distribution [{}]'\ + .format(td.label)) + axes.axhline(y=threshold_ms / 1000., linewidth=2, + color='r', linestyle='--') + + # Histogram of all latencies + axes = plt.subplot(gs[1,1]) + df.latency.plot(kind='hist', bins=64, ax=axes, + xlim=(0,ymax), legend=False, + title='Latency histogram (64 bins, {} [ms] green threshold)'\ + .format(threshold_ms)); + axes.axvspan(0, threshold_ms / 1000., facecolor='g', alpha=0.5); + + # Save generated plots into datadir + task_name = re.sub('[\ :/]', '_', td.label) + figname = '{}/{}task_latencies_{}_{}.png'\ + .format(self._trace.plots_dir, self._trace.plots_prefix, + td.pid, task_name) + pl.savefig(figname, bbox_inches='tight') + + # Return statistics + return df.describe(percentiles=[0.95, 0.99]) + + def plotLatencyBands(self, task, axes=None): + """ + Draw a plot that shows intervals of time when the execution of a + RUNNABLE task has been delayed. The plot reports: + WAKEUP lantecies as RED colored bands + PREEMPTION lantecies as BLUE colored bands + + The optional axes parameter allows to plot the signal on an existing + graph. + + :param task: the task to report latencies for + :type task: str + + :param axes: axes on which to plot the signal + :type axes: :mod:`matplotlib.axes.Axes` + """ + if not self._trace.hasEvents('sched_switch'): + logging.warn('Event [sched_switch] not found, ' + 'plot DISABLED!') + return + if not self._trace.hasEvents('sched_wakeup'): + logging.warn('Event [sched_wakeup] not found, ' + 'plot DISABLED!') + return + + # Get task PID + td = self._getTaskData(task) + if not td: + return None + + wkl_df = self._dfg_latency_wakeup_df(td.pid) + prt_df = self._dfg_latency_preemption_df(td.pid) + + if wkl_df is None and prt_df is None: + logging.warning("No task with name [{}]".format(td.label)) + return + + # If not axis provided: generate a standalone plot + if not axes: + gs = gridspec.GridSpec(1, 1) + plt.figure(figsize=(16, 2)) + axes = plt.subplot(gs[0, 0]) + axes.set_title('Latencies on [{}] ' + '(red: WAKEUP, blue: PREEMPT)'\ + .format(td.label)) + axes.set_xlim(self._trace.x_min, self._trace.x_max) + axes.set_yticklabels([]) + axes.set_xlabel('Time [s]') + axes.grid(True) + + # Draw WAKEUP latencies + try: + bands = [(t, wkl_df['wakeup_latency'][t]) for t in wkl_df.index] + for (start, duration) in bands: + end = start + duration + axes.axvspan(start, end, facecolor='r', alpha=0.1) + except: pass + + # Draw PREEMPTION latencies + try: + bands = [(t, prt_df['preempt_latency'][t]) for t in prt_df.index] + for (start, duration) in bands: + end = start + duration + axes.axvspan(start, end, facecolor='b', alpha=0.1) + except: pass + + +############################################################################### +# Utility Methods +############################################################################### + + @memoized + def _getTaskData(self, task): + + # Get task PID + if isinstance(task, str): + task_pids = self._trace.getTaskByName(task) + if len(task_pids) == 0: + logging.warning("No tasks found with name [%s]", task) + return None + + task_pid = task_pids[0] + if len(task_pids) > 1: + logging.warning("Multiple PIDs for task named [%s]", task) + for pid in task_pids: + logging.warning(" %5d : %s", pid, + ','.join(self._trace.getTaskByPid(pid))) + logging.warning("Returning stats only for PID: %d", + task_pid) + task_names = self._trace.getTaskByPid(task_pid) + + # Get task name + elif isinstance(task, int): + task_pid = task + task_names = self._trace.getTaskByPid(task_pid) + if len(task_names) == 0: + logging.warning("No tasks found with name [%s]", task) + return None + + else: + raise ValueError("Task must be either an int or str") + + task_label = "{}: {}".format(task_pid, ', '.join(task_names)) + return TaskData(task_pid, task_names, task_label) + + @memoized + def _taskState(self, state): + + # Tasks STATE flags (Linux 4.8) + TASK_STATES = { + 0: "R", # TASK_RUNNING + 1: "S", # TASK_INTERRUPTIBLE + 2: "D", # TASK_UNINTERRUPTIBLE + 4: "T", # __TASK_STOPPED + 8: "t", # __TASK_TRACED + 16: "X", # EXIT_DEAD + 32: "Z", # EXIT_ZOMBIE + 64: "x", # TASK_DEAD + 128: "K", # TASK_WAKEKILL + 256: "W", # TASK_WAKING + 512: "P", # TASK_PARKED + 1024: "N", # TASK_NOLOAD + 2048: "n", # TASK_NEW + } + TASK_MAX_STATE = 4096 + + res = "R" + if state & (TASK_MAX_STATE - 1) != 0: + res = "" + for key in TASK_STATES.keys(): + if key & state: + res += TASK_STATES[key] + if state & TASK_MAX_STATE: + res += "+" + else: + res = '|'.join(res) + return res + +# vim :set tabstop=4 shiftwidth=4 expandtab