Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(254)

Side by Side Diff: build/android/resource_sizes.py

Issue 2757293002: Android: Add APK patch size estimates to resource_sizes.py. (Closed)
Patch Set: Fix import & make args descriptive Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Prints the size of each given file and optionally computes the size of 6 """Prints the size of each given file and optionally computes the size of
7 libchrome.so without the dependencies added for building with android NDK. 7 libchrome.so without the dependencies added for building with android NDK.
8 Also breaks down the contents of the APK to determine the installed size 8 Also breaks down the contents of the APK to determine the installed size
9 and assign size contributions to different classes of file. 9 and assign size contributions to different classes of file.
10 """ 10 """
11 11
12 import argparse 12 import argparse
13 import collections 13 import collections
14 from contextlib import contextmanager 14 from contextlib import contextmanager
15 import json 15 import json
16 import logging 16 import logging
17 import operator 17 import operator
18 import os 18 import os
19 import re 19 import re
20 import struct 20 import struct
21 import sys 21 import sys
22 import tempfile 22 import tempfile
23 import zipfile 23 import zipfile
24 import zlib 24 import zlib
25 25
26 from binary_size import apk_downloader
26 import devil_chromium 27 import devil_chromium
27 from devil.android.sdk import build_tools 28 from devil.android.sdk import build_tools
28 from devil.utils import cmd_helper 29 from devil.utils import cmd_helper
29 from devil.utils import lazy 30 from devil.utils import lazy
30 import method_count 31 import method_count
31 from pylib import constants 32 from pylib import constants
32 from pylib.constants import host_paths 33 from pylib.constants import host_paths
33 34
34 _AAPT_PATH = lazy.WeakConstant(lambda: build_tools.GetPath('aapt')) 35 _AAPT_PATH = lazy.WeakConstant(lambda: build_tools.GetPath('aapt'))
35 _GRIT_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'tools', 'grit') 36 _GRIT_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'tools', 'grit')
36 _BUILD_UTILS_PATH = os.path.join( 37 _BUILD_UTILS_PATH = os.path.join(
37 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gyp') 38 host_paths.DIR_SOURCE_ROOT, 'build', 'android', 'gyp')
39 _APK_PATCH_SIZE_ESTIMATOR_PATH = os.path.join(
40 host_paths.DIR_SOURCE_ROOT, 'third_party', 'apk-patch-size-estimator')
38 41
39 # Prepend the grit module from the source tree so it takes precedence over other 42 # Prepend the grit module from the source tree so it takes precedence over other
40 # grit versions that might present in the search path. 43 # grit versions that might present in the search path.
41 with host_paths.SysPath(_GRIT_PATH, 1): 44 with host_paths.SysPath(_GRIT_PATH, 1):
42 from grit.format import data_pack # pylint: disable=import-error 45 from grit.format import data_pack # pylint: disable=import-error
43 46
44 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): 47 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH):
45 import perf_tests_results_helper # pylint: disable=import-error 48 import perf_tests_results_helper # pylint: disable=import-error
46 49
47 with host_paths.SysPath(_BUILD_UTILS_PATH, 1): 50 with host_paths.SysPath(_BUILD_UTILS_PATH, 1):
48 from util import build_utils # pylint: disable=import-error 51 from util import build_utils # pylint: disable=import-error
49 52
53 with host_paths.SysPath(_APK_PATCH_SIZE_ESTIMATOR_PATH):
54 import apk_patch_size_estimator # pylint: disable=import-error
55
50 56
51 # Python had a bug in zipinfo parsing that triggers on ChromeModern.apk 57 # Python had a bug in zipinfo parsing that triggers on ChromeModern.apk
52 # https://bugs.python.org/issue14315 58 # https://bugs.python.org/issue14315
53 def _PatchedDecodeExtra(self): 59 def _PatchedDecodeExtra(self):
54 # Try to decode the extra field. 60 # Try to decode the extra field.
55 extra = self.extra 61 extra = self.extra
56 unpack = struct.unpack 62 unpack = struct.unpack
57 while len(extra) >= 4: 63 while len(extra) >= 4:
58 tp, ln = unpack('<HH', extra[:4]) 64 tp, ln = unpack('<HH', extra[:4])
59 if tp == 1: 65 if tp == 1:
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
667 graph_title = os.path.basename(apk_filename) + '_Dex' 673 graph_title = os.path.basename(apk_filename) + '_Dex'
668 dex_metrics = method_count.CONTRIBUTORS_TO_DEX_CACHE 674 dex_metrics = method_count.CONTRIBUTORS_TO_DEX_CACHE
669 for key, label in dex_metrics.iteritems(): 675 for key, label in dex_metrics.iteritems():
670 ReportPerfResult(chartjson, graph_title, label, sizes[key], 'entries') 676 ReportPerfResult(chartjson, graph_title, label, sizes[key], 'entries')
671 677
672 graph_title = '%sCache' % graph_title 678 graph_title = '%sCache' % graph_title
673 ReportPerfResult(chartjson, graph_title, 'DexCache', sizes['dex_cache_size'], 679 ReportPerfResult(chartjson, graph_title, 'DexCache', sizes['dex_cache_size'],
674 'bytes') 680 'bytes')
675 681
676 682
683 def _PrintPatchSizeEstimate(new_apk, builder, bucket, chartjson=None):
684 apk_name = os.path.basename(new_apk)
685 title = apk_name + '_PatchSizeEstimate'
686 # Reference APK paths have spaces replaced by underscores.
687 builder = builder.replace(' ', '_')
688 old_apk = apk_downloader.MaybeDownloadApk(
689 builder, apk_downloader.CURRENT_MILESTONE, apk_name,
690 apk_downloader.DEFAULT_DOWNLOAD_PATH, bucket)
691 if old_apk:
692 # Use a temp dir in case patch size functions fail to clean up temp files.
693 with build_utils.TempDir() as tmp:
694 tmp_name = os.path.join(tmp, 'patch.tmp')
695 bsdiff = apk_patch_size_estimator.calculate_bsdiff(
696 old_apk, new_apk, None, tmp_name)
697 ReportPerfResult(chartjson, title, 'BSDiff (gzipped)', bsdiff, 'bytes')
698 fbf = apk_patch_size_estimator.calculate_filebyfile(
699 old_apk, new_apk, None, tmp_name)
700 ReportPerfResult(chartjson, title, 'FileByFile (gzipped)', fbf, 'bytes')
701
702
677 @contextmanager 703 @contextmanager
678 def Unzip(zip_file, filename=None): 704 def Unzip(zip_file, filename=None):
679 """Utility for temporary use of a single file in a zip archive.""" 705 """Utility for temporary use of a single file in a zip archive."""
680 with build_utils.TempDir() as unzipped_dir: 706 with build_utils.TempDir() as unzipped_dir:
681 unzipped_files = build_utils.ExtractAll( 707 unzipped_files = build_utils.ExtractAll(
682 zip_file, unzipped_dir, True, pattern=filename) 708 zip_file, unzipped_dir, True, pattern=filename)
683 if len(unzipped_files) == 0: 709 if len(unzipped_files) == 0:
684 raise Exception( 710 raise Exception(
685 '%s not found in %s' % (filename, zip_file)) 711 '%s not found in %s' % (filename, zip_file))
686 yield unzipped_files[0] 712 yield unzipped_files[0]
(...skipping 18 matching lines...) Expand all
705 help='Location of the build artifacts.') 731 help='Location of the build artifacts.')
706 argparser.add_argument('--chartjson', action='store_true', 732 argparser.add_argument('--chartjson', action='store_true',
707 help='Sets output mode to chartjson.') 733 help='Sets output mode to chartjson.')
708 argparser.add_argument('--output-dir', default='.', 734 argparser.add_argument('--output-dir', default='.',
709 help='Directory to save chartjson to.') 735 help='Directory to save chartjson to.')
710 argparser.add_argument('--no-output-dir', action='store_true', 736 argparser.add_argument('--no-output-dir', action='store_true',
711 help='Skip all measurements that rely on having ' 737 help='Skip all measurements that rely on having '
712 'output-dir') 738 'output-dir')
713 argparser.add_argument('-d', '--device', 739 argparser.add_argument('-d', '--device',
714 help='Dummy option for perf runner.') 740 help='Dummy option for perf runner.')
741 argparser.add_argument('--estimate-patch-size', action='store_true',
742 help='Include patch size estimates. Useful for perf '
743 'builders where a reference APK is available but adds '
744 '~3 mins to run time.')
745 argparser.add_argument('--reference-apk-builder',
746 default=apk_downloader.DEFAULT_BUILDER,
747 help='Builder name to use for reference APK for patch '
748 'size estimates.')
749 argparser.add_argument('--reference-apk-bucket',
750 default=apk_downloader.DEFAULT_BUCKET,
751 help='Storage bucket holding reference APKs.')
715 argparser.add_argument('apk', help='APK file path.') 752 argparser.add_argument('apk', help='APK file path.')
716 args = argparser.parse_args() 753 args = argparser.parse_args()
717 754
718 chartjson = _BASE_CHART.copy() if args.chartjson else None 755 chartjson = _BASE_CHART.copy() if args.chartjson else None
719 756
720 if args.chromium_output_directory: 757 if args.chromium_output_directory:
721 constants.SetOutputDirectory(args.chromium_output_directory) 758 constants.SetOutputDirectory(args.chromium_output_directory)
722 if not args.no_output_dir: 759 if not args.no_output_dir:
723 constants.CheckOutputDirectory() 760 constants.CheckOutputDirectory()
724 devil_chromium.Initialize() 761 devil_chromium.Initialize()
725 build_vars = _ReadBuildVars(constants.GetOutDirectory()) 762 build_vars = _ReadBuildVars(constants.GetOutDirectory())
726 tools_prefix = build_vars['android_tool_prefix'] 763 tools_prefix = build_vars['android_tool_prefix']
727 else: 764 else:
728 tools_prefix = '' 765 tools_prefix = ''
729 766
730 PrintApkAnalysis(args.apk, tools_prefix, chartjson=chartjson) 767 PrintApkAnalysis(args.apk, tools_prefix, chartjson=chartjson)
731 _PrintDexAnalysis(args.apk, chartjson=chartjson) 768 _PrintDexAnalysis(args.apk, chartjson=chartjson)
769 if args.estimate_patch_size:
770 _PrintPatchSizeEstimate(
771 args.apk, args.builder, args.bucket, chartjson=chartjson)
732 if not args.no_output_dir: 772 if not args.no_output_dir:
733 PrintPakAnalysis(args.apk, args.min_pak_resource_size) 773 PrintPakAnalysis(args.apk, args.min_pak_resource_size)
734 _PrintStaticInitializersCountFromApk( 774 _PrintStaticInitializersCountFromApk(
735 args.apk, tools_prefix, chartjson=chartjson) 775 args.apk, tools_prefix, chartjson=chartjson)
736 if chartjson: 776 if chartjson:
737 results_path = os.path.join(args.output_dir, 'results-chart.json') 777 results_path = os.path.join(args.output_dir, 'results-chart.json')
738 logging.critical('Dumping json to %s', results_path) 778 logging.critical('Dumping json to %s', results_path)
739 with open(results_path, 'w') as json_file: 779 with open(results_path, 'w') as json_file:
740 json.dump(chartjson, json_file) 780 json.dump(chartjson, json_file)
741 781
742 782
743 if __name__ == '__main__': 783 if __name__ == '__main__':
744 sys.exit(main()) 784 sys.exit(main())
OLDNEW
« no previous file with comments | « build/android/binary_size/update_apks.py ('k') | third_party/apk-patch-size-estimator/README.chromium » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698