blob: b7c53b820c9201afc745b62776254c2931ad767f [file] [log] [blame]
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +02001#!/usr/bin/env python
2# Copyright (c) 2018, 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
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +02006from __future__ import print_function
7import argparse
Rico Wind1f4172c2018-09-06 16:29:03 +02008import gradle
9import golem
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020010import os
Rico Wind49620922018-10-11 09:12:05 +020011import subprocess
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020012import sys
13import utils
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020014from enum import Enum
15
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020016BENCHMARKS_ROOT_DIR = os.path.join(utils.REPO_ROOT, 'third_party', 'benchmarks')
17
18def parse_arguments():
19 parser = argparse.ArgumentParser(
20 description='Run D8 or DX on gradle apps located in'
21 ' third_party/benchmarks/.'
22 ' Report Golem-compatible RunTimeRaw values.')
Rico Wind1f4172c2018-09-06 16:29:03 +020023 parser.add_argument('--golem',
24 help = 'Running on golem, link in third_party resources.',
25 default = False, action = 'store_true')
Rico Wind23359232018-04-17 09:41:18 +020026 parser.add_argument('--skip_download',
Rico Wind834e7fc2018-04-16 14:24:52 +020027 help='Don\'t automatically pull down dependencies.',
28 default=False, action='store_true')
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020029 parser.add_argument('--tool',
30 choices=['dx', 'd8'],
31 required=True,
32 help='Compiler tool to use.')
Rico Wind834e7fc2018-04-16 14:24:52 +020033
Rico Windab38fb92018-04-06 16:10:52 +020034 parser.add_argument('--benchmark',
35 help='Which benchmark to run, default all')
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020036 return parser.parse_args()
37
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020038class Benchmark:
39 class Tools(Enum):
40 D8 = 1
41 DX = 2
42
43 class DesugarMode(Enum):
44 D8_DESUGARING = 1
45 DESUGAR_TOOL = 2
46
47 displayName = ""
48 rootDirPath = ""
49 appPath = ""
50 moduleName = ""
51 buildCommand = ""
52 cleanCommand = ""
Jean-Marie Henaff889dd942018-04-05 15:56:36 +020053 env = {}
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020054
Rico Winde03b1a42018-04-06 16:14:40 +020055 def __init__(self, displayName, benchmarkDir, moduleName, buildCommand,
56 cleanCommand):
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020057 self.displayName = displayName
Rico Winde03b1a42018-04-06 16:14:40 +020058 self.rootDirPath = os.path.join(BENCHMARKS_ROOT_DIR,
59 benchmarkDir.split(os.sep)[0])
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020060 self.appPath = os.path.join(BENCHMARKS_ROOT_DIR, benchmarkDir)
61 self.moduleName = moduleName
62 self.buildCommand = buildCommand
63 self.cleanCommand = cleanCommand
Jean-Marie Henaff889dd942018-04-05 15:56:36 +020064 self.env = os.environ.copy()
Rico Winde03b1a42018-04-06 16:14:40 +020065 self.env["ANDROID_HOME"] = os.path.join(utils.REPO_ROOT, 'third_party',
66 'benchmarks', 'android-sdk')
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020067
68 def RunGradle(self, command, tool, desugarMode):
69
70 args = ['-Dr8.root.dir=' + utils.REPO_ROOT, '--init-script',
71 os.path.join(BENCHMARKS_ROOT_DIR, 'init-script.gradle')]
72
73 if tool == self.Tools.D8:
74 args.append('-Dandroid.enableD8=true')
75 elif tool == self.Tools.DX:
76 args.append('-Dandroid.enableD8=false')
77 else:
78 raise AssertionError("Unknown tool: " + repr(tool))
79
80 if desugarMode == self.DesugarMode.D8_DESUGARING:
81 args.append('-Dandroid.enableDesugar=false')
82 elif desugarMode == self.DesugarMode.DESUGAR_TOOL:
83 args.append('-Dandroid.enableDesugar=true')
84 else:
85 raise AssertionError("Unknown desugar mode: " + repr(desugarMode))
Rico Wind49620922018-10-11 09:12:05 +020086 # Running with a daemon will give inconsistent results based on previous runs
87 # and if the golem runners restarted.
88 args.append('--no-daemon')
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020089 args.extend(command)
90
Jean-Marie Henaff889dd942018-04-05 15:56:36 +020091 return gradle.RunGradleWrapperInGetOutput(args, self.appPath, env=self.env)
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +020092
93 def Build(self, tool, desugarMode):
94 return self.RunGradle(self.buildCommand, tool, desugarMode)
95
96 def Clean(self):
97 # tools and desugar mode not relevant for clean
Rico Winde03b1a42018-04-06 16:14:40 +020098 return self.RunGradle(self.cleanCommand,
99 self.Tools.D8,
100 self.DesugarMode.D8_DESUGARING)
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200101
102 def EnsurePresence(self):
103 EnsurePresence(self.rootDirPath, self.displayName)
104
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200105def EnsurePresence(dir, displayName):
106 if not os.path.exists(dir) or os.path.getmtime(dir + '.tar.gz')\
107 < os.path.getmtime(dir + '.tar.gz.sha1'):
108 utils.DownloadFromX20(dir + '.tar.gz.sha1')
109 # Update the mtime of the tar file to make sure we do not run again unless
110 # there is an update.
111 os.utime(dir + '.tar.gz', None)
112 else:
113 print('test_gradle_benchmarks.py: benchmark {} is present'.format(displayName))
114
115def TaskFilter(taskname):
116 acceptedGradleTasks = [
117 'dex',
118 'Dex',
119 'proguard',
120 'Proguard',
121 'kotlin',
122 'Kotlin',
123 ]
124
125 return any(namePattern in taskname for namePattern in acceptedGradleTasks)
126
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200127def PrintBuildTimeForGolem(benchmark, stdOut):
128 for line in stdOut.splitlines():
129 if 'BENCH' in line and benchmark.moduleName in line:
130 commaSplit = line.split(',')
131 assert len(commaSplit) == 3
132
133 # Keep only module that have been configured to use R8
134 if benchmark.moduleName + ':' not in commaSplit[1]:
135 continue
136
137 # remove <module-name> + ':'
138 taskName = commaSplit[1][(len(benchmark.moduleName) + 1):]
139
140 # Just a temporary assumption.
Rico Winde03b1a42018-04-06 16:14:40 +0200141 # This means we have submodules, so we'll need to check their
142 # configuration so that the right r8/d8 is taken. For now it shouldn't
143 # be the case.
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200144 assert taskName.find(':') == -1, taskName
145
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200146 if TaskFilter(taskName):
Rico Winde03b1a42018-04-06 16:14:40 +0200147 # taskName looks like:
148 # transformClassesWithDexBuilderForDevelopmentDebug
149 # we don't want unimportant information in UI, so we strip it down to:
150 # ClassesDexBuilderDevelopment
151 # Output example:
152 # SantaTracker-ClassesDexBuilderDevelopment(RunTimeRaw): 748 ms
153 assert taskName.startswith('transform')
154 taskName = taskName[len('transform'):]
155 taskName = taskName.replace('With', '')
156 taskName = taskName.replace('For', '')
157 taskName = taskName.replace('Default', '')
158 benchmarkName = benchmark.displayName + '-' + taskName
159 print('{}(RunTimeRaw): {} ms'.format(benchmarkName, commaSplit[2]))
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200160
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200161def Main():
162 args = parse_arguments()
Rico Wind1f4172c2018-09-06 16:29:03 +0200163 if args.golem:
Rico Wind49620922018-10-11 09:12:05 +0200164 # Ensure that we don't have a running daemon
165 exitcode = subprocess.call(['pkill', 'java'])
166 assert exitcode == 0 or exitcode == 1
Rico Wind1f4172c2018-09-06 16:29:03 +0200167 golem.link_third_party()
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200168
169 if args.tool == 'd8':
170 tool = Benchmark.Tools.D8
171 desugarMode = Benchmark.DesugarMode.D8_DESUGARING
172 else:
173 tool = Benchmark.Tools.DX
174 desugarMode = Benchmark.DesugarMode.DESUGAR_TOOL
175
176 buildTimeBenchmarks = [
177 Benchmark('AntennaPod',
178 os.path.join('antenna-pod', 'AntennaPod'),
179 ':app',
180 [':app:assembleDebug'],
181 ['clean']),
182 Benchmark('Maps',
183 'gradle-java-1.6',
184 ':maps',
Rico Winde03b1a42018-04-06 16:14:40 +0200185 [':maps:assembleDebug', '--settings-file',
186 'settings.gradle.maps'],
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200187 ['clean']),
188 Benchmark('Music2',
189 'gradle-java-1.6',
190 ':music2Old',
Rico Winde03b1a42018-04-06 16:14:40 +0200191 [':music2Old:assembleDebug', '--settings-file',
192 'settings.gradle.music2Old'],
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200193 ['clean']),
194 Benchmark('Velvet',
195 'gradle-java-1.6',
196 ':velvet',
Rico Winde03b1a42018-04-06 16:14:40 +0200197 [':velvet:assembleDebug', '--settings-file',
198 'settings.gradle.velvet'],
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200199 ['clean']),
200 Benchmark('SantaTracker',
201 'santa-tracker',
202 ':santa-tracker',
203 [':santa-tracker:assembleDebug'],
204 ['clean']),
205
206 # disabled for now, apparently because of b/74227571
207 # Benchmark('Tachiyomi',
208 # 'tachiyomi',
209 # ':app',
210 # ['assembleStandardDebug'],
211 # ['clean']),
212
213 Benchmark('WordPress',
214 'wordpress',
215 ':WordPress',
216 ['assembleVanillaDebug'],
217 ['clean']),
218
219 ]
Rico Wind1f4172c2018-09-06 16:29:03 +0200220 if not args.skip_download and not args.golem:
Rico Wind834e7fc2018-04-16 14:24:52 +0200221 EnsurePresence(os.path.join('third_party', 'benchmarks', 'android-sdk'),
222 'android SDK')
223 EnsurePresence(os.path.join('third_party', 'gradle-plugin'),
224 'Android Gradle plugin')
Rico Windab38fb92018-04-06 16:10:52 +0200225 toRun = buildTimeBenchmarks
226 if args.benchmark:
227 toRun = [b for b in toRun if b.displayName == args.benchmark]
228 if len(toRun) != 1:
229 raise AssertionError("Unknown benchmark: " + args.benchmark)
230 for benchmark in toRun:
Rico Wind834e7fc2018-04-16 14:24:52 +0200231 if not args.skip_download:
232 benchmark.EnsurePresence()
Jean-Marie Henaffe4e36d12018-04-05 10:33:50 +0200233 benchmark.Clean()
234 stdOut = benchmark.Build(tool, desugarMode)
235 PrintBuildTimeForGolem(benchmark, stdOut)
236
237
238if __name__ == '__main__':
239 sys.exit(Main())