|  | #!/usr/bin/env python | 
|  | # Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file | 
|  | # for details. All rights reserved. Use of this source code is governed by a | 
|  | # BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | # Script for running kotlin based benchmarks | 
|  |  | 
|  | import golem | 
|  | import optparse | 
|  | import os | 
|  | import subprocess | 
|  | import sys | 
|  | import toolhelper | 
|  | import utils | 
|  |  | 
|  |  | 
|  | BENCHMARK_ROOT = os.path.join(utils.REPO_ROOT, 'third_party', 'benchmarks', | 
|  | 'kotlin-benches') | 
|  |  | 
|  | BENCHMARK_PATTERN = '{benchmark}/kotlin/perf/build/libs/perf-1.0-BENCH.jar' | 
|  | BENCHMARK_MAIN_CLASS = 'com.android.kt.bms.cli.Runner' | 
|  | ART = os.path.join(utils.TOOLS_DIR, 'linux', 'art', 'bin', 'art') | 
|  |  | 
|  | PROGUARD_CONF = """ | 
|  | # From Android rules | 
|  | -keepclasseswithmembers public class * { | 
|  | public static void main(java.lang.String[]); | 
|  | } | 
|  | # Disable obfuscation to only focus on shrinking | 
|  | -dontobfuscate | 
|  | # Once we're ready for optimization, we might want to relax access modifiers. | 
|  | -allowaccessmodification | 
|  | """ | 
|  |  | 
|  | DEVICE_TEMP='/data/local/temp/bench' | 
|  |  | 
|  |  | 
|  | def parse_options(): | 
|  | result = optparse.OptionParser() | 
|  | result.add_option('--api', | 
|  | help='Android api level', | 
|  | default='26', | 
|  | choices=['21', '22', '23', '24', '25', '26']) | 
|  | result.add_option('--benchmark', | 
|  | help='The benchmark to run', | 
|  | default='rgx', | 
|  | choices=['rgx', 'deltablue', 'sta', 'empty']) | 
|  | result.add_option('--golem', | 
|  | help='Don\'t build r8 and link in third_party deps', | 
|  | default=False, action='store_true') | 
|  | result.add_option('--use-device', | 
|  | help='Run the benchmark on an attaced device', | 
|  | default=False, action='store_true') | 
|  | return result.parse_args() | 
|  |  | 
|  |  | 
|  | def get_jar_for_benchmark(benchmark): | 
|  | return os.path.join(BENCHMARK_ROOT, | 
|  | BENCHMARK_PATTERN.format(benchmark=benchmark)) | 
|  |  | 
|  | def run_art(dex): | 
|  | command = ['bash', ART, '-cp', dex, BENCHMARK_MAIN_CLASS] | 
|  | utils.PrintCmd(command) | 
|  | benchmark_output = subprocess.check_output(command) | 
|  | return get_result(benchmark_output) | 
|  |  | 
|  | def adb(args): | 
|  | command = ['adb'] + args | 
|  | utils.PrintCmd(command) | 
|  | return subprocess.check_output(['adb'] + args) | 
|  |  | 
|  | def get_result(output): | 
|  | # There is a lot of debug output, with the actual results being in the line with: | 
|  | # RESULTS,KtBench,KtBench,15719 | 
|  | # structure. | 
|  | for result in [s for s in output.splitlines() if s.startswith('RESULTS')]: | 
|  | return s.split('RESULTS,KtBench,KtBench,')[1] | 
|  |  | 
|  | def run_art_device(dex): | 
|  | adb(['wait-for-device', 'root']) | 
|  | device_dst = os.path.join(DEVICE_TEMP, os.path.basename(dex)) | 
|  | adb(['push', dex, device_dst]) | 
|  | benchmark_output = adb(['shell', 'dalvikvm', '-cp', device_dst, BENCHMARK_MAIN_CLASS]) | 
|  | return get_result(benchmark_output) | 
|  |  | 
|  | def Main(): | 
|  | (options, args) = parse_options() | 
|  | if options.golem: | 
|  | golem.link_third_party() | 
|  | with utils.TempDir() as temp: | 
|  | dex_path = os.path.join(temp, "classes.jar") | 
|  | proguard_conf = os.path.join(temp, 'proguard.conf') | 
|  | with open(proguard_conf, 'w') as f: | 
|  | f.write(PROGUARD_CONF) | 
|  | benchmark_jar = get_jar_for_benchmark(options.benchmark) | 
|  | r8_args = [ | 
|  | '--lib', utils.get_android_jar(26), # Only works with api 26 | 
|  | '--output', dex_path, | 
|  | '--pg-conf', proguard_conf, | 
|  | '--min-api', str(options.api), | 
|  | benchmark_jar | 
|  | ] | 
|  | toolhelper.run('r8', r8_args, build=not options.golem) | 
|  | if options.use_device: | 
|  | result = run_art_device(dex_path) | 
|  | else: | 
|  | result = run_art(dex_path) | 
|  | print('Kotlin_{}(RunTimeRaw): {} ms'.format(options.benchmark, result)) | 
|  |  | 
|  | if __name__ == '__main__': | 
|  | sys.exit(Main()) |