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

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

Issue 2757293002: Android: Add APK patch size estimates to resource_sizes.py. (Closed)
Patch Set: Comment patch-size estimating slowness 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 as patch_size # pylint: disable=import-error
agrieve 2017/03/20 17:53:40 nit: you have a double space in here, although eve
estevenson 2017/03/20 18:02:37 Done.
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 = patch_size.calculate_bsdiff(old_apk, new_apk, None, tmp_name)
696 ReportPerfResult(chartjson, title, 'BSDiff (gzipped)', bsdiff, 'bytes')
697 fbf = patch_size.calculate_filebyfile(old_apk, new_apk, None, tmp_name)
698 ReportPerfResult(chartjson, title, 'FileByFile (gzipped)', fbf, 'bytes')
699
700
677 @contextmanager 701 @contextmanager
678 def Unzip(zip_file, filename=None): 702 def Unzip(zip_file, filename=None):
679 """Utility for temporary use of a single file in a zip archive.""" 703 """Utility for temporary use of a single file in a zip archive."""
680 with build_utils.TempDir() as unzipped_dir: 704 with build_utils.TempDir() as unzipped_dir:
681 unzipped_files = build_utils.ExtractAll( 705 unzipped_files = build_utils.ExtractAll(
682 zip_file, unzipped_dir, True, pattern=filename) 706 zip_file, unzipped_dir, True, pattern=filename)
683 if len(unzipped_files) == 0: 707 if len(unzipped_files) == 0:
684 raise Exception( 708 raise Exception(
685 '%s not found in %s' % (filename, zip_file)) 709 '%s not found in %s' % (filename, zip_file))
686 yield unzipped_files[0] 710 yield unzipped_files[0]
(...skipping 18 matching lines...) Expand all
705 help='Location of the build artifacts.') 729 help='Location of the build artifacts.')
706 argparser.add_argument('--chartjson', action='store_true', 730 argparser.add_argument('--chartjson', action='store_true',
707 help='Sets output mode to chartjson.') 731 help='Sets output mode to chartjson.')
708 argparser.add_argument('--output-dir', default='.', 732 argparser.add_argument('--output-dir', default='.',
709 help='Directory to save chartjson to.') 733 help='Directory to save chartjson to.')
710 argparser.add_argument('--no-output-dir', action='store_true', 734 argparser.add_argument('--no-output-dir', action='store_true',
711 help='Skip all measurements that rely on having ' 735 help='Skip all measurements that rely on having '
712 'output-dir') 736 'output-dir')
713 argparser.add_argument('-d', '--device', 737 argparser.add_argument('-d', '--device',
714 help='Dummy option for perf runner.') 738 help='Dummy option for perf runner.')
739 argparser.add_argument('--estimate-patch-size', action='store_true',
740 help='Include patch size estimates. Useful for perf '
741 'builders where a reference APK is available but adds '
742 '~3 mins to run time.')
743 argparser.add_argument('--builder', default=apk_downloader.DEFAULT_BUILDER,
744 help='Builder name to use for reference APK for patch '
745 'size estimates.')
746 argparser.add_argument('--bucket', default=apk_downloader.DEFAULT_BUCKET,
agrieve 2017/03/20 17:53:40 name bikeshed: how about --reference-apk-bucket an
estevenson 2017/03/20 18:02:36 Done.
747 help='Storage bucket holding reference APKs.')
715 argparser.add_argument('apk', help='APK file path.') 748 argparser.add_argument('apk', help='APK file path.')
716 args = argparser.parse_args() 749 args = argparser.parse_args()
717 750
718 chartjson = _BASE_CHART.copy() if args.chartjson else None 751 chartjson = _BASE_CHART.copy() if args.chartjson else None
719 752
720 if args.chromium_output_directory: 753 if args.chromium_output_directory:
721 constants.SetOutputDirectory(args.chromium_output_directory) 754 constants.SetOutputDirectory(args.chromium_output_directory)
722 if not args.no_output_dir: 755 if not args.no_output_dir:
723 constants.CheckOutputDirectory() 756 constants.CheckOutputDirectory()
724 devil_chromium.Initialize() 757 devil_chromium.Initialize()
725 build_vars = _ReadBuildVars(constants.GetOutDirectory()) 758 build_vars = _ReadBuildVars(constants.GetOutDirectory())
726 tools_prefix = build_vars['android_tool_prefix'] 759 tools_prefix = build_vars['android_tool_prefix']
727 else: 760 else:
728 tools_prefix = '' 761 tools_prefix = ''
729 762
730 PrintApkAnalysis(args.apk, tools_prefix, chartjson=chartjson) 763 PrintApkAnalysis(args.apk, tools_prefix, chartjson=chartjson)
731 _PrintDexAnalysis(args.apk, chartjson=chartjson) 764 _PrintDexAnalysis(args.apk, chartjson=chartjson)
765 if args.estimate_patch_size:
766 _PrintPatchSizeEstimate(
767 args.apk, args.builder, args.bucket, chartjson=chartjson)
732 if not args.no_output_dir: 768 if not args.no_output_dir:
733 PrintPakAnalysis(args.apk, args.min_pak_resource_size) 769 PrintPakAnalysis(args.apk, args.min_pak_resource_size)
734 _PrintStaticInitializersCountFromApk( 770 _PrintStaticInitializersCountFromApk(
735 args.apk, tools_prefix, chartjson=chartjson) 771 args.apk, tools_prefix, chartjson=chartjson)
736 if chartjson: 772 if chartjson:
737 results_path = os.path.join(args.output_dir, 'results-chart.json') 773 results_path = os.path.join(args.output_dir, 'results-chart.json')
738 logging.critical('Dumping json to %s', results_path) 774 logging.critical('Dumping json to %s', results_path)
739 with open(results_path, 'w') as json_file: 775 with open(results_path, 'w') as json_file:
740 json.dump(chartjson, json_file) 776 json.dump(chartjson, json_file)
741 777
742 778
743 if __name__ == '__main__': 779 if __name__ == '__main__':
744 sys.exit(main()) 780 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