blob: 79c0a3d33607b23b77272c0a42eb40831fdedc7a [file] [log] [blame]
Peter Wen0cea52b2021-08-18 16:11:061#!/usr/bin/env python3
Avi Drissman73a09d12022-09-08 20:33:382# Copyright 2017 The Chromium Authors
bsheedy20e696b2017-09-13 20:31:053# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Runs resource_sizes.py on two apks and outputs the diff."""
7
Raul Tambre9e24293b2019-05-12 06:11:078from __future__ import print_function
9
bsheedy20e696b2017-09-13 20:31:0510import argparse
11import json
bsheedy889406d2018-11-01 19:43:3412import logging
bsheedy20e696b2017-09-13 20:31:0513import os
14import subprocess
15import sys
16
17from pylib.constants import host_paths
18from pylib.utils import shared_preference_utils
19
20with host_paths.SysPath(host_paths.BUILD_COMMON_PATH):
21 import perf_tests_results_helper # pylint: disable=import-error
22
bsheedy889406d2018-11-01 19:43:3423with host_paths.SysPath(host_paths.TRACING_PATH):
24 from tracing.value import convert_chart_json # pylint: disable=import-error
25
bsheedy20e696b2017-09-13 20:31:0526_ANDROID_DIR = os.path.dirname(os.path.abspath(__file__))
Brian Sheedy45ea5b92019-04-16 17:37:4827with host_paths.SysPath(os.path.join(_ANDROID_DIR, 'gyp')):
28 from util import build_utils # pylint: disable=import-error
bsheedy20e696b2017-09-13 20:31:0529
30
31_BASE_CHART = {
32 'format_version': '0.1',
33 'benchmark_name': 'resource_sizes_diff',
34 'benchmark_description': 'APK resource size diff information',
35 'trace_rerun_options': [],
36 'charts': {},
37}
38
bsheedy889406d2018-11-01 19:43:3439_CHARTJSON_FILENAME = 'results-chart.json'
40_HISTOGRAMS_FILENAME = 'perf_results.json'
bsheedy20e696b2017-09-13 20:31:0541
42
43def DiffResults(chartjson, base_results, diff_results):
44 """Reports the diff between the two given results.
45
46 Args:
47 chartjson: A dictionary that chartjson results will be placed in, or None
48 to only print results.
49 base_results: The chartjson-formatted size results of the base APK.
50 diff_results: The chartjson-formatted size results of the diff APK.
51 """
Ben Joyced7822952021-08-17 17:19:0352 for graph_title, graph in base_results['charts'].items():
53 for trace_title, trace in graph.items():
bsheedy20e696b2017-09-13 20:31:0554 perf_tests_results_helper.ReportPerfResult(
55 chartjson, graph_title, trace_title,
56 diff_results['charts'][graph_title][trace_title]['value']
57 - trace['value'],
58 trace['units'], trace['improvement_direction'],
59 trace['important'])
60
61
62def AddIntermediateResults(chartjson, base_results, diff_results):
63 """Copies the intermediate size results into the output chartjson.
64
65 Args:
66 chartjson: A dictionary that chartjson results will be placed in.
67 base_results: The chartjson-formatted size results of the base APK.
68 diff_results: The chartjson-formatted size results of the diff APK.
69 """
Ben Joyced7822952021-08-17 17:19:0370 for graph_title, graph in base_results['charts'].items():
71 for trace_title, trace in graph.items():
bsheedy20e696b2017-09-13 20:31:0572 perf_tests_results_helper.ReportPerfResult(
73 chartjson, graph_title + '_base_apk', trace_title,
74 trace['value'], trace['units'], trace['improvement_direction'],
75 trace['important'])
76
77 # Both base_results and diff_results should have the same charts/traces, but
78 # loop over them separately in case they don't
Ben Joyced7822952021-08-17 17:19:0379 for graph_title, graph in diff_results['charts'].items():
80 for trace_title, trace in graph.items():
bsheedy20e696b2017-09-13 20:31:0581 perf_tests_results_helper.ReportPerfResult(
82 chartjson, graph_title + '_diff_apk', trace_title,
83 trace['value'], trace['units'], trace['improvement_direction'],
84 trace['important'])
85
86
87def _CreateArgparser():
bsheedy852269e2017-09-22 19:51:1088 def chromium_path(arg):
89 if arg.startswith('//'):
90 return os.path.join(host_paths.DIR_SOURCE_ROOT, arg[2:])
91 return arg
92
bsheedy20e696b2017-09-13 20:31:0593 argparser = argparse.ArgumentParser(
94 description='Diff resource sizes of two APKs. Arguments not listed here '
95 'will be passed on to both invocations of resource_sizes.py.')
96 argparser.add_argument('--chromium-output-directory-base',
97 dest='out_dir_base',
bsheedy852269e2017-09-22 19:51:1098 type=chromium_path,
bsheedy20e696b2017-09-13 20:31:0599 help='Location of the build artifacts for the base '
100 'APK, i.e. what the size increase/decrease will '
101 'be measured from.')
102 argparser.add_argument('--chromium-output-directory-diff',
103 dest='out_dir_diff',
bsheedy852269e2017-09-22 19:51:10104 type=chromium_path,
bsheedy20e696b2017-09-13 20:31:05105 help='Location of the build artifacts for the diff '
106 'APK.')
107 argparser.add_argument('--chartjson',
108 action='store_true',
bsheedy889406d2018-11-01 19:43:34109 help='DEPRECATED. Use --output-format=chartjson '
110 'instead.')
111 argparser.add_argument('--output-format',
112 choices=['chartjson', 'histograms'],
113 help='Output the results to a file in the given '
114 'format instead of printing the results.')
bsheedy20e696b2017-09-13 20:31:05115 argparser.add_argument('--include-intermediate-results',
116 action='store_true',
117 help='Include the results from the resource_sizes.py '
118 'runs in the chartjson output.')
119 argparser.add_argument('--output-dir',
120 default='.',
bsheedy852269e2017-09-22 19:51:10121 type=chromium_path,
bsheedy20e696b2017-09-13 20:31:05122 help='Directory to save chartjson to.')
123 argparser.add_argument('--base-apk',
124 required=True,
bsheedy852269e2017-09-22 19:51:10125 type=chromium_path,
bsheedy20e696b2017-09-13 20:31:05126 help='Path to the base APK, i.e. what the size '
127 'increase/decrease will be measured from.')
128 argparser.add_argument('--diff-apk',
129 required=True,
bsheedy852269e2017-09-22 19:51:10130 type=chromium_path,
bsheedy20e696b2017-09-13 20:31:05131 help='Path to the diff APK, i.e. the APK whose size '
132 'increase/decrease will be measured against the '
133 'base APK.')
134 return argparser
135
136
137def main():
138 args, unknown_args = _CreateArgparser().parse_known_args()
bsheedy889406d2018-11-01 19:43:34139 # TODO(bsheedy): Remove this once all uses of --chartjson are removed.
140 if args.chartjson:
141 args.output_format = 'chartjson'
142
143 chartjson = _BASE_CHART.copy() if args.output_format else None
bsheedy20e696b2017-09-13 20:31:05144
145 with build_utils.TempDir() as base_dir, build_utils.TempDir() as diff_dir:
146 # Run resource_sizes.py on the two APKs
147 resource_sizes_path = os.path.join(_ANDROID_DIR, 'resource_sizes.py')
bsheedy889406d2018-11-01 19:43:34148 shared_args = (['python', resource_sizes_path, '--output-format=chartjson']
bsheedy20e696b2017-09-13 20:31:05149 + unknown_args)
150
151 base_args = shared_args + ['--output-dir', base_dir, args.base_apk]
152 if args.out_dir_base:
153 base_args += ['--chromium-output-directory', args.out_dir_base]
bsheedya9d10792017-09-23 21:47:11154 try:
155 subprocess.check_output(base_args, stderr=subprocess.STDOUT)
156 except subprocess.CalledProcessError as e:
Raul Tambre9e24293b2019-05-12 06:11:07157 print(e.output)
bsheedya9d10792017-09-23 21:47:11158 raise
bsheedy20e696b2017-09-13 20:31:05159
160 diff_args = shared_args + ['--output-dir', diff_dir, args.diff_apk]
161 if args.out_dir_diff:
bsheedy135012ca2017-09-26 00:00:40162 diff_args += ['--chromium-output-directory', args.out_dir_diff]
bsheedya9d10792017-09-23 21:47:11163 try:
164 subprocess.check_output(diff_args, stderr=subprocess.STDOUT)
165 except subprocess.CalledProcessError as e:
Raul Tambre9e24293b2019-05-12 06:11:07166 print(e.output)
bsheedya9d10792017-09-23 21:47:11167 raise
bsheedy20e696b2017-09-13 20:31:05168
169 # Combine the separate results
bsheedy889406d2018-11-01 19:43:34170 base_file = os.path.join(base_dir, _CHARTJSON_FILENAME)
171 diff_file = os.path.join(diff_dir, _CHARTJSON_FILENAME)
bsheedy20e696b2017-09-13 20:31:05172 base_results = shared_preference_utils.ExtractSettingsFromJson(base_file)
173 diff_results = shared_preference_utils.ExtractSettingsFromJson(diff_file)
174 DiffResults(chartjson, base_results, diff_results)
175 if args.include_intermediate_results:
176 AddIntermediateResults(chartjson, base_results, diff_results)
177
bsheedy889406d2018-11-01 19:43:34178 if args.output_format:
179 chartjson_path = os.path.join(os.path.abspath(args.output_dir),
180 _CHARTJSON_FILENAME)
181 logging.critical('Dumping diff chartjson to %s', chartjson_path)
182 with open(chartjson_path, 'w') as outfile:
bsheedy20e696b2017-09-13 20:31:05183 json.dump(chartjson, outfile)
184
bsheedy889406d2018-11-01 19:43:34185 if args.output_format == 'histograms':
186 histogram_result = convert_chart_json.ConvertChartJson(chartjson_path)
187 if histogram_result.returncode != 0:
188 logging.error('chartjson conversion failed with error: %s',
189 histogram_result.stdout)
190 return 1
191
192 histogram_path = os.path.join(os.path.abspath(args.output_dir),
193 'perf_results.json')
194 logging.critical('Dumping diff histograms to %s', histogram_path)
195 with open(histogram_path, 'w') as json_file:
196 json_file.write(histogram_result.stdout)
Yoshisato Yanagisawa0f42f102021-11-30 14:04:37197 return 0
bsheedy889406d2018-11-01 19:43:34198
199
bsheedy20e696b2017-09-13 20:31:05200if __name__ == '__main__':
201 sys.exit(main())