Skip to content

Instantly share code, notes, and snippets.

@jlelli
Last active July 9, 2018 08:06
Show Gist options
  • Save jlelli/a4846de091ccced685410d9bd317e348 to your computer and use it in GitHub Desktop.
Save jlelli/a4846de091ccced685410d9bd317e348 to your computer and use it in GitHub Desktop.
Test SCHED_DEADLINE with single rt-app task
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import logging\n",
"from conf import LisaLogging\n",
"LisaLogging.setup()\n",
"\n",
"# Uncomment the follwing line to enabled devlib debugging statements\n",
"# logging.getLogger('ssh').setLevel(logging.DEBUG)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Generate plots inline\n",
"%pylab inline\n",
"\n",
"import copy\n",
"import json\n",
"import os\n",
"import datetime\n",
"\n",
"# Support to access the remote target\n",
"import devlib\n",
"from env import TestEnv\n",
"\n",
"# Support to configure and run RTApp based workloads\n",
"from wlgen import RTA, Periodic, PerfMessaging\n",
"\n",
"# Support for performance analysis of RTApp workloads\n",
"from perf_analysis import PerfAnalysis\n",
"\n",
"# Support for trace events analysis\n",
"from trace import Trace\n",
"\n",
"# Suport for FTrace events parsing and visualization\n",
"import trappy\n",
"\n",
"import pandas as pd\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Test environment setup"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Setup a target configuration\n",
"conf = {\n",
" \n",
" # Target type\n",
" \"platform\" : 'linux',\n",
" \"board\" : \"hikey960\",\n",
" \n",
" # Login credentials\n",
" \"host\" : \"192.168.1.181\",\n",
"\n",
" # Binary tools required to run this experiment\n",
" # These tools must be present in the tools/ folder for the architecture\n",
" \"tools\" : ['rt-app', 'taskset', 'trace-cmd'],\n",
" \n",
" # Comment the following line to force rt-app calibration on your target\n",
" \"rtapp-calib\" : {\"0\": 304, \"1\": 304, \"2\": 304, \"3\": 304, \"4\": 136, \"5\": 136, \"6\": 136, \"7\": 136},\n",
" \n",
" # FTrace events end buffer configuration\n",
" \"ftrace\" : {\n",
" \"events\" : [\n",
" \"sched_switch\",\n",
" \"sched_wakeup_new\",\n",
" \"sched_wakeup\",\n",
" \"cpu_frequency\",\n",
" \"cpu_capacity\",\n",
" \"sched_load_avg_task\",\n",
" \"sched_load_cfs_rq\",\n",
" \"sched_load_dl_rq\"\n",
" ],\n",
" \"buffsize\" : 10240\n",
" },\n",
" \n",
" \"exclude_modules\" : [\n",
" 'hwmon'\n",
" ],\n",
"\n",
"\n",
" # Energy Meters Configuration for BayLibre's ACME Cape\n",
" \"emeter\" : {\n",
" \"instrument\" : \"acme\",\n",
" \"conf\" : {\n",
" #'iio-capture' : '/usr/bin/iio-capture',\n",
" 'ip_address' : '192.168.1.134',\n",
" },\n",
" 'channel_map' : {\n",
" 'Device0' : 0\n",
" }\n",
" },\n",
" \n",
" # Where results are collected\n",
" \"results_dir\" : datetime.datetime.today().strftime('%Y_%m_%d') + \"_rt-app-single\"\n",
" \n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"te = TestEnv(conf, force_new=True, wipe=True)\n",
"target = te.target"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"logging.info(\"Target ABI: %s, CPus: %s\",\n",
" target.abi,\n",
" target.cpuinfo.cpu_names)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"target.write_value('/proc/sys/kernel/sched_rt_runtime_us', -1)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"target.write_value('/sys/kernel/debug/sched_features', 'HRTICK', False)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Support functions"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"These are a set of functions to run a workload with different CPUFreq configurations"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def set_performance():\n",
" target.cpufreq.set_all_governors('performance')\n",
"\n",
"def set_powersave():\n",
" target.cpufreq.set_all_governors('powersave')\n",
"\n",
"def set_interactive():\n",
" target.cpufreq.set_all_governors('interactive')\n",
"\n",
"def set_schedutil():\n",
" target.cpufreq.set_all_governors('schedutil')\n",
"\n",
"def set_ondemand():\n",
" target.cpufreq.set_all_governors('ondemand') "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# CPUFreq configurations to test\n",
"confs = {\n",
"# 'performance' : {\n",
"# 'label' : 'prf',\n",
"# 'set' : set_performance,\n",
"# },\n",
"# 'powersave' : {\n",
"# 'label' : 'pws',\n",
"# 'set' : set_powersave,\n",
"# },\n",
" 'schedutil' : {\n",
" 'label' : 'sch',\n",
" 'set' : set_schedutil,\n",
" },\n",
"# 'ondemand' : {\n",
"# 'label' : 'odm',\n",
"# 'set' : set_ondemand,\n",
"# }\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"code_folding": []
},
"outputs": [],
"source": [
"def experiment(governor, rtapp, exp_dir, results, ftrace=True, energy=True):\n",
" os.system('mkdir -p {}'.format(exp_dir));\n",
"\n",
" logging.info('------------------------')\n",
" logging.info('Run workload using %s governor', governor)\n",
" confs[governor]['set']()\n",
"\n",
" # Start FTrace and Energy monitoring\n",
" if ftrace:\n",
" te.ftrace.start()\n",
" \n",
" if energy:\n",
" te.emeter.reset()\n",
" \n",
" # Run the workload\n",
" rtapp.run(out_dir=exp_dir)\n",
" \n",
" # Stop FTrace and sample Energy consumption\n",
" if energy:\n",
" nrg = te.emeter.report(exp_dir).channels\n",
" logging.info('Energy: %s', nrg)\n",
" results['energy'] = nrg['Device0']\n",
" \n",
" if ftrace:\n",
" te.ftrace.stop()\n",
" \n",
" # Dump platform description\n",
" te.platform_dump(exp_dir)\n",
" \n",
" # Collect and keep track of the trace\n",
" if ftrace:\n",
" trace_file = os.path.join(exp_dir, 'trace.dat')\n",
" te.ftrace.get_trace(trace_file)\n",
" \n",
" # Parse trace\n",
" tr = Trace(te.platform, exp_dir,\n",
" events=conf['ftrace']['events'])\n",
" results['trace'] = trace_file\n",
" results['tr'] = tr\n",
" results['ftrace'] = tr.ftrace\n",
" \n",
" results['dir'] = exp_dir\n",
" \n",
" return results\n",
"\n",
" \n",
"def compare(tid, tname, rtapp, governor, iteration, ftrace):\n",
" logging.info('Test case: %s', tid)\n",
" \n",
" res_dir = os.path.join(te.res_dir, tid)\n",
" logging.info(' results folder: %s', res_dir)\n",
" \n",
" # Run the workload in all the configured governors\n",
" results = {}\n",
" results['tid'] = tid\n",
" results['iter'] = iteration\n",
" results['governor'] = governor\n",
" test_dir = os.path.join(res_dir, governor, str(iteration))\n",
" experiment(governor, rtapp, test_dir, results, ftrace=ftrace)\n",
" deadline_miss_report(results, tname)\n",
" \n",
" return results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def deadline_miss(perf_file):\n",
" counter_miss = 0\n",
" counter_all = 0\n",
" with open(perf_file) as f:\n",
" next(f)\n",
" next(f)\n",
" for line in f:\n",
" counter_all+=1\n",
" parts = line.split() # split line into parts\n",
" #print \"Checking \", parts[7]\n",
" if '-' in parts[7]:\n",
" counter_miss+=1\n",
" \n",
" return counter_miss, counter_all"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def deadline_miss_report(results, tname):\n",
" dmiss, dall = deadline_miss(results['dir'] + '/rt-app-' + tname + '-0.log')\n",
" results['dmiss'] = dmiss\n",
" results['dall'] = dall"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# 10%-80% duty cycle (16ms period)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"iterations = 3\n",
"duration = 5 #s\n",
"duty_min = 10 #% w.r.t. period\n",
"duty_max = 40 #% w.r.t. period\n",
"period = 16 #ms\n",
"overprov = 20 #% of overprovisioning (w.r.t. runtime)\n",
"ftrace = True #might harm energy/perf\n",
"\n",
"results = []\n",
"\n",
"for duty in range(duty_min, duty_max + 1, 10):\n",
" # Define a label for this test case\n",
" test_case = 'single-task-' + str(duty)\n",
" task_name = 'task_p' + str(period)\n",
" period_us = period * 1000\n",
" duty_us = period_us / 100 * duty\n",
"\n",
" rtapp = RTA(target, 'smoke', calibration=te.calibration())\n",
" rtapp.conf(\n",
" kind = 'profile',\n",
" params = { \n",
" task_name : Periodic (\n",
" period_ms = period,\n",
" duty_cycle_pct = duty,\n",
" duration_s = duration,\n",
" sched = {\n",
" 'policy' : 'DEADLINE',\n",
" 'priority' : 0,\n",
" 'dl-period' : period_us,\n",
" 'dl-deadline' : period_us,\n",
" 'dl-runtime' : int(duty_us + float(duty_us)/100*overprov),\n",
" },\n",
" cpus = 4\n",
" ).get(),\n",
" },\n",
" );\n",
" \n",
" for governor in confs:\n",
" for it in range(iterations):\n",
" # Run this workload in all the configurations\n",
" results.append(compare(test_case, task_name, rtapp, governor, it, ftrace))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_res = pd.DataFrame(results)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_res['pmiss'] = df_res['dmiss'] / df_res['dall'] * 100"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_res.groupby(['tid','governor']).pmiss.describe()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"df_res.groupby(['tid','governor']).energy.describe()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kernelshark {results[6]['trace']} 2>/dev/null"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"results"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.15"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment