test_framework.py revision 5cf51bb7d718bb7730440dab6ddbff7721497274
1#!/usr/bin/env python 2# Copyright (c) 2017, the R8 project authors. Please see the AUTHORS file 3# for details. All rights reserved. Use of this source code is governed by a 4# BSD-style license that can be found in the LICENSE file. 5 6# Run D8 or DX on 'third_party/framework/framework_<version>.jar'. 7# Report Golem-compatible CodeSize and RunTimeRaw values: 8# 9# <NAME>(CodeSize): <size> 10# <NAME>(RunTimeRaw>: <time> ms 11# 12# and also detailed segment sizes for each dex segment: 13# 14# <NAME>-Code(CodeSize): <size> 15# <NAME>-AnnotationSets(CodeSize): <size> 16# ... 17# 18# Uses the DexSegment Java tool (Gradle target). 19 20from __future__ import print_function 21from glob import glob 22import argparse 23import os 24import re 25import subprocess 26import sys 27import time 28 29import utils 30 31DX_JAR = os.path.join(utils.REPO_ROOT, 'tools', 'linux', 'dx', 'framework', 32 'dx.jar') 33D8_JAR = os.path.join(utils.REPO_ROOT, 'build', 'libs', 'd8.jar') 34FRAMEWORK_JAR = os.path.join('third_party', 'framework', 35 'framework_160115954.jar') 36DEX_SEGMENTS_JAR = os.path.join(utils.REPO_ROOT, 'build', 'libs', 37 'dexsegments.jar') 38DEX_SEGMENTS_RESULT_PATTERN = re.compile('- ([^:]+): ([0-9]+)') 39MIN_SDK_VERSION = '24' 40 41def parse_arguments(): 42 parser = argparse.ArgumentParser( 43 description = 'Run D8 or DX on third_party/framework/framework*.jar.' 44 ' Report Golem-compatible CodeSize and RunTimeRaw values.') 45 parser.add_argument('--tool', 46 choices = ['dx', 'd8', 'd8-release'], 47 required = True, 48 help = 'Compiler tool to use.') 49 parser.add_argument('--name', 50 required = True, 51 help = 'Results will be printed using the specified benchmark name (e.g.' 52 ' <NAME>(CodeSize): <bytes>)') 53 return parser.parse_args() 54 55# Return a dictionary: {segment_name -> segments_size} 56def getDexSegmentSizes(dex_files): 57 assert len(dex_files) > 0 58 cmd = ['java', '-jar', DEX_SEGMENTS_JAR] 59 cmd.extend(dex_files) 60 utils.PrintCmd(cmd) 61 output = subprocess.check_output(cmd) 62 63 matches = DEX_SEGMENTS_RESULT_PATTERN.findall(output) 64 65 if matches is None or len(matches) == 0: 66 raise Exception('DexSegments failed to return any output for' \ 67 ' these files: {}'.format(dex_files)) 68 69 result = {} 70 71 for match in matches: 72 result[match[0]] = int(match[1]) 73 74 return result 75 76def Main(): 77 args = parse_arguments() 78 79 with utils.TempDir() as temp_dir: 80 if args.tool == 'dx': 81 jar_file = DX_JAR 82 jar_args = ['--output=' + temp_dir, '--multi-dex', 83 '--min-sdk-version=' + MIN_SDK_VERSION, '--dex'] 84 else: 85 jar_file = D8_JAR 86 jar_args = ['--output', temp_dir, '--min-sdk-version', MIN_SDK_VERSION] 87 if args.tool == 'd8-release': 88 jar_args.append('--release') 89 90 cmd = ['java', '-jar', jar_file] + jar_args + [FRAMEWORK_JAR] 91 92 utils.PrintCmd(cmd) 93 94 t0 = time.time() 95 subprocess.check_call(cmd) 96 dt = time.time() - t0 97 98 dex_files = [f for f in glob(os.path.join(temp_dir, '*.dex'))] 99 code_size = 0 100 for dex_file in dex_files: 101 code_size += os.path.getsize(dex_file) 102 103 print('{}(RunTimeRaw): {} ms' 104 .format(args.name, 1000.0 * dt)) 105 106 print('{}(CodeSize): {}' 107 .format(args.name, code_size)) 108 109 for segment_name, size in getDexSegmentSizes(dex_files).items(): 110 print('{}-{}(CodeSize): {}' 111 .format(args.name, segment_name, size)) 112 113if __name__ == '__main__': 114 sys.exit(Main()) 115