test_framework.py revision fc34cd80f0abbae2372f5d8203363ecc2cd58f08
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, DX or Goyt on 'third_party/framework/framework_<version>.jar'. 7# Report Golem-compatible CodeSize and RunTimeRaw values: 8# 9# <NAME>-Total(CodeSize): <size> 10# <NAME>-Total(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') 34GOYT_EXE = os.path.join('third_party', 'goyt', 35 'goyt_160525751') 36FRAMEWORK_JAR = os.path.join('third_party', 'framework', 37 'framework_160115954.jar') 38DEX_SEGMENTS_JAR = os.path.join(utils.REPO_ROOT, 'build', 'libs', 39 'dexsegments.jar') 40DEX_SEGMENTS_RESULT_PATTERN = re.compile('- ([^:]+): ([0-9]+)') 41MIN_SDK_VERSION = '24' 42 43def parse_arguments(): 44 parser = argparse.ArgumentParser( 45 description = 'Run D8, DX or Goyt on' 46 ' third_party/framework/framework*.jar.' 47 ' Report Golem-compatible CodeSize and RunTimeRaw values.') 48 parser.add_argument('--tool', 49 choices = ['dx', 'd8', 'd8-release', 'goyt'], 50 required = True, 51 help = 'Compiler tool to use.') 52 parser.add_argument('--name', 53 required = True, 54 help = 'Results will be printed using the specified benchmark name (e.g.' 55 ' <NAME>-<segment>(CodeSize): <bytes>)') 56 parser.add_argument('--print-memoryuse', 57 help = 'Prints the line \'<NAME>(MemoryUse):' + 58 ' <mem>\' at the end where <mem> is the peak' + 59 ' peak resident set size (VmHWM) in bytes.', 60 default = False, 61 action = 'store_true') 62 return parser.parse_args() 63 64# Return a dictionary: {segment_name -> segments_size} 65def getDexSegmentSizes(dex_files): 66 assert len(dex_files) > 0 67 cmd = ['java', '-jar', DEX_SEGMENTS_JAR] 68 cmd.extend(dex_files) 69 utils.PrintCmd(cmd) 70 output = subprocess.check_output(cmd) 71 72 matches = DEX_SEGMENTS_RESULT_PATTERN.findall(output) 73 74 if matches is None or len(matches) == 0: 75 raise Exception('DexSegments failed to return any output for' \ 76 ' these files: {}'.format(dex_files)) 77 78 result = {} 79 80 for match in matches: 81 result[match[0]] = int(match[1]) 82 83 return result 84 85def Main(): 86 args = parse_arguments() 87 88 with utils.TempDir() as temp_dir: 89 90 if args.tool in ['dx', 'goyt']: 91 tool_args = ['--dex', '--output=' + temp_dir, '--multi-dex', 92 '--min-sdk-version=' + MIN_SDK_VERSION] 93 94 if args.tool == 'goyt': 95 tool_file = GOYT_EXE 96 tool_args = ['--num-threads=4'] + tool_args 97 elif args.tool == 'dx': 98 tool_file = DX_JAR 99 else: 100 tool_file = D8_JAR 101 tool_args = ['--output', temp_dir, '--min-api', MIN_SDK_VERSION] 102 if args.tool == 'd8-release': 103 tool_args.append('--release') 104 105 106 cmd = [] 107 108 track_memory_file = None 109 if args.print_memoryuse: 110 track_memory_file = os.path.join(temp_dir, utils.MEMORY_USE_TMP_FILE) 111 cmd.extend(['tools/track_memory.sh', track_memory_file]) 112 113 if tool_file.endswith('.jar'): 114 cmd.extend(['java', '-jar']) 115 116 cmd.extend([tool_file] + tool_args + [FRAMEWORK_JAR]) 117 118 utils.PrintCmd(cmd) 119 120 t0 = time.time() 121 subprocess.check_call(cmd) 122 dt = time.time() - t0 123 124 if args.print_memoryuse: 125 print('{}(MemoryUse): {}' 126 .format(args.name, utils.grep_memoryuse(track_memory_file))) 127 128 dex_files = [f for f in glob(os.path.join(temp_dir, '*.dex'))] 129 code_size = 0 130 for dex_file in dex_files: 131 code_size += os.path.getsize(dex_file) 132 133 print('{}-Total(RunTimeRaw): {} ms' 134 .format(args.name, 1000.0 * dt)) 135 136 print('{}-Total(CodeSize): {}' 137 .format(args.name, code_size)) 138 139 for segment_name, size in getDexSegmentSizes(dex_files).items(): 140 print('{}-{}(CodeSize): {}' 141 .format(args.name, segment_name, size)) 142 143if __name__ == '__main__': 144 sys.exit(Main()) 145