tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

diff_resource_sizes.py (8089B)


      1 #!/usr/bin/env python3
      2 # Copyright 2017 The Chromium Authors
      3 # 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 
      8 
      9 import argparse
     10 import json
     11 import logging
     12 import os
     13 import subprocess
     14 import sys
     15 
     16 from pylib.constants import host_paths
     17 
     18 with host_paths.SysPath(host_paths.BUILD_UTIL_PATH):
     19  from lib.common import perf_tests_results_helper
     20 
     21 with host_paths.SysPath(host_paths.TRACING_PATH):
     22  from tracing.value import convert_chart_json # pylint: disable=import-error
     23 
     24 _ANDROID_DIR = os.path.dirname(os.path.abspath(__file__))
     25 with host_paths.SysPath(os.path.join(_ANDROID_DIR, 'gyp')):
     26  from util import build_utils  # pylint: disable=import-error
     27 
     28 
     29 _BASE_CHART = {
     30    'format_version': '0.1',
     31    'benchmark_name': 'resource_sizes_diff',
     32    'benchmark_description': 'APK resource size diff information',
     33    'trace_rerun_options': [],
     34    'charts': {},
     35 }
     36 
     37 _CHARTJSON_FILENAME = 'results-chart.json'
     38 _HISTOGRAMS_FILENAME = 'perf_results.json'
     39 
     40 
     41 def DiffResults(chartjson, base_results, diff_results):
     42  """Reports the diff between the two given results.
     43 
     44  Args:
     45    chartjson: A dictionary that chartjson results will be placed in, or None
     46        to only print results.
     47    base_results: The chartjson-formatted size results of the base APK.
     48    diff_results: The chartjson-formatted size results of the diff APK.
     49  """
     50  for graph_title, graph in base_results['charts'].items():
     51    for trace_title, trace in graph.items():
     52      perf_tests_results_helper.ReportPerfResult(
     53          chartjson, graph_title, trace_title,
     54          diff_results['charts'][graph_title][trace_title]['value']
     55              - trace['value'],
     56          trace['units'], trace['improvement_direction'],
     57          trace['important'])
     58 
     59 
     60 def AddIntermediateResults(chartjson, base_results, diff_results):
     61  """Copies the intermediate size results into the output chartjson.
     62 
     63  Args:
     64    chartjson: A dictionary that chartjson results will be placed in.
     65    base_results: The chartjson-formatted size results of the base APK.
     66    diff_results: The chartjson-formatted size results of the diff APK.
     67  """
     68  for graph_title, graph in base_results['charts'].items():
     69    for trace_title, trace in graph.items():
     70      perf_tests_results_helper.ReportPerfResult(
     71          chartjson, graph_title + '_base_apk', trace_title,
     72          trace['value'], trace['units'], trace['improvement_direction'],
     73          trace['important'])
     74 
     75  # Both base_results and diff_results should have the same charts/traces, but
     76  # loop over them separately in case they don't
     77  for graph_title, graph in diff_results['charts'].items():
     78    for trace_title, trace in graph.items():
     79      perf_tests_results_helper.ReportPerfResult(
     80          chartjson, graph_title + '_diff_apk', trace_title,
     81          trace['value'], trace['units'], trace['improvement_direction'],
     82          trace['important'])
     83 
     84 
     85 def _CreateArgparser():
     86  def chromium_path(arg):
     87    if arg.startswith('//'):
     88      return os.path.join(host_paths.DIR_SOURCE_ROOT, arg[2:])
     89    return arg
     90 
     91  argparser = argparse.ArgumentParser(
     92      description='Diff resource sizes of two APKs. Arguments not listed here '
     93                  'will be passed on to both invocations of resource_sizes.py.')
     94  argparser.add_argument('--chromium-output-directory-base',
     95                         dest='out_dir_base',
     96                         type=chromium_path,
     97                         help='Location of the build artifacts for the base '
     98                              'APK, i.e. what the size increase/decrease will '
     99                              'be measured from.')
    100  argparser.add_argument('--chromium-output-directory-diff',
    101                         dest='out_dir_diff',
    102                         type=chromium_path,
    103                         help='Location of the build artifacts for the diff '
    104                              'APK.')
    105  argparser.add_argument('--chartjson',
    106                         action='store_true',
    107                         help='DEPRECATED. Use --output-format=chartjson '
    108                              'instead.')
    109  argparser.add_argument('--output-format',
    110                         choices=['chartjson', 'histograms'],
    111                         help='Output the results to a file in the given '
    112                              'format instead of printing the results.')
    113  argparser.add_argument('--include-intermediate-results',
    114                         action='store_true',
    115                         help='Include the results from the resource_sizes.py '
    116                              'runs in the chartjson output.')
    117  argparser.add_argument('--output-dir',
    118                         default='.',
    119                         type=chromium_path,
    120                         help='Directory to save chartjson to.')
    121  argparser.add_argument('--base-apk',
    122                         required=True,
    123                         type=chromium_path,
    124                         help='Path to the base APK, i.e. what the size '
    125                              'increase/decrease will be measured from.')
    126  argparser.add_argument('--diff-apk',
    127                         required=True,
    128                         type=chromium_path,
    129                         help='Path to the diff APK, i.e. the APK whose size '
    130                              'increase/decrease will be measured against the '
    131                              'base APK.')
    132  return argparser
    133 
    134 
    135 def main():
    136  args, unknown_args = _CreateArgparser().parse_known_args()
    137  # TODO(bsheedy): Remove this once all uses of --chartjson are removed.
    138  if args.chartjson:
    139    args.output_format = 'chartjson'
    140 
    141  chartjson = _BASE_CHART.copy() if args.output_format else None
    142 
    143  with build_utils.TempDir() as base_dir, build_utils.TempDir() as diff_dir:
    144    # Run resource_sizes.py on the two APKs
    145    resource_sizes_path = os.path.join(_ANDROID_DIR, 'resource_sizes.py')
    146    shared_args = (['python', resource_sizes_path, '--output-format=chartjson']
    147                   + unknown_args)
    148 
    149    base_args = shared_args + ['--output-dir', base_dir, args.base_apk]
    150    if args.out_dir_base:
    151      base_args += ['--chromium-output-directory', args.out_dir_base]
    152    try:
    153      subprocess.check_output(base_args, stderr=subprocess.STDOUT)
    154    except subprocess.CalledProcessError as e:
    155      print(e.output)
    156      raise
    157 
    158    diff_args = shared_args + ['--output-dir', diff_dir, args.diff_apk]
    159    if args.out_dir_diff:
    160      diff_args += ['--chromium-output-directory', args.out_dir_diff]
    161    try:
    162      subprocess.check_output(diff_args, stderr=subprocess.STDOUT)
    163    except subprocess.CalledProcessError as e:
    164      print(e.output)
    165      raise
    166 
    167    # Combine the separate results
    168    with open(os.path.join(base_dir, _CHARTJSON_FILENAME)) as base_file:
    169      base_results = json.load(base_file)
    170    with open(os.path.join(diff_dir, _CHARTJSON_FILENAME)) as diff_file:
    171      diff_results = json.load(diff_file)
    172    DiffResults(chartjson, base_results, diff_results)
    173    if args.include_intermediate_results:
    174      AddIntermediateResults(chartjson, base_results, diff_results)
    175 
    176    if args.output_format:
    177      chartjson_path = os.path.join(os.path.abspath(args.output_dir),
    178                                    _CHARTJSON_FILENAME)
    179      logging.critical('Dumping diff chartjson to %s', chartjson_path)
    180      with open(chartjson_path, 'w') as outfile:
    181        json.dump(chartjson, outfile)
    182 
    183      if args.output_format == 'histograms':
    184        histogram_result = convert_chart_json.ConvertChartJson(chartjson_path)
    185        if histogram_result.returncode != 0:
    186          logging.error('chartjson conversion failed with error: %s',
    187              histogram_result.stdout)
    188          return 1
    189 
    190        histogram_path = os.path.join(os.path.abspath(args.output_dir),
    191            'perf_results.json')
    192        logging.critical('Dumping diff histograms to %s', histogram_path)
    193        with open(histogram_path, 'w') as json_file:
    194          json_file.write(histogram_result.stdout)
    195  return 0
    196 
    197 
    198 if __name__ == '__main__':
    199  sys.exit(main())