| #!/usr/bin/env python3 |
| # Copyright (c) 2022, 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. |
| |
| import argparse |
| import os |
| import subprocess |
| import sys |
| |
| import compiledump |
| import gradle |
| import jdk |
| import utils |
| |
| GOLEM_BUILD_TARGETS_TESTS = [ |
| utils.GRADLE_TASK_ALL_TESTS_WITH_APPLY_MAPPING_JAR, |
| utils.GRADLE_TASK_TESTBASE_WITH_APPLY_MAPPING_JAR, |
| utils.GRADLE_TASK_TEST_DEPS_JAR |
| ] |
| GOLEM_BUILD_TARGETS = [ |
| utils.GRADLE_TASK_R8LIB, utils.GRADLE_TASK_KEEP_ANNO_JAR |
| ] + GOLEM_BUILD_TARGETS_TESTS |
| |
| |
| def get_golem_resource_path(benchmark): |
| return os.path.join('benchmarks', benchmark) |
| |
| |
| def get_jdk_home(options, benchmark): |
| if options.golem: |
| return os.path.join(get_golem_resource_path(benchmark), 'linux') |
| return None |
| |
| |
| def parse_options(argv): |
| result = argparse.ArgumentParser(description='Run test-based benchmarks.') |
| result.add_argument('--golem', |
| help='Indicate this as a run on golem', |
| default=False, |
| action='store_true') |
| result.add_argument('--benchmark', |
| help='The test benchmark to run', |
| required=True) |
| result.add_argument( |
| '--target', |
| help='The test target to run', |
| required=True, |
| # These should 1:1 with benchmarks/BenchmarkTarget.java |
| choices=['d8', 'r8-full', 'r8-force', 'r8-compat', 'retrace']) |
| result.add_argument( |
| '--debug-agent', |
| '--debug_agent', |
| help= |
| 'Enable Java debug agent and suspend compilation (default disabled)', |
| default=False, |
| action='store_true') |
| result.add_argument('--nolib', |
| '--no-lib', |
| '--no-r8lib', |
| help='Run the non-lib R8 build (default false)', |
| default=False, |
| action='store_true') |
| result.add_argument('--no-build', |
| '--no_build', |
| help='Run without building first (default false)', |
| default=False, |
| action='store_true') |
| result.add_argument('--enable-assertions', |
| '--enable_assertions', |
| '-ea', |
| help='Enable assertions when running', |
| default=False, |
| action='store_true') |
| result.add_argument('--iterations', |
| '-i', |
| help='Number of iterations to run', |
| type=int) |
| result.add_argument('--output', |
| help='Output path where to write the result') |
| result.add_argument('--print-times', |
| help='Print timing information from r8', |
| default=False, |
| action='store_true') |
| result.add_argument( |
| '--version', |
| '-v', |
| help='Use R8 version/hash for the run (default local build)', |
| default=None) |
| result.add_argument( |
| '--version-jar', |
| help='The r8.jar corresponding to the version given at --version.', |
| default=None) |
| result.add_argument('--temp', |
| help='A directory to use for temporaries and outputs.', |
| default=None) |
| result.add_argument('--verbose', |
| help='To enable verbose logging.', |
| action='store_true', |
| default=False) |
| options, args = result.parse_known_args(argv) |
| options.quiet = not options.verbose |
| # We must download the non-lib distribution when running with a specific |
| # version, since BenchmarkMainEntryRunner is using R8 internals. |
| # TODO(b/346477461): Look into removing this limitation. |
| assert options.version is None or options.nolib |
| return options, args |
| |
| |
| def main(argv, temp): |
| options, args = parse_options(argv) |
| |
| if options.output: |
| options.output = os.path.abspath(options.output) |
| |
| if options.temp: |
| temp = options.temp |
| os.makedirs(temp, exist_ok=True) |
| |
| if options.golem: |
| options.no_build = True |
| if options.nolib: |
| print("Error: golem should always run r8lib") |
| return 1 |
| |
| if options.nolib: |
| testBuildTargets = [ |
| utils.GRADLE_TASK_TEST_JAR, utils.GRADLE_TASK_TEST_DEPS_JAR, |
| utils.GRADLE_TASK_TEST_UNZIP_TESTBASE |
| ] |
| buildTargets = [utils.GRADLE_TASK_R8, utils.GRADLE_TASK_KEEP_ANNO_JAR |
| ] + testBuildTargets |
| r8jar = utils.R8_JAR |
| testjars = [ |
| utils.R8_TESTS_JAR, utils.R8_TESTS_DEPS_JAR, utils.R8_TESTBASE_JAR |
| ] |
| else: |
| testBuildTargets = GOLEM_BUILD_TARGETS_TESTS |
| buildTargets = GOLEM_BUILD_TARGETS |
| r8jar = utils.R8LIB_JAR |
| testjars = [ |
| os.path.join(utils.R8LIB_TESTS_JAR), |
| os.path.join(utils.R8LIB_TESTS_DEPS_JAR), |
| os.path.join(utils.R8LIB_TESTBASE_JAR) |
| ] |
| |
| if options.version or options.version_jar: |
| # r8 is downloaded so only test jar needs to be built. |
| buildTargets = testBuildTargets |
| r8jar = options.version_jar or compiledump.download_distribution( |
| options.version, options, temp) |
| |
| if not options.no_build: |
| gradle.RunGradle(buildTargets + ['-Pno_internal']) |
| |
| if not options.golem: |
| # When running locally, change the working directory to be in 'temp'. |
| # This is hard to do properly within the JVM so we do it here. |
| with utils.ChangedWorkingDirectory(temp): |
| return run(options, r8jar, testjars) |
| else: |
| return run(options, r8jar, testjars) |
| |
| |
| def run(options, r8jar, testjars): |
| jdkhome = get_jdk_home(options, options.benchmark) |
| cmd = [ |
| jdk.GetJavaExecutable(jdkhome), |
| '-Xms8g', |
| '-Xmx8g', |
| '-XX:+TieredCompilation', |
| '-XX:TieredStopAtLevel=4', |
| '-DBENCHMARK_IGNORE_CODE_SIZE_DIFFERENCES', |
| f'-DBUILD_PROP_KEEPANNO_RUNTIME_PATH={utils.REPO_ROOT}/d8_r8/keepanno/build/classes/java/main', |
| # Since we change the working directory to a temp folder. |
| f'-DREPO_ROOT={utils.REPO_ROOT}' |
| ] |
| if options.enable_assertions: |
| cmd.append('-ea') |
| if options.print_times: |
| cmd.append('-Dcom.android.tools.r8.printtimes=1') |
| if not options.golem: |
| cmd.extend([ |
| f'-DTEST_DATA_LOCATION={utils.REPO_ROOT}/d8_r8/test_modules/tests_java_8/build/classes/java/test', |
| f'-DTESTBASE_DATA_LOCATION={utils.REPO_ROOT}/d8_r8/test_modules/testbase/build/classes/java/main', |
| ]) |
| if options.iterations is not None: |
| if options.iterations == 0: |
| return |
| cmd.append(f'-DBENCHMARK_ITERATIONS={options.iterations}') |
| if options.output: |
| cmd.append(f'-DBENCHMARK_OUTPUT={options.output}') |
| cmd.extend(['-cp', ':'.join([r8jar] + testjars)]) |
| if options.debug_agent: |
| cmd.append( |
| '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005' |
| ) |
| cmd.extend([ |
| 'com.android.tools.r8.benchmarks.BenchmarkMainEntryRunner', |
| options.benchmark, |
| options.target, |
| # When running locally the working directory is moved and we pass the |
| # repository root as an argument. The runner can then setup dependencies. |
| 'golem' if options.golem else utils.REPO_ROOT, |
| ]) |
| utils.PrintCmd(cmd, quiet=options.quiet) |
| return subprocess.check_call(cmd) |
| |
| |
| if __name__ == '__main__': |
| with utils.TempDir() as temp: |
| sys.exit(main(sys.argv[1:], temp)) |