blob: 4a951778060a5474e84a1d2d146eb11b5ab87373 [file] [log] [blame]
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import threading
import time
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import chrome_binary_test
from autotest_lib.client.cros import service_stopper
from autotest_lib.client.cros.power import power_status
from autotest_lib.client.cros.power import power_utils
from autotest_lib.client.cros.video import device_capability
from autotest_lib.client.cros.video import helper_logger
DECODE_WITH_HW_ACCELERATION = 'jpeg_decode_with_hw'
DECODE_WITHOUT_HW_ACCELERATION = 'jpeg_decode_with_sw'
# Measurement duration in seconds.
MEASUREMENT_DURATION = 10
# Time in seconds to wait for cpu idle until giveup.
WAIT_FOR_IDLE_CPU_TIMEOUT = 60.0
# Maximum percent of cpu usage considered as idle.
CPU_IDLE_USAGE = 0.1
# Minimum battery charge percentage to run the test
BATTERY_INITIAL_CHARGED_MIN = 10
class video_JDAPerf(chrome_binary_test.ChromeBinaryTest):
"""
The test outputs the cpu usage and the power consumption for jpeg decoding
to performance dashboard.
"""
version = 1
# Decoding times for performance measurement
perf_jpeg_decode_times = 600
binary = 'jpeg_decode_accelerator_unittest'
jda_filter = 'JpegDecodeAcceleratorTest.PerfJDA'
sw_filter = 'JpegDecodeAcceleratorTest.PerfSW'
def initialize(self):
"""Initialize this test."""
super(video_JDAPerf, self).initialize()
self._service_stopper = None
self._original_governors = None
self._backlight = None
self._use_ec = False
@chrome_binary_test.nuke_chrome
def run_once(self, capability, power_test=False):
"""
Runs the video_JDAPerf test.
@param capability: Capability required for executing this test.
@param power_test: True for power consumption test.
False for cpu usage test.
"""
device_capability.DeviceCapability().ensure_capability(capability)
if power_test:
keyvals = self.test_power()
self.log_result(keyvals, 'jpeg_decode_energy', 'W')
else:
keyvals = self.test_cpu_usage()
self.log_result(keyvals, 'jpeg_decode_cpu', 'percent')
def test_cpu_usage(self):
"""
Runs the video cpu usage test.
@return a dictionary that contains the test result.
"""
def get_cpu_usage():
cpu_usage_start = utils.get_cpu_usage()
time.sleep(MEASUREMENT_DURATION)
cpu_usage_end = utils.get_cpu_usage()
return utils.compute_active_cpu_time(cpu_usage_start,
cpu_usage_end) * 100
# crbug/753292 - APNG login pictures increase CPU usage. Move the more
# strict idle checks after the login phase.
if not utils.wait_for_idle_cpu(WAIT_FOR_IDLE_CPU_TIMEOUT,
CPU_IDLE_USAGE):
logging.warning('Could not get idle CPU pre login.')
if not utils.wait_for_cool_machine():
logging.warning('Could not get cold machine pre login.')
# Stop the thermal service that may change the cpu frequency.
self._service_stopper = service_stopper.get_thermal_service_stopper()
self._service_stopper.stop_services()
# Set the scaling governor to performance mode to set the cpu to the
# highest frequency available.
self._original_governors = utils.set_high_performance_mode()
return self.test_decode(get_cpu_usage)
def test_power(self):
"""
Runs the video power consumption test.
@return a dictionary that contains the test result.
"""
self._backlight = power_utils.Backlight()
self._backlight.set_level(0)
self._power_status = power_status.get_status()
self._use_ec = True
if not power_utils.charge_control_by_ectool(is_charge=False):
logging.warning('Can\'t stop charging')
return {}
if not self._power_status.battery:
raise error.TestFail('No valid battery')
# Verify that the battery is sufficiently charged.
percent_initial_charge = self._power_status.percent_current_charge()
if percent_initial_charge < BATTERY_INITIAL_CHARGED_MIN:
logging.warning('Initial charge (%f) less than min (%f)',
(percent_initial_charge,
BATTERY_INITIAL_CHARGED_MIN))
return {}
measurements = [power_status.SystemPower(
self._power_status.battery_path)]
def get_power():
power_logger = power_status.PowerLogger(measurements)
power_logger.start()
start_time = time.time()
time.sleep(MEASUREMENT_DURATION)
power_logger.checkpoint('result', start_time)
keyval = power_logger.calc()
return keyval['result_' + measurements[0].domain + '_pwr_avg']
return self.test_decode(get_power)
def start_decode(self, gtest_filter):
"""
Start jpeg decode process.
@param gtest_filter: gtest_filter argument.
"""
logging.debug('Starting video_JpegDecodeAccelerator %s', gtest_filter)
cmd_line_list = [helper_logger.chrome_vmodule_flag()]
cmd_line_list.append('--gtest_filter="%s"' % gtest_filter)
cmd_line_list.append('--perf_decode_times=%d' %
self.perf_jpeg_decode_times)
cmd_line = ' '.join(cmd_line_list)
self.run_chrome_test_binary(self.binary, cmd_line)
def test_decode(self, gather_result):
"""
Runs the jpeg decode test with and without hardware acceleration.
@param gather_result: a function to run and return the test result
@return a dictionary that contains test the result.
"""
keyvals = {}
thread = threading.Thread(target=self.start_decode,
kwargs={'gtest_filter': self.jda_filter})
thread.start()
result = gather_result()
thread.join()
keyvals[DECODE_WITH_HW_ACCELERATION] = result
thread = threading.Thread(target=self.start_decode,
kwargs={'gtest_filter': self.sw_filter})
thread.start()
result = gather_result()
thread.join()
keyvals[DECODE_WITHOUT_HW_ACCELERATION] = result
return keyvals
def log_result(self, keyvals, description, units):
"""
Logs the test result output to the performance dashboard.
@param keyvals: a dictionary that contains results returned by
test_playback.
@param description: a string that describes the video and test result
and it will be part of the entry name in the dashboard.
@param units: the units of test result.
"""
result_with_hw = keyvals.get(DECODE_WITH_HW_ACCELERATION)
if result_with_hw is not None:
self.output_perf_value(description='hw_' + description,
value=result_with_hw,
units=units, higher_is_better=False)
result_without_hw = keyvals.get(DECODE_WITHOUT_HW_ACCELERATION)
if result_without_hw is not None:
self.output_perf_value(
description='sw_' + description, value=result_without_hw,
units=units, higher_is_better=False)
def cleanup(self):
"""Autotest cleanup function
It is run by common_lib/test.py.
"""
if self._backlight:
self._backlight.restore()
if self._service_stopper:
self._service_stopper.restore_services()
if self._original_governors:
utils.restore_scaling_governor_states(self._original_governors)
if self._use_ec:
power_utils.charge_control_by_ectool(is_charge=True)
super(video_JDAPerf, self).cleanup()