Add Pixel C knobs to skpbench
BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2369533002 Review-Url: https://codereview.chromium.org/2369533002
This commit is contained in:
parent
68c3d30702
commit
bf41fa841b
@ -3,7 +3,7 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
'''Parses an skpbench result from a line of output text.'''
|
||||
"""Parses an skpbench result from a line of output text."""
|
||||
|
||||
from __future__ import print_function
|
||||
import re
|
||||
|
@ -5,12 +5,21 @@
|
||||
|
||||
import time
|
||||
|
||||
class HardwareException(Exception):
|
||||
def __init__(self, message, sleeptime=60):
|
||||
Exception.__init__(self, message)
|
||||
self.sleeptime = sleeptime
|
||||
|
||||
class Hardware:
|
||||
"""Locks down and monitors hardware for benchmarking.
|
||||
|
||||
This is a common base for classes that can control the specific hardware
|
||||
we are running on. Its purpose is to lock the hardware into a constant
|
||||
benchmarking mode for the duration of a 'with' block. e.g.:
|
||||
|
||||
with hardware:
|
||||
run_benchmark()
|
||||
|
||||
While benchmarking, the caller must call sanity_check() frequently to verify
|
||||
the hardware state has not changed.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self.kick_in_time = 0
|
||||
|
||||
@ -21,9 +30,60 @@ class Hardware:
|
||||
pass
|
||||
|
||||
def sanity_check(self):
|
||||
'''Raises a HardwareException if any hardware state is not as expected.'''
|
||||
"""Raises a HardwareException if any hardware state is not as expected."""
|
||||
pass
|
||||
|
||||
def sleep(self, sleeptime):
|
||||
'''Puts the hardware into a resting state for a fixed amount of time.'''
|
||||
"""Puts the hardware into a resting state for a fixed amount of time."""
|
||||
time.sleep(sleeptime)
|
||||
|
||||
|
||||
class HardwareException(Exception):
|
||||
"""Gets thrown when certain hardware state is not what we expect.
|
||||
|
||||
Generally this happens because of thermal conditions or other variables beyond
|
||||
our control, and the appropriate course of action is to take a short nap
|
||||
before resuming the benchmark.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, message, sleeptime=60):
|
||||
Exception.__init__(self, message)
|
||||
self.sleeptime = sleeptime
|
||||
|
||||
|
||||
class Expectation:
|
||||
"""Simple helper for checking the readings on hardware gauges."""
|
||||
def __init__(self, value_type, min_value=None, max_value=None,
|
||||
exact_value=None, name=None, sleeptime=60):
|
||||
self.value_type = value_type
|
||||
self.min_value = min_value
|
||||
self.max_value = max_value
|
||||
self.exact_value = exact_value
|
||||
self.name = name
|
||||
self.sleeptime = sleeptime
|
||||
|
||||
def check(self, stringvalue):
|
||||
typedvalue = self.value_type(stringvalue)
|
||||
if self.min_value is not None and typedvalue < self.min_value:
|
||||
raise HardwareException("%s is too low (%s, min=%s)" %
|
||||
(self.name, stringvalue, str(self.min_value)),
|
||||
sleeptime=self.sleeptime)
|
||||
if self.max_value is not None and typedvalue > self.max_value:
|
||||
raise HardwareException("%s is too high (%s, max=%s)" %
|
||||
(self.name, stringvalue, str(self.max_value)),
|
||||
sleeptime=self.sleeptime)
|
||||
if self.exact_value is not None and typedvalue != self.exact_value:
|
||||
raise HardwareException("unexpected %s (%s, expected=%s)" %
|
||||
(self.name, stringvalue, str(self.exact_value)),
|
||||
sleeptime=self.sleeptime)
|
||||
|
||||
@staticmethod
|
||||
def check_all(expectations, stringvalues):
|
||||
if len(stringvalues) != len(expectations):
|
||||
raise Exception("unexpected reading from hardware gauges "
|
||||
"(expected %i values):\n%s" %
|
||||
(len(expectations), '\n'.join(stringvalues)))
|
||||
|
||||
for value, expected in zip(stringvalues, expectations):
|
||||
expected.check(value)
|
||||
|
94
tools/skpbench/_hardware_pixel_c.py
Normal file
94
tools/skpbench/_hardware_pixel_c.py
Normal file
@ -0,0 +1,94 @@
|
||||
# Copyright 2016 Google Inc.
|
||||
#
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
from _hardware import HardwareException, Expectation
|
||||
from _hardware_android import HardwareAndroid
|
||||
|
||||
CPU_CLOCK_RATE = 1836000
|
||||
GPU_EMC_PROFILE = '0c: core 921 MHz emc 1600 MHz a A d D *'
|
||||
GPU_EMC_PROFILE_ID = '0c'
|
||||
|
||||
class HardwarePixelC(HardwareAndroid):
|
||||
def __init__(self, adb):
|
||||
HardwareAndroid.__init__(self, adb)
|
||||
|
||||
def __enter__(self):
|
||||
self._lock_clocks()
|
||||
return HardwareAndroid.__enter__(self)
|
||||
|
||||
def __exit__(self, exception_type, exception_value, exception_traceback):
|
||||
HardwareAndroid.__exit__(self, exception_type,
|
||||
exception_value, exception_traceback)
|
||||
self._unlock_clocks()
|
||||
|
||||
def _lock_clocks(self):
|
||||
if not self._is_root:
|
||||
return
|
||||
|
||||
# lock cpu clocks.
|
||||
self._adb.shell('''\
|
||||
for N in $(seq 0 3); do
|
||||
echo userspace > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
|
||||
echo %i > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
|
||||
done''' % CPU_CLOCK_RATE)
|
||||
|
||||
# lock gpu/emc clocks.
|
||||
self._adb.shell('''\
|
||||
chown root:root /sys/devices/57000000.gpu/pstate
|
||||
echo %s > /sys/devices/57000000.gpu/pstate''' % GPU_EMC_PROFILE_ID)
|
||||
|
||||
def _unlock_clocks(self):
|
||||
if not self._is_root:
|
||||
return
|
||||
|
||||
# unlock gpu/emc clocks.
|
||||
self._adb.shell('''\
|
||||
echo auto > /sys/devices/57000000.gpu/pstate
|
||||
chown system:system /sys/devices/57000000.gpu/pstate''')
|
||||
|
||||
# unlock cpu clocks.
|
||||
self._adb.shell('''\
|
||||
for N in $(seq 0 3); do
|
||||
echo 0 > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_setspeed
|
||||
echo interactive > /sys/devices/system/cpu/cpu$N/cpufreq/scaling_governor
|
||||
done''')
|
||||
|
||||
def sanity_check(self):
|
||||
HardwareAndroid.sanity_check(self)
|
||||
|
||||
if not self._is_root:
|
||||
return
|
||||
|
||||
# only issue one shell command in an attempt to minimize interference.
|
||||
result = self._adb.check_lines('''\
|
||||
cat /sys/class/power_supply/bq27742-0/capacity \
|
||||
/sys/class/thermal/thermal_zone7/temp \
|
||||
/sys/class/thermal/thermal_zone0/temp \
|
||||
/sys/class/thermal/thermal_zone1/temp \
|
||||
/sys/class/thermal/thermal_zone7/cdev1/cur_state \
|
||||
/sys/class/thermal/thermal_zone7/cdev0/cur_state
|
||||
for N in $(seq 0 3); do
|
||||
cat /sys/devices/system/cpu/cpu$N/cpufreq/scaling_cur_freq
|
||||
done
|
||||
cat /sys/devices/57000000.gpu/pstate | grep \*$''')
|
||||
|
||||
expectations = \
|
||||
[Expectation(int, min_value=30, name='battery', sleeptime=30*60),
|
||||
Expectation(int, max_value=40000, name='skin temperature'),
|
||||
Expectation(int, max_value=86000, name='cpu temperature'),
|
||||
Expectation(int, max_value=87000, name='gpu temperature'),
|
||||
Expectation(int, exact_value=0, name='cpu throttle'),
|
||||
Expectation(int, exact_value=0, name='gpu throttle')] + \
|
||||
[Expectation(int, exact_value=CPU_CLOCK_RATE,
|
||||
name='cpu_%i clock rate' % i, sleeptime=30)
|
||||
for i in range(4)] + \
|
||||
[Expectation(str, exact_value=GPU_EMC_PROFILE, name='gpu/emc profile')]
|
||||
|
||||
Expectation.check_all(expectations, result)
|
||||
|
||||
def sleep(self, sleeptime):
|
||||
self._unlock_clocks()
|
||||
HardwareAndroid.sleep(self, sleeptime)
|
||||
self._lock_clocks()
|
@ -18,7 +18,7 @@ import urllib
|
||||
import urlparse
|
||||
import webbrowser
|
||||
|
||||
__argparse = ArgumentParser(description='''
|
||||
__argparse = ArgumentParser(description="""
|
||||
|
||||
Parses output files from skpbench.py into csv.
|
||||
|
||||
@ -31,7 +31,7 @@ This script can also be used to generate a Google sheet:
|
||||
|
||||
(3) Run parseskpbench.py with the --open flag.
|
||||
|
||||
''')
|
||||
""")
|
||||
|
||||
__argparse.add_argument('-r', '--result',
|
||||
choices=['median', 'accum', 'max', 'min'], default='median',
|
||||
|
@ -20,14 +20,14 @@ import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
__argparse = ArgumentParser(description='''
|
||||
__argparse = ArgumentParser(description="""
|
||||
|
||||
Executes the skpbench binary with various configs and skps.
|
||||
|
||||
Also monitors the output in order to filter out and re-run results that have an
|
||||
unacceptable stddev.
|
||||
|
||||
''')
|
||||
""")
|
||||
|
||||
__argparse.add_argument('--adb',
|
||||
action='store_true', help="execute skpbench over adb")
|
||||
@ -82,7 +82,7 @@ class SubprocessMonitor(Thread):
|
||||
Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
'''Runs on the background thread.'''
|
||||
"""Runs on the background thread."""
|
||||
for line in iter(self._proc.stdout.readline, b''):
|
||||
self._queue.put(Message(Message.READLINE, line.decode('utf-8').rstrip()))
|
||||
self._queue.put(Message(Message.EXIT))
|
||||
@ -243,8 +243,9 @@ def main():
|
||||
if FLAGS.adb:
|
||||
adb = Adb(FLAGS.device_serial)
|
||||
model = adb.get_device_model()
|
||||
if False:
|
||||
pass # TODO: unique subclasses tailored to individual platforms.
|
||||
if model == 'Pixel C':
|
||||
from _hardware_pixel_c import HardwarePixelC
|
||||
hardware = HardwarePixelC(adb)
|
||||
else:
|
||||
from _hardware_android import HardwareAndroid
|
||||
print("WARNING: %s: don't know how to monitor this hardware; results "
|
||||
|
Loading…
Reference in New Issue
Block a user