EAS Testing - YouTube on Android

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


Populating the interactive namespace from numpy and matplotlib

In [3]:
# Set it to your local CATAPULT home folder
CATAPULT_HOME = "/home/pippo/work/catapult"

Test Environment set up

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


adbd is already running as 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


2016-04-12 15:20:10,656 INFO    :         Target - Using base path: /home/pippo/work/lisa
2016-04-12 15:20:10,657 INFO    :         Target - Loading custom (inline) target configuration
2016-04-12 15:20:10,658 INFO    :         Target - Loading custom (inline) test configuration
2016-04-12 15:20:10,659 INFO    :         Target - Devlib modules to load: ['bl', 'cpufreq']
2016-04-12 15:20:10,660 INFO    :         Target - Connecting Android target [DEFAULT]
2016-04-12 15:20:11,142 INFO    :         Target - Initializing target workdir:
2016-04-12 15:20:11,144 INFO    :         Target -    /data/local/tmp/devlib-target
2016-04-12 15:20:13,757 INFO    :         Target - Topology:
2016-04-12 15:20:13,759 INFO    :         Target -    [[0, 1, 2, 3], [4, 5]]
2016-04-12 15:20:14,399 INFO    :         FTrace - Enabled tracepoints:
2016-04-12 15:20:14,400 INFO    :         FTrace -   sched_switch
2016-04-12 15:20:14,401 INFO    :         FTrace -   sched_load_avg_cpu
2016-04-12 15:20:14,402 INFO    :         FTrace -   cpu_frequency
2016-04-12 15:20:14,402 INFO    :         FTrace -   cpu_capacity
2016-04-12 15:20:14,403 WARNING :        TestEnv - Wipe previous contents of the results folder:
2016-04-12 15:20:14,404 WARNING :        TestEnv -    /home/pippo/work/lisa/results/Android_Youtube
2016-04-12 15:20:14,434 INFO    :        TestEnv - Set results folder to:
2016-04-12 15:20:14,435 INFO    :        TestEnv -    /home/pippo/work/lisa/results/Android_Youtube
2016-04-12 15:20:14,435 INFO    :        TestEnv - Experiment results available also in:
2016-04-12 15:20:14,435 INFO    :        TestEnv -    /home/pippo/work/lisa/results_latest

Support Functions

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
    }

Run experiments and collect traces


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)


2016-04-12 15:20:15,080 INFO    : ------------------------
2016-04-12 15:20:15,081 INFO    : Run workload using performance governor
2016-04-12 15:20:15,219 INFO    : SysTrace: /home/pippo/work/catapult/systrace/systrace/systrace.py -o /home/pippo/work/lisa/results/Android_Youtube/performance/trace.html gfx view sched freq idle -t 15
2016-04-12 15:20:37,068 INFO    : Waiting systrace report [/home/pippo/work/lisa/results/Android_Youtube/performance/trace.html]...
2016-04-12 15:20:42,981 INFO    : Parsing SysTrace format...
2016-04-12 15:20:44,844 INFO    : Collected events spans a 3.673 [s] time interval
2016-04-12 15:20:44,845 INFO    : Set plots time range to (0.000000, 3.672542)[s]
2016-04-12 15:20:45,134 INFO    : ------------------------
2016-04-12 15:20:45,135 INFO    : Run workload using interactive governor
2016-04-12 15:20:45,177 INFO    : SysTrace: /home/pippo/work/catapult/systrace/systrace/systrace.py -o /home/pippo/work/lisa/results/Android_Youtube/interactive/trace.html gfx view sched freq idle -t 15
2016-04-12 15:21:08,083 INFO    : Waiting systrace report [/home/pippo/work/lisa/results/Android_Youtube/interactive/trace.html]...
2016-04-12 15:21:25,486 INFO    : Parsing SysTrace format...
2016-04-12 15:21:27,296 INFO    : Collected events spans a 3.450 [s] time interval
2016-04-12 15:21:27,296 INFO    : Set plots time range to (0.000000, 3.449909)[s]

UI Performance Analysis


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 ""


Frame Statistics for PERFORMANCE governor
Stats since: 6429956328009ns
Total frames rendered: 549
Janky frames: 65 (11.84%)
90th percentile: 17ms
95th percentile: 34ms
99th percentile: 89ms

Frame Statistics for INTERACTIVE governor
Stats since: 6429956328009ns
Total frames rendered: 665
Janky frames: 88 (13.23%)
90th percentile: 18ms
95th percentile: 36ms
99th percentile: 89ms


In [14]:
trace_file = results['interactive']['trace']
!xdg-open {trace_file}