The goal of this experiment is to run Youtube videos on a Nexus N5X running Android with an EAS kernel and collect results. The Analysis phase will consist in comparing EAS with other schedulers, that is comparing sched governor with:
- interactive
- performance
- powersave
- ondemand
In [1]:
import logging
reload(logging)
log_fmt = '%(asctime)-9s %(levelname)-8s: %(message)s'
logging.basicConfig(format=log_fmt)
# Change to info once the notebook runs ok
logging.getLogger().setLevel(logging.INFO)
In [2]:
%pylab inline
import os
import pexpect as pe
from time import sleep
# Support to access the remote target
import devlib
from env import TestEnv
from devlib.utils.android import adb_command
# Support for trace events analysis
from trace import Trace
# Suport for FTrace events parsing and visualization
import trappy
In [3]:
# Set it to your local CATAPULT home folder
CATAPULT_HOME = "/home/pippo/work/catapult"
In case more than one Android device are conencted to the host, you must specify the ID of the device you want to target in my_target_conf
. Run adb devices
on your host to get the ID.
In [4]:
# Setup a target configuration
my_target_conf = {
# Target platform and board
"platform" : 'android',
# Add target support
"board" : 'n5x',
# Device ID
#"device" : "00b1346f0878ccb1",
# Define devlib modules to load
"modules" : [
'cpufreq' # enable CPUFreq support
],
}
In [5]:
my_tests_conf = {
# Folder where all the results will be collected
"results_dir" : "Android_Youtube",
# Platform configurations to test
"confs" : [
{
"tag" : "youtube",
"flags" : "ftrace", # Enable FTrace events
"sched_features" : "ENERGY_AWARE", # enable EAS
},
],
# FTrace events to collect for all the tests configuration which have
# the "ftrace" flag enabled
"ftrace" : {
"events" : [
"sched_switch",
"sched_load_avg_cpu",
"cpu_frequency",
"cpu_capacity"
],
"buffsize" : 10 * 1024,
},
# Tools required by the experiments
"tools" : [ 'trace-cmd' ],
}
In [6]:
# Ensure ADB has root priviledges, which are required by systrace
!adb root
In [7]:
# Initialize a test environment using:
# the provided target configuration (my_target_conf)
# the provided test configuration (my_test_conf)
te = TestEnv(target_conf=my_target_conf, test_conf=my_tests_conf)
target = te.target
This set of support functions will help us running the benchmark using different CPUFreq governors.
In [8]:
def set_performance():
target.cpufreq.set_all_governors('performance')
def set_powersave():
target.cpufreq.set_all_governors('powersave')
def set_interactive():
target.cpufreq.set_all_governors('interactive')
def set_sched():
target.cpufreq.set_all_governors('sched')
def set_ondemand():
target.cpufreq.set_all_governors('ondemand')
for cpu in target.list_online_cpus():
tunables = target.cpufreq.get_governor_tunables(cpu)
target.cpufreq.set_governor_tunables(
cpu,
'ondemand',
**{'sampling_rate' : tunables['sampling_rate_min']}
)
In [9]:
# CPUFreq configurations to test
confs = {
'performance' : {
'label' : 'prf',
'set' : set_performance,
},
#'powersave' : {
# 'label' : 'pws',
# 'set' : set_powersave,
#},
'interactive' : {
'label' : 'int',
'set' : set_interactive,
},
#'sched' : {
# 'label' : 'sch',
# 'set' : set_sched,
#},
#'ondemand' : {
# 'label' : 'odm',
# 'set' : set_ondemand,
#}
}
# The set of results for each comparison test
results = {}
In [10]:
YOUTUBE_CMD = 'shell dumpsys gfxinfo com.google.android.youtube > {}'
def youtube_run(exp_dir, video_url, video_duration_s):
# Unlock device screen (assume no password required)
target.execute('input keyevent 82')
# Press Back button to be sure we run the video from the start
target.execute('input keyevent KEYCODE_BACK')
# Start YouTube video on the target device
target.execute('am start -a android.intent.action.VIEW "{}"'.format(video_url))
# Allow the activity to start
sleep(3)
# Reset framestats collection
target.execute('dumpsys gfxinfo --reset')
# Wait until the end of the video
sleep(video_duration_s)
# Get frame stats
framestats_file = os.path.join(exp_dir, "framestats.txt")
adb_command(target.adb_name, YOUTUBE_CMD.format(framestats_file))
# Close application
target.execute('am force-stop com.google.android.youtube')
# Clear application data
target.execute('pm clear com.google.android.youtube')
return framestats_file
In [11]:
SYSTRACE_CMD = CATAPULT_HOME + "/systrace/systrace/systrace.py -o {} gfx view sched freq idle -t {}"
def experiment(governor, exp_dir, collect='ftrace', trace_time=30):
os.system('mkdir -p {}'.format(exp_dir));
logging.info('------------------------')
logging.info('Run workload using %s governor', governor)
confs[governor]['set']()
# Start the required tracing command
if 'ftrace' in collect:
# Start FTrace and Energy monitoring
te.ftrace.start()
elif 'systrace' in collect:
# Start systrace
trace_file = os.path.join(exp_dir, 'trace.html')
trace_cmd = SYSTRACE_CMD.format(trace_file, trace_time)
logging.info('SysTrace: %s', trace_cmd)
systrace_output = pe.spawn(trace_cmd)
### Run the benchmark ###
framestats_file = youtube_run(exp_dir, "https://youtu.be/XSGBVzeBUbk?t=45s", trace_time)
# Stop the required trace command
if 'ftrace' in collect:
te.ftrace.stop()
# Collect and keep track of the trace
trace_file = os.path.join(exp_dir, 'trace.dat')
te.ftrace.get_trace(trace_file)
elif 'systrace' in collect:
logging.info('Waiting systrace report [%s]...', trace_file)
systrace_output.wait()
# Parse trace
tr = Trace(te.platform, trace_file,
events=my_tests_conf['ftrace']['events'])
# return all the experiment data
return {
'dir' : exp_dir,
'framestats_file' : framestats_file,
'trace' : trace_file,
'ftrace' : tr.ftrace
}
In [12]:
# Run the benchmark in all the configured governors
for governor in confs:
test_dir = os.path.join(te.res_dir, governor)
results[governor] = experiment(governor, test_dir,
collect='systrace', trace_time=15)
In [13]:
for governor in confs:
framestats_file = results[governor]['framestats_file']
print "Frame Statistics for {} governor".format(governor.upper())
!sed '/Stats since/,/99th/!d;/99th/q' $framestats_file
print ""
In [14]:
trace_file = results['interactive']['trace']
!xdg-open {trace_file}