diff --git a/ipynb/tests/Frequency_Invariance_Test.ipynb b/ipynb/tests/Frequency_Invariance_Test.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..f14232522e4673304ebd4caeb4421877e7fdeb59 --- /dev/null +++ b/ipynb/tests/Frequency_Invariance_Test.ipynb @@ -0,0 +1,677 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Frequency Invariant Load Tracking Test\n", + "\n", + "FreqInvarianceTest is a LisaTest class for automated testing of frequency invariant load tracking. This notebook uses the methods it provides to perform the same analysis as the automated test and plot some results.\n", + "\n", + "The test class runs the same workload at a selection of frequencies, each entry in `t.experiments` represents a run at a different frequency." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import json\n", + "\n", + "from trace import Trace\n", + "from trappy.plotter import plot_trace\n", + "from trappy.stats.grammar import Parser\n", + "from trappy import ILinePlot" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2017-02-13 18:36:59,553 INFO : root : Using LISA logging configuration:\n", + "2017-02-13 18:36:59,554 INFO : root : /home/brendan/sources/lisa/logging.conf\n" + ] + } + ], + "source": [ + "import logging\n", + "from conf import LisaLogging\n", + "LisaLogging.setup()\n", + "logging.getLogger('Analysis').setLevel(logging.ERROR)\n", + "logging.getLogger('Trace').setLevel(logging.ERROR)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run test workload\n", + "\n", + "There's currently no way to pass a `TestEnv` or configuration to automated test classes. Instead the target information comes from the `target.config` file (in the root of the LISA source tree), so you'll need to edit that to configure LISA to connect to your target." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " Goal\n", + " ====\n", + " Basic check for frequency invariant load tracking\n", + "\n", + " Detailed Description\n", + " ====================\n", + " This test runs the same workload on the most capable CPU on the system at a\n", + " cross section of available frequencies. The trace is then examined to find\n", + " the average activation length of the workload, which is combined with the\n", + " known period to estimate an expected mean value for util_avg for each\n", + " frequency. The util_avg value is extracted from scheduler trace events and\n", + " its mean is compared with the expected value (ignoring the first 300ms so\n", + " that the signal can stabilize). The test fails if the observed mean is\n", + " beyond a certain error margin from the expected one. load_avg is then\n", + " similarly compared with the expected util_avg mean, under the assumption\n", + " that load_avg should equal util_avg when system load is light.\n", + "\n", + " Expected Behaviour\n", + " ==================\n", + " Load tracking signals are scaled so that the workload results in roughly the\n", + " same util & load values regardless of frequency.\n", + " \n" + ] + } + ], + "source": [ + "from tests.eas.load_tracking import FreqInvarianceTest\n", + "\n", + "t = FreqInvarianceTest()\n", + "print t.__doc__" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To run automated tests from within a notebook we instantiate the test class and call `runExperiments` on it." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2017-02-13 18:36:59,608 INFO : LisaTest : Setup tests execution engine...\n", + "2017-02-13 18:36:59,609 INFO : TestEnv : Using base path: /home/brejac01/sources/lisa\n", + "2017-02-13 18:36:59,610 INFO : TestEnv : Loading default (file) target configuration\n", + "2017-02-13 18:36:59,611 INFO : TestEnv : Loading target configuration [/home/brejac01/sources/lisa/target.config]...\n", + "2017-02-13 18:36:59,613 INFO : TestEnv : Loading custom (inline) test configuration\n", + "2017-02-13 18:36:59,614 INFO : TestEnv : Devlib modules to load: ['bl', u'cpuidle', 'cgroups', 'cpufreq']\n", + "2017-02-13 18:36:59,615 INFO : TestEnv : Connecting linux target:\n", + "2017-02-13 18:36:59,616 INFO : TestEnv : username : brendan\n", + "2017-02-13 18:36:59,617 INFO : TestEnv : host : 192.168.2.2\n", + "2017-02-13 18:36:59,618 INFO : TestEnv : password : password\n", + "2017-02-13 18:36:59,618 INFO : TestEnv : Connection settings:\n", + "2017-02-13 18:36:59,619 INFO : TestEnv : {'username': u'brendan', 'host': u'192.168.2.2', 'password': u'password'}\n", + "2017-02-13 18:37:07,367 INFO : TestEnv : Initializing target workdir:\n", + "2017-02-13 18:37:07,369 INFO : TestEnv : /home/brendan/devlib-target\n", + "2017-02-13 18:37:11,034 INFO : CGroups : Available controllers:\n", + "2017-02-13 18:37:12,775 INFO : CGroups : cpuset : /home/brendan/devlib-target/cgroups/devlib_cgh2\n", + "2017-02-13 18:37:14,512 INFO : CGroups : cpu : /home/brendan/devlib-target/cgroups/devlib_cgh3\n", + "2017-02-13 18:37:16,249 INFO : CGroups : cpuacct : /home/brendan/devlib-target/cgroups/devlib_cgh3\n", + "2017-02-13 18:37:17,988 INFO : CGroups : blkio : /home/brendan/devlib-target/cgroups/devlib_cgh4\n", + "2017-02-13 18:37:19,726 INFO : CGroups : memory : /home/brendan/devlib-target/cgroups/devlib_cgh5\n", + "2017-02-13 18:37:21,465 INFO : CGroups : devices : /home/brendan/devlib-target/cgroups/devlib_cgh6\n", + "2017-02-13 18:37:23,205 INFO : CGroups : perf_event : /home/brendan/devlib-target/cgroups/devlib_cgh7\n", + "2017-02-13 18:37:24,944 INFO : CGroups : hugetlb : /home/brendan/devlib-target/cgroups/devlib_cgh8\n", + "2017-02-13 18:37:26,682 INFO : CGroups : pids : /home/brendan/devlib-target/cgroups/devlib_cgh9\n", + "2017-02-13 18:37:29,594 INFO : TestEnv : Topology:\n", + "2017-02-13 18:37:29,596 INFO : TestEnv : [[0, 3, 4, 5], [1, 2]]\n", + "2017-02-13 18:37:32,227 INFO : TestEnv : Loading default EM:\n", + "2017-02-13 18:37:32,229 INFO : TestEnv : /home/brejac01/sources/lisa/libs/utils/platforms/juno.json\n", + "2017-02-13 18:37:33,996 WARNING : LinuxTarget : Event [sched_load_avg_task] not available for tracing\n", + "2017-02-13 18:37:33,999 WARNING : LinuxTarget : Event [sched_load_avg_cpu] not available for tracing\n", + "2017-02-13 18:37:34,001 INFO : TestEnv : Enabled tracepoints:\n", + "2017-02-13 18:37:34,002 INFO : TestEnv : sched_switch\n", + "2017-02-13 18:37:34,003 INFO : TestEnv : sched_load_avg_task\n", + "2017-02-13 18:37:34,004 INFO : TestEnv : sched_load_avg_cpu\n", + "2017-02-13 18:37:34,006 INFO : TestEnv : sched_pelt_se\n", + "2017-02-13 18:37:34,007 WARNING : TestEnv : Using configuration provided RTApp calibration\n", + "2017-02-13 18:37:34,008 INFO : TestEnv : Using RT-App calibration values:\n", + "2017-02-13 18:37:34,010 INFO : TestEnv : {\"0\": 354, \"1\": 138, \"2\": 138, \"3\": 363, \"4\": 355, \"5\": 357}\n", + "2017-02-13 18:37:34,011 INFO : EnergyMeter : HWMON module not enabled\n", + "2017-02-13 18:37:34,012 WARNING : EnergyMeter : Energy sampling disabled by configuration\n", + "2017-02-13 18:37:34,013 INFO : TestEnv : Set results folder to:\n", + "2017-02-13 18:37:34,015 INFO : TestEnv : /home/brejac01/sources/lisa/results/20170213_183734\n", + "2017-02-13 18:37:34,016 INFO : TestEnv : Experiment results available also in:\n", + "2017-02-13 18:37:34,017 INFO : TestEnv : /home/brejac01/sources/lisa/results_latest\n", + "2017-02-13 18:37:34,018 INFO : Executor : Loading custom (inline) test configuration\n", + "2017-02-13 18:37:34,019 INFO : Executor : \n", + "2017-02-13 18:37:34,020 INFO : Executor : ################################################################################\n", + "2017-02-13 18:37:34,022 INFO : Executor : Experiments configuration\n", + "2017-02-13 18:37:34,023 INFO : Executor : ################################################################################\n", + "2017-02-13 18:37:34,024 INFO : Executor : Configured to run:\n", + "2017-02-13 18:37:34,025 INFO : Executor : 1 target configurations:\n", + "2017-02-13 18:37:34,026 INFO : Executor : freq_450000\n", + "2017-02-13 18:37:34,027 INFO : Executor : 1 workloads (1 iterations each)\n", + "2017-02-13 18:37:34,028 INFO : Executor : fie_10pct\n", + "2017-02-13 18:37:34,029 INFO : Executor : Total: 1 experiments\n", + "2017-02-13 18:37:34,030 INFO : Executor : Results will be collected under:\n", + "2017-02-13 18:37:34,031 INFO : Executor : /home/brejac01/sources/lisa/results/20170213_183734\n", + "2017-02-13 18:37:34,032 INFO : Executor : rt-app workloads found, installing tool on target\n", + "2017-02-13 18:37:34,033 INFO : LisaTest : Experiments execution...\n", + "2017-02-13 18:37:34,034 INFO : Executor : \n", + "2017-02-13 18:37:34,035 INFO : Executor : ################################################################################\n", + "2017-02-13 18:37:34,036 INFO : Executor : Experiments execution\n", + "2017-02-13 18:37:34,037 INFO : Executor : ################################################################################\n", + "2017-02-13 18:37:34,038 INFO : Executor : \n", + "2017-02-13 18:37:34,039 INFO : Executor : ================================================================================\n", + "2017-02-13 18:37:34,040 INFO : Executor : configuring target for [freq_450000] experiments\n", + "2017-02-13 18:37:35,760 INFO : Executor : Configuring all CPUs to use [userspace] cpufreq governor\n", + "2017-02-13 18:37:36,666 INFO : Executor : CPUFreq - CPU frequencies: {1: 450000}\n", + "2017-02-13 18:37:38,683 INFO : Workload : Setup new workload fie_10pct\n", + "2017-02-13 18:37:38,685 INFO : Workload : Workload duration defined by longest task\n", + "2017-02-13 18:37:38,686 INFO : Workload : Default policy: SCHED_OTHER\n", + "2017-02-13 18:37:38,687 INFO : Workload : ------------------------\n", + "2017-02-13 18:37:38,688 INFO : Workload : task [fie_test0], sched: using default policy\n", + "2017-02-13 18:37:38,689 INFO : Workload : | calibration CPU: 1\n", + "2017-02-13 18:37:38,691 INFO : Workload : | loops count: 1\n", + "2017-02-13 18:37:38,692 INFO : Workload : + phase_000001: duration 1.000000 [s] (62 loops)\n", + "2017-02-13 18:37:38,693 INFO : Workload : | period 16000 [us], duty_cycle 10 %\n", + "2017-02-13 18:37:38,694 INFO : Workload : | run_time 1600 [us], sleep_time 14400 [us]\n", + "2017-02-13 18:37:39,836 INFO : Executor : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n", + "2017-02-13 18:37:39,838 INFO : Executor : Experiment 0/1, [freq_450000:fie_10pct] 1/1\n", + "2017-02-13 18:37:40,255 WARNING : Executor : No freezer cgroup controller on target. Not freezing userspace\n", + "2017-02-13 18:37:40,257 WARNING : Executor : FTrace events collection enabled\n", + "2017-02-13 18:37:46,898 INFO : Workload : Workload execution START:\n", + "2017-02-13 18:37:46,899 INFO : Workload : /home/brendan/devlib-target/bin/taskset 0x2 /home/brendan/devlib-target/bin/rt-app /home/brendan/devlib-target/run_dir/fie_10pct_00.json 2>&1\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2017-02-13 18:37:54,459 INFO : Executor : Collected FTrace binary trace:\n", + "2017-02-13 18:37:54,460 INFO : Executor : /rtapp:freq_450000:fie_10pct/1/trace.dat\n", + "2017-02-13 18:37:54,461 INFO : Executor : Collected FTrace function profiling:\n", + "2017-02-13 18:37:54,463 INFO : Executor : /rtapp:freq_450000:fie_10pct/1/trace_stat.json\n", + "2017-02-13 18:37:54,463 INFO : Executor : --------------------------------------------------------------------------------\n", + "2017-02-13 18:37:54,464 INFO : Executor : \n", + "2017-02-13 18:37:54,465 INFO : Executor : ################################################################################\n", + "2017-02-13 18:37:54,467 INFO : Executor : Experiments execution completed\n", + "2017-02-13 18:37:54,467 INFO : Executor : ################################################################################\n", + "2017-02-13 18:37:54,468 INFO : Executor : Results available in:\n", + "2017-02-13 18:37:54,469 INFO : Executor : /home/brejac01/sources/lisa/results/20170213_183734\n" + ] + } + ], + "source": [ + "t.runExperiments()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Show variance in util_avg and load_avg\n", + "We want to see the same util_avg and load_avg values regardless of frequencies - the bar charts below should have bars all with roughly the same height." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [], + "source": [ + "# Get the frequency an experiment was run at\n", + "def experiment_freq(exp):\n", + " [cpu] = exp.wload.cpus\n", + " freq = exp.conf['cpufreq']['freqs'][cpu]\n", + " return freq\n", + "freqs = [experiment_freq(e) for e in t.experiments]" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def plot_signal_against_freq(signal):\n", + " means = [t.get_signal_mean(e, signal) for e in t.experiments]\n", + " limits = (0 , max(means) * 1.15)\n", + " pd.DataFrame(means, index=freqs, columns=['Mean ' + signal]).plot(kind='bar', ylim=limits)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot of variation of util_avg value with frequency:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "['sched_switch', 'sched_pelt_se']" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.get_trace(t.experiments[0]).available_events" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nrkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_signal_against_freq('util_avg')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### And the same thing for load_avg:" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXIAAAEWCAYAAAB7QRxFAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAFHVJREFUeJzt3XuQVNWBx/FvA44LysCMGF7DQzQmYh5iXDUWFh2NCrso\nJFZ4lUoemgqWiWjFDeyW7FhGo64uJqVYm41JoRVIGZdVMSGiYIOVZMFC44OHo5YgoCCB4SUIjJz9\n4zbNzDAwQ08304f5fqq6+t5zX8dx+jeHc889DZIkSZIkSZIkSZIkSZIkSUcldawvOGzYsLBo0aJj\nfVlJit0iIN3UhuaC/NfAPwMfAV/Mlv0HMBLYC7wLfAfYlt02Ffgu8CnwI2B+E+cMIYSWV106hqqr\nq6murm7rakiHSKVScJjM7tDMsb8Bhjcqmw+cDXwZqCEJb4DBwNjs+3BgRgvOL0lqpeaC9iWgtlHZ\n88D+7PISoCq7PAqYDewDVgPvAOcXpJaSpMNqbYv5u8Afs8t9gHX1tq0D+rby/NIxlU6n27oK0lHr\n1Ipj/42kn3zWEfZpsjO8fh9kOp32w6OS4e+iSkUmkyGTybRo35aMWhkIzOXgzU6AbwM3AJcCn2TL\npmTf78m+/wn4d5Lul/q82SnVU1lZSW1t4x5MtVcVFRVs2bLlkPIj3ezMp0U+HLgNGMbBEAd4hqR1\n/p8kXSqfBZbmcX6pXamtrcXGjQ7IBvZRaS7IZ5MEdg9gLUkLeypQRnLTE+CvwI3ACuCJ7Htdtszf\nTkkqsmP+QBB2rUgNpFIpW+TKOdzvQ2vGkUuSSpxBLikamUyGfv36FeXcAwcOZMGCBUU5d7EZ5FKJ\nKS+vJJVKFe1VXl7Z4roMHDiQE088kc2bNzcoHzJkCB06dOD9998v9H9+mznw84mRQS6VmB07aknG\nCRTnlZy/ZVKpFIMGDWL27Nm5sjfeeIPdu3dHG3rHI4Nc0hFdc801PPbYY7n1mTNnct111zW4Ibdn\nzx5+/OMfM2DAAHr16sWkSZP45JNkdPLWrVsZOXIkn/nMZ6isrOTKK69k/fr1uWPT6TTTpk1j6NCh\nlJeXc8UVVxzyL4DDWblyJel0moqKCr7whS8wd+7c3LY//OEPDBkyhG7dutG/f3/uuOOOBsc+/vjj\nDBgwgB49enD33Xe36HpLly7lq1/9KhUVFfTp04cf/vCH7Nu3D4BJkyZx2223Ndh/1KhRTJ8+HYBX\nXnmFIUOGUF5ezpgxYxg7diy33357i65bioKkgxp/JoAAoYivln8GBw4cGF544YXwuc99LqxcuTLU\n1dWFqqqqsGbNmpBKpcKaNWtCCCFMnjw5jBo1KtTW1oYdO3aEK6+8MkydOjWEEMLmzZvDnDlzwu7d\nu8OOHTvCt771rTB69OjcNYYNGxbOOOOM8Pbbb4fdu3eHdDodpkyZ0mR9XnzxxVBVVRVCCGHv3r3h\n9NNPDz/72c/Cvn37wsKFC0PXrl3DW2+9FUIIIZPJhDfffDOEEMLrr78eevbsGZ566qkQQgjLly8P\nJ598cnjppZfCnj17wq233ho6deoUFixYcMSfx7Jly8KSJUvCp59+GlavXh3OOuus8OCDD4YQQli8\neHHo169fbt8tW7aEzp07hw8//DDs2bMn9O/fP/ziF78IdXV1Yc6cOaGsrCzcfvvth1zjcP9/KLHh\n3Ef8QUntTePPBCUY5D/96U/D1KlTw7x588Lll18e6urqckG+f//+cNJJJ4V33303d9xf/vKXcNpp\npzV5zldffTVUVFTk1tPpdLjrrrty6zNmzAjDhw9v8tj6Qb548eLQq1evBtvHjx8fqqurmzz25ptv\nDrfccksIIYQ77rgjjB8/Prft448/DmVlZc0GeWPTp08P3/jGN0IIIezfvz/0798/LF68OIQQwi9/\n+ctw6aWXhhBCWLRoUejbt2+DY4cOHVqwIG/NXCuS2oFUKsW1117LxRdfzHvvvXdIt8qmTZvYtWsX\nX/nKV3JlIQT2708mSd21axe33HILzz33XG4qgp07dxJCyPWz9+rVK3ds586d2blzZ7P1+uCDDw4Z\nwTJgwIBct82SJUuYMmUKy5cvZ+/evezZs4cxY8bkjq2qqsod16VLF0455ZRmr1lTU8Ott97KsmXL\n2LVrF3V1dZx33nm5n9O4ceOYPXs2F198MbNmzeK6667LXa9v34ZzCPbr169gzw/YRy6pWf3792fQ\noEHMmzePb37zmw229ejRg86dO7NixQpqa2upra1l69atbN++HYAHHniAmpoali5dyrZt21i0aBEh\nhFaHWJ8+fVi7dm2D86xZsyYX0BMmTGD06NGsW7eOrVu38oMf/CC374FjD9i1a1eL+uUnTZrE4MGD\neeedd9i2bRt33XVX7g8WwPjx43nyySdZs2YNS5cu5eqrrwagd+/eDe4LALz//vsFu2FskEtqkUcf\n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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_signal_against_freq('load_avg')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Examine trace from workload execution" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Plot task residency and `sched_util` and `sched_load` for the workload task, along with the expected mean value for util_avg. Note that assuming the system was under little load, so that the task was RUNNING whenever it was RUNNABLE, `load_avg` and `util_avg` should be the same. \n", + "\n", + "Call `examine_experiment` with different experiment indexes to get plots for runs at different frequencies." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "signals = ['util_avg', 'load_avg']\n", + "def examine_experiment(idx):\n", + " experiment = t.experiments[idx]\n", + " \n", + " [freq] = experiment.conf['cpufreq']['freqs'].values()\n", + " print \"Experiment ran at frequency {}\".format(freq)\n", + " events = t.te.test_conf[\"ftrace\"][\"events\"]\n", + " \n", + " # todo add get_trace method\n", + " tasks = experiment.wload.tasks.keys()\n", + " #trace = Trace(t.te.platform, experiment.out_dir, events, tasks)\n", + " print 'Trace plot:'\n", + " plot_trace(t.get_trace(experiment).ftrace)\n", + " \n", + " # Get observed signal\n", + " signal_df = t.get_sched_task_signals(experiment, signals)\n", + " # Get expected average value for util_avg signal\n", + " expected_util_avg_mean = t.get_expected_util_avg(experiment)\n", + " \n", + " # Plot task util_avg signal with expected mean value\n", + " util_avg_mean = pd.Series([expected_util_avg_mean], name='expected_util_avg', index=[signal_df.index[0]])\n", + " df = pd.concat([signal_df, util_avg_mean], axis=1).ffill()\n", + " ILinePlot(df, column=signals + ['expected_util_avg'], drawstyle='steps-post',\n", + " title='Scheduler task signals').view()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Experiment 0: 450000Hz\n" + ] + } + ], + "source": [ + "for i , f in enumerate(freqs):\n", + " print \"Experiment {}:{:10d}Hz\".format(i, f)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Experiment ran at frequency 450000\n", + "Trace plot:\n" + ] + }, + { + "data": { + "text/html": [ + "\n", + "
\n", + "\n", + "\n", + "\n", + " \n", + "
" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
Scheduler task signals
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " " + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "examine_experiment(0)" + ] + } + ], + "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.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/tests/eas/load_tracking.py b/tests/eas/load_tracking.py new file mode 100644 index 0000000000000000000000000000000000000000..c4f71475dc2778a5c9f4ef26456c6ca3f63165d9 --- /dev/null +++ b/tests/eas/load_tracking.py @@ -0,0 +1,226 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2016, 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. +# + +from bart.common.Utils import select_window, area_under_curve +from devlib.utils.misc import memoized +from trappy.stats.grammar import Parser +import pandas as pd + +from test import LisaTest, experiment_test + +UTIL_SCALE = 1024 +# Time in seconds to allow for util_avg to converge (i.e. ignored time) +UTIL_AVG_CONVERGENCE_TIME = 0.3 +# Allowed margin between expected and observed util_avg value +ERROR_MARGIN_PCT = 15 + +class FreqInvarianceTest(LisaTest): + """ + Goal + ==== + Basic check for frequency invariant load tracking + + Detailed Description + ==================== + This test runs the same workload on the most capable CPU on the system at a + cross section of available frequencies. The trace is then examined to find + the average activation length of the workload, which is combined with the + known period to estimate an expected mean value for util_avg for each + frequency. The util_avg value is extracted from scheduler trace events and + its mean is compared with the expected value (ignoring the first 300ms so + that the signal can stabilize). The test fails if the observed mean is + beyond a certain error margin from the expected one. load_avg is then + similarly compared with the expected util_avg mean, under the assumption + that load_avg should equal util_avg when system load is light. + + Expected Behaviour + ================== + Load tracking signals are scaled so that the workload results in roughly the + same util & load values regardless of frequency. + """ + + test_conf = { + 'tools' : [ 'rt-app' ], + 'ftrace' : { + 'events' : [ + 'sched_switch', + 'sched_load_avg_task', + 'sched_load_avg_cpu', + 'sched_pelt_se', + ], + }, + # cgroups required by freeze_userspace flag + 'modules': ['cpufreq', 'cgroups'], + } + + @classmethod + def setUpClass(cls, *args, **kwargs): + super(FreqInvarianceTest, cls).runExperiments(*args, **kwargs) + + @memoized + @classmethod + def _get_cpu(cls, target): + # Run on a 'big' CPU, or any CPU if not big.LITTLE + if hasattr(target, 'bl'): + return target.bl.bigs[0] + else: + return 0 + + @classmethod + def _getExperimentsConf(cls, test_env): + cpu = cls._get_cpu(test_env.target) + + # 10% periodic RTApp workload: + wloads = { + 'fie_10pct' : { + 'type' : 'rt-app', + 'conf' : { + 'class' : 'periodic', + 'params' : { + 'duty_cycle_pct': 10, + 'duration_s': 1, + 'period_ms': 16, + }, + 'tasks' : 1, + 'prefix' : 'fie_test', + 'cpus' : [cpu] + }, + }, + } + + # Create a set of confs with different frequencies + # We'll run the 10% workload under each conf (i.e. at each frequency) + confs = [] + + all_freqs = test_env.target.cpufreq.list_frequencies(cpu) + # If we have loads of frequencies just test a cross-section so it + # doesn't take all day + cls.freqs = all_freqs[::len(all_freqs)/8 + 1] + for freq in cls.freqs: + confs.append({ + 'tag' : 'freq_{}'.format(freq), + 'flags' : ['ftrace', 'freeze_userspace'], + 'cpufreq' : { + 'freqs' : {cpu: freq}, + 'governor' : 'userspace', + }, + }) + + return { + 'wloads': wloads, + 'confs': confs, + } + + def get_expected_util_avg(self, experiment): + """ + Examine trace to figure out an expected mean for util_avg + + Assumes an RT-App workload with a single task with a single phase, + running on a CPU with the highest max capacity in the system + + This takes into account the frequency the workload was run at, but + doesn't use the kernel's data for compute capacities at each frequency, + instead it assumes that these values scale linearly. + """ + [task] = experiment.wload.tasks.keys() + sched_assert = self.get_sched_assert(experiment, task) + + [freq] = experiment.conf['cpufreq']['freqs'].values() + freq_scaling_factor = float(freq) / max(self.freqs) + duty_cycle_pct = sched_assert.getDutyCycle(self.get_window(experiment)) + + return UTIL_SCALE * (duty_cycle_pct / 100.) * freq_scaling_factor + + def get_sched_task_signals(self, experiment, signals): + """ + Get a pandas.DataFrame with the sched signals for the workload task + + This examines scheduler load tracking trace events, supporting either + sched_load_avg_task or sched_pelt_se. You will need a target kernel that + includes these events. + + :param experiment: Experiment to get trace for + :param signals: List of load tracking signals to extract. Probably a + subset of ``['util_avg', 'load_avg']`` + :returns: :class:`pandas.DataFrame` with a column for each signal for + the experiment's workload task + """ + [task] = experiment.wload.tasks.keys() + trace = self.get_trace(experiment) + + # There are two different scheduler trace events that expose the load + # tracking signals. Neither of them is in mainline. Eventually they + # should be unified but for now we'll just check for both types of + # event. + # TODO: Add support for this parsing in Trappy and/or tasks_analysis + if 'sched_load_avg_task' in trace.available_events: + event = 'sched_load_avg_task' + elif 'sched_pelt_se' in trace.available_events: + event = 'sched_pelt_se' + else: + raise ValueError('No sched_load_avg_task or sched_pelt_se events. ' + 'Does the kernel support them?') + + df = getattr(trace.ftrace, event).data_frame + signals = df[df['comm'] == task][signals] + return select_window(signals, self.get_window(experiment)) + + def get_signal_mean(self, experiment, signal, + ignore_first_s=UTIL_AVG_CONVERGENCE_TIME): + """ + Get the mean of a scheduler signal for the experiment's task + + Ignore the first `ignore_first_s` seconds of the signal. + """ + (wload_start, wload_end) = self.get_window(experiment) + window = (wload_start + ignore_first_s, wload_end) + + signal = self.get_sched_task_signals(experiment, [signal])[signal] + signal = select_window(signal, window) + return area_under_curve(signal) / (window[1] - window[0]) + + def _test_signal(self, experiment, tasks, signal_name): + [task] = tasks + exp_util = self.get_expected_util_avg(experiment) + signal_mean = self.get_signal_mean(experiment, signal_name) + + error_margin = exp_util * (ERROR_MARGIN_PCT / 100.) + [freq] = experiment.conf['cpufreq']['freqs'].values() + + msg = 'Saw {} around {}, expected {} at freq {}'.format( + signal_name, signal_mean, exp_util, freq) + self.assertAlmostEqual(signal_mean, exp_util, delta=error_margin, + msg=msg) + + @experiment_test + def test_task_util_avg(self, experiment, tasks): + """ + Test that the mean of the util_avg signal matched the expected value + """ + return self._test_signal(experiment, tasks, 'util_avg') + + @experiment_test + def test_task_load_avg(self, experiment, tasks): + """ + Test that the mean of the load_avg signal matched the expected value + + Assuming that the system was under little stress (so the task was + RUNNING whenever it was RUNNABLE) and that the task was run with a + 'nice' value of 0, the load_avg should be similar to the util_avg. So, + this test does the same as test_task_util_avg but for load_avg. + """ + return self._test_signal(experiment, tasks, 'load_avg')