OLD | NEW |
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 collections | 12 import collections |
13 import json | 13 import json |
14 import logging | 14 import logging |
15 import operator | 15 import operator |
16 import optparse | 16 import optparse |
17 import os | 17 import os |
18 import re | 18 import re |
| 19 import struct |
19 import sys | 20 import sys |
20 import tempfile | 21 import tempfile |
21 import zipfile | 22 import zipfile |
22 import zlib | 23 import zlib |
23 | 24 |
24 import devil_chromium | 25 import devil_chromium |
25 from devil.utils import cmd_helper | 26 from devil.utils import cmd_helper |
26 from pylib import constants | 27 from pylib import constants |
27 from pylib.constants import host_paths | 28 from pylib.constants import host_paths |
28 | 29 |
29 _GRIT_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'tools', 'grit') | 30 _GRIT_PATH = os.path.join(host_paths.DIR_SOURCE_ROOT, 'tools', 'grit') |
30 | 31 |
31 with host_paths.SysPath(_GRIT_PATH): | 32 with host_paths.SysPath(_GRIT_PATH): |
32 from grit.format import data_pack # pylint: disable=import-error | 33 from grit.format import data_pack # pylint: disable=import-error |
33 | 34 |
34 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): | 35 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): |
35 import perf_tests_results_helper # pylint: disable=import-error | 36 import perf_tests_results_helper # pylint: disable=import-error |
36 | 37 |
| 38 # Python had a bug in zipinfo parsing that triggers on ChromeModern.apk |
| 39 # https://bugs.python.org/issue14315 |
| 40 def _PatchedDecodeExtra(self): |
| 41 # Try to decode the extra field. |
| 42 extra = self.extra |
| 43 unpack = struct.unpack |
| 44 while len(extra) >= 4: |
| 45 tp, ln = unpack('<HH', extra[:4]) |
| 46 if tp == 1: |
| 47 if ln >= 24: |
| 48 counts = unpack('<QQQ', extra[4:28]) |
| 49 elif ln == 16: |
| 50 counts = unpack('<QQ', extra[4:20]) |
| 51 elif ln == 8: |
| 52 counts = unpack('<Q', extra[4:12]) |
| 53 elif ln == 0: |
| 54 counts = () |
| 55 else: |
| 56 raise RuntimeError, "Corrupt extra field %s"%(ln,) |
| 57 |
| 58 idx = 0 |
| 59 |
| 60 # ZIP64 extension (large files and/or large archives) |
| 61 if self.file_size in (0xffffffffffffffffL, 0xffffffffL): |
| 62 self.file_size = counts[idx] |
| 63 idx += 1 |
| 64 |
| 65 if self.compress_size == 0xFFFFFFFFL: |
| 66 self.compress_size = counts[idx] |
| 67 idx += 1 |
| 68 |
| 69 if self.header_offset == 0xffffffffL: |
| 70 self.header_offset = counts[idx] |
| 71 idx += 1 |
| 72 |
| 73 extra = extra[ln + 4:] |
| 74 |
| 75 zipfile.ZipInfo._decodeExtra = ( # pylint: disable=protected-access |
| 76 _PatchedDecodeExtra) |
37 | 77 |
38 # Static initializers expected in official builds. Note that this list is built | 78 # Static initializers expected in official builds. Note that this list is built |
39 # using 'nm' on libchrome.so which results from a GCC official build (i.e. | 79 # using 'nm' on libchrome.so which results from a GCC official build (i.e. |
40 # Clang is not supported currently). | 80 # Clang is not supported currently). |
41 | 81 |
42 _BASE_CHART = { | 82 _BASE_CHART = { |
43 'format_version': '0.1', | 83 'format_version': '0.1', |
44 'benchmark_name': 'resource_sizes', | 84 'benchmark_name': 'resource_sizes', |
45 'benchmark_description': 'APK resource size information.', | 85 'benchmark_description': 'APK resource size information.', |
46 'trace_rerun_options': [], | 86 'trace_rerun_options': [], |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 | 449 |
410 if chartjson: | 450 if chartjson: |
411 results_path = os.path.join(options.output_dir, 'results-chart.json') | 451 results_path = os.path.join(options.output_dir, 'results-chart.json') |
412 logging.critical('Dumping json to %s', results_path) | 452 logging.critical('Dumping json to %s', results_path) |
413 with open(results_path, 'w') as json_file: | 453 with open(results_path, 'w') as json_file: |
414 json.dump(chartjson, json_file) | 454 json.dump(chartjson, json_file) |
415 | 455 |
416 | 456 |
417 if __name__ == '__main__': | 457 if __name__ == '__main__': |
418 sys.exit(main(sys.argv)) | 458 sys.exit(main(sys.argv)) |
OLD | NEW |