mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-31 18:21:14 +00:00
Remove existing applaunch workload
The applaunch workload is deprecated to be replaced by another implementation.
This commit is contained in:
parent
c38dc287ab
commit
bd37973442
@ -1,189 +0,0 @@
|
|||||||
# Copyright 2013-2015 ARM Limited
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
# pylint: disable=E1101
|
|
||||||
|
|
||||||
from __future__ import division
|
|
||||||
import os
|
|
||||||
|
|
||||||
try:
|
|
||||||
import jinja2
|
|
||||||
except ImportError:
|
|
||||||
jinja2 = None
|
|
||||||
|
|
||||||
from wlauto import Workload, settings, Parameter
|
|
||||||
from wlauto.exceptions import WorkloadError
|
|
||||||
from wlauto.utils.hwmon import discover_sensors
|
|
||||||
from wlauto.utils.misc import get_meansd
|
|
||||||
from wlauto.utils.types import boolean, identifier, list_of_strs
|
|
||||||
|
|
||||||
|
|
||||||
THIS_DIR = os.path.dirname(__file__)
|
|
||||||
TEMPLATE_NAME = 'device_script.template'
|
|
||||||
SCRIPT_TEMPLATE = os.path.join(THIS_DIR, TEMPLATE_NAME)
|
|
||||||
|
|
||||||
APP_CONFIG = {
|
|
||||||
'browser': {
|
|
||||||
'package': 'com.android.browser',
|
|
||||||
'activity': '.BrowserActivity',
|
|
||||||
'options': '-d about:blank',
|
|
||||||
},
|
|
||||||
'calculator': {
|
|
||||||
'package': 'com.android.calculator2',
|
|
||||||
'activity': '.Calculator',
|
|
||||||
'options': '',
|
|
||||||
},
|
|
||||||
'calendar': {
|
|
||||||
'package': 'com.android.calendar',
|
|
||||||
'activity': '.LaunchActivity',
|
|
||||||
'options': '',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class ApplaunchWorkload(Workload):
|
|
||||||
|
|
||||||
name = 'applaunch'
|
|
||||||
description = """
|
|
||||||
Measures the time and energy used in launching an application.
|
|
||||||
|
|
||||||
"""
|
|
||||||
supported_platforms = ['android']
|
|
||||||
|
|
||||||
parameters = [
|
|
||||||
Parameter('app', default='browser', allowed_values=['calculator', 'browser', 'calendar'],
|
|
||||||
description='The name of the application to measure.'),
|
|
||||||
Parameter('set_launcher_affinity', kind=bool, default=True,
|
|
||||||
description=('If ``True``, this will explicitly set the affinity of the launcher '
|
|
||||||
'process to the A15 cluster.')),
|
|
||||||
Parameter('times', kind=int, default=8,
|
|
||||||
description='Number of app launches to do on the device.'),
|
|
||||||
Parameter('measure_energy', kind=boolean, default=False,
|
|
||||||
description="""
|
|
||||||
Specfies wether energy measurments should be taken during the run.
|
|
||||||
|
|
||||||
.. note:: This depends on appropriate sensors to be exposed through HWMON.
|
|
||||||
|
|
||||||
"""),
|
|
||||||
Parameter('io_stress', kind=boolean, default=False,
|
|
||||||
description='Specifies whether to stress IO during App launch.'),
|
|
||||||
Parameter('io_scheduler', allowed_values=['noop', 'deadline', 'row', 'cfq', 'bfq'],
|
|
||||||
description='Set the IO scheduler to test on the device.'),
|
|
||||||
Parameter('cleanup', kind=boolean, default=True,
|
|
||||||
description='Specifies whether to clean up temporary files on the device.'),
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, device, **kwargs):
|
|
||||||
super(ApplaunchWorkload, self).__init__(device, **kwargs)
|
|
||||||
if not jinja2:
|
|
||||||
raise WorkloadError('Please install jinja2 Python package: "sudo pip install jinja2"')
|
|
||||||
filename = '{}-{}.sh'.format(self.name, self.app)
|
|
||||||
self.host_script_file = os.path.join(settings.meta_directory, filename)
|
|
||||||
self.device_script_file = os.path.join(self.device.working_directory, filename)
|
|
||||||
self._launcher_pid = None
|
|
||||||
self._old_launcher_affinity = None
|
|
||||||
self.sensors = []
|
|
||||||
|
|
||||||
def on_run_init(self, context): # pylint: disable=W0613
|
|
||||||
if self.measure_energy:
|
|
||||||
self.sensors = discover_sensors(self.device, ['energy'])
|
|
||||||
for sensor in self.sensors:
|
|
||||||
sensor.label = identifier(sensor.label).upper()
|
|
||||||
|
|
||||||
def setup(self, context):
|
|
||||||
self.logger.debug('Creating script {}'.format(self.host_script_file))
|
|
||||||
with open(self.host_script_file, 'w') as wfh:
|
|
||||||
env = jinja2.Environment(loader=jinja2.FileSystemLoader(THIS_DIR))
|
|
||||||
template = env.get_template(TEMPLATE_NAME)
|
|
||||||
wfh.write(template.render(device=self.device, # pylint: disable=maybe-no-member
|
|
||||||
sensors=self.sensors,
|
|
||||||
iterations=self.times,
|
|
||||||
io_stress=self.io_stress,
|
|
||||||
io_scheduler=self.io_scheduler,
|
|
||||||
cleanup=self.cleanup,
|
|
||||||
package=APP_CONFIG[self.app]['package'],
|
|
||||||
activity=APP_CONFIG[self.app]['activity'],
|
|
||||||
options=APP_CONFIG[self.app]['options'],
|
|
||||||
busybox=self.device.busybox,
|
|
||||||
))
|
|
||||||
self.device_script_file = self.device.install(self.host_script_file)
|
|
||||||
if self.set_launcher_affinity:
|
|
||||||
self._set_launcher_affinity()
|
|
||||||
self.device.clear_logcat()
|
|
||||||
|
|
||||||
def run(self, context):
|
|
||||||
self.device.execute('sh {}'.format(self.device_script_file), timeout=300, as_root=self.io_stress)
|
|
||||||
|
|
||||||
def update_result(self, context): # pylint: disable=too-many-locals
|
|
||||||
result_files = ['time.result']
|
|
||||||
result_files += ['{}.result'.format(sensor.label) for sensor in self.sensors]
|
|
||||||
metric_suffix = ''
|
|
||||||
if self.io_stress:
|
|
||||||
host_scheduler_file = os.path.join(context.output_directory, 'scheduler')
|
|
||||||
device_scheduler_file = '/sys/block/mmcblk0/queue/scheduler'
|
|
||||||
self.device.pull_file(device_scheduler_file, host_scheduler_file)
|
|
||||||
with open(host_scheduler_file) as fh:
|
|
||||||
scheduler = fh.read()
|
|
||||||
scheduler_used = scheduler[scheduler.index("[") + 1:scheduler.index("]")]
|
|
||||||
metric_suffix = '_' + scheduler_used
|
|
||||||
for filename in result_files:
|
|
||||||
self._extract_results_from_file(context, filename, metric_suffix)
|
|
||||||
|
|
||||||
def teardown(self, context):
|
|
||||||
if self.set_launcher_affinity:
|
|
||||||
self._reset_launcher_affinity()
|
|
||||||
if self.cleanup:
|
|
||||||
self.device.delete_file(self.device_script_file)
|
|
||||||
|
|
||||||
def _set_launcher_affinity(self):
|
|
||||||
try:
|
|
||||||
self._launcher_pid = self.device.get_pids_of('com.android.launcher')[0]
|
|
||||||
result = self.device.execute('taskset -p {}'.format(self._launcher_pid), busybox=True, as_root=True)
|
|
||||||
self._old_launcher_affinity = int(result.split(':')[1].strip(), 16)
|
|
||||||
|
|
||||||
cpu_ids = [i for i, x in enumerate(self.device.core_names) if x == 'a15']
|
|
||||||
if not cpu_ids or len(cpu_ids) == len(self.device.core_names):
|
|
||||||
self.logger.debug('Cannot set affinity.')
|
|
||||||
return
|
|
||||||
|
|
||||||
new_mask = reduce(lambda x, y: x | y, cpu_ids, 0x0)
|
|
||||||
self.device.execute('taskset -p 0x{:X} {}'.format(new_mask, self._launcher_pid), busybox=True, as_root=True)
|
|
||||||
except IndexError:
|
|
||||||
raise WorkloadError('Could not set affinity of launcher: PID not found.')
|
|
||||||
|
|
||||||
def _reset_launcher_affinity(self):
|
|
||||||
command = 'taskset -p 0x{:X} {}'.format(self._old_launcher_affinity, self._launcher_pid)
|
|
||||||
self.device.execute(command, busybox=True, as_root=True)
|
|
||||||
|
|
||||||
def _extract_results_from_file(self, context, filename, metric_suffix):
|
|
||||||
host_result_file = os.path.join(context.output_directory, filename)
|
|
||||||
device_result_file = self.device.path.join(self.device.working_directory, filename)
|
|
||||||
self.device.pull_file(device_result_file, host_result_file)
|
|
||||||
|
|
||||||
with open(host_result_file) as fh:
|
|
||||||
if filename == 'time.result':
|
|
||||||
values = [v / 1000 for v in map(int, fh.read().split())]
|
|
||||||
_add_metric(context, 'time' + metric_suffix, values, 'Seconds')
|
|
||||||
else:
|
|
||||||
metric = filename.replace('.result', '').lower()
|
|
||||||
numbers = iter(map(int, fh.read().split()))
|
|
||||||
deltas = [(after - before) / 1000000 for before, after in zip(numbers, numbers)]
|
|
||||||
_add_metric(context, metric, deltas, 'Joules')
|
|
||||||
|
|
||||||
|
|
||||||
def _add_metric(context, metric, values, units):
|
|
||||||
mean, sd = get_meansd(values)
|
|
||||||
context.result.add_metric(metric, mean, units)
|
|
||||||
context.result.add_metric(metric + ' sd', sd, units, lower_is_better=True)
|
|
@ -1,88 +0,0 @@
|
|||||||
#!{{ device.binaries_directory.rstrip('/') }}/sh
|
|
||||||
|
|
||||||
|
|
||||||
{% for sensor in sensors %}
|
|
||||||
GET_{{ sensor.label }}="cat {{ sensor.filepath }}"
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
LAUNCH_COMMAND="am start -W -n {{ package }}/{{ activity }} {{ options }}"
|
|
||||||
STOP_COMMAND="am force-stop {{ package }}"
|
|
||||||
TEMP_FILE=tmp.txt
|
|
||||||
|
|
||||||
TIME_RESULT=""
|
|
||||||
{% for sensor in sensors %}
|
|
||||||
{{ sensor.label }}=""
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
cd {{ device.working_directory }}
|
|
||||||
|
|
||||||
# esc esc down down down ENTER (this should bring up the apps menu)
|
|
||||||
input keyevent 111
|
|
||||||
sleep 1
|
|
||||||
input keyevent 111
|
|
||||||
sleep 1
|
|
||||||
input keyevent 20
|
|
||||||
sleep 1
|
|
||||||
input keyevent 20
|
|
||||||
sleep 1
|
|
||||||
input keyevent 20
|
|
||||||
sleep 1
|
|
||||||
input keyevent 66
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Warm up caches.
|
|
||||||
$LAUNCH_COMMAND
|
|
||||||
$STOP_COMMAND
|
|
||||||
$LAUNCH_COMMAND
|
|
||||||
$STOP_COMMAND
|
|
||||||
$LAUNCH_COMMAND
|
|
||||||
$STOP_COMMAND
|
|
||||||
|
|
||||||
{% if io_scheduler != None %}
|
|
||||||
echo {{ io_scheduler }} > /sys/block/mmcblk0/queue/scheduler
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
for i in $({{ busybox }} seq 1 {{ iterations }})
|
|
||||||
do
|
|
||||||
{% for sensor in sensors %}
|
|
||||||
{{ sensor.label }}="${{ sensor.label }} `$GET_{{ sensor.label }}`"
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% if io_stress %}
|
|
||||||
# Drop caches to get a cold start.
|
|
||||||
sync; echo 3 > /proc/sys/vm/drop_caches
|
|
||||||
# Run IO stress during App launch.
|
|
||||||
{{ busybox }} dd if=/dev/zero of=write.img bs=1048576 count=2000 conv=fsync > dd_write.txt 2>&1 &
|
|
||||||
io_write=$!
|
|
||||||
{{ busybox }} dd if=/dev/block/mmcblk0 of=/dev/null bs=1048576 > dd_read.txt 2>&1 &
|
|
||||||
io_read=$!
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
$LAUNCH_COMMAND > $TEMP_FILE
|
|
||||||
|
|
||||||
{% for sensor in sensors %}
|
|
||||||
{{ sensor.label }}="${{ sensor.label }} `$GET_{{ sensor.label }}`"
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
TIME=`{{ busybox }} awk '{if($1~"TotalTime") print $2}' $TEMP_FILE`
|
|
||||||
TIME_RESULT="$TIME_RESULT $TIME"
|
|
||||||
{% if cleanup %}
|
|
||||||
rm $TEMP_FILE
|
|
||||||
{% if io_stress %}
|
|
||||||
kill $io_write
|
|
||||||
kill $io_read
|
|
||||||
rm -f write.img
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
$STOP_COMMAND
|
|
||||||
sleep 2
|
|
||||||
done
|
|
||||||
|
|
||||||
{% for sensor in sensors %}
|
|
||||||
echo ${{ sensor.label }} > {{ sensor.label }}.result
|
|
||||||
{% endfor %}
|
|
||||||
echo $TIME_RESULT > time.result
|
|
||||||
# esc esc down down down ENTER (this should bring up the apps menu)
|
|
||||||
input keyevent 111
|
|
||||||
sleep 1
|
|
Loading…
x
Reference in New Issue
Block a user