OLD | NEW |
1 #! /usr/bin/env python | 1 #! /usr/bin/env python |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | 2 # Copyright 2015 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 import argparse | 6 import argparse |
7 import collections | 7 import collections |
8 import os | 8 import os |
9 import re | 9 import re |
10 import shutil | 10 import shutil |
(...skipping 30 matching lines...) Expand all Loading... |
41 # method_ids_off : 449924 (0x06dd84) | 41 # method_ids_off : 449924 (0x06dd84) |
42 # class_defs_size : 2616 | 42 # class_defs_size : 2616 |
43 # class_defs_off : 719516 (0x0afa9c) | 43 # class_defs_off : 719516 (0x0afa9c) |
44 # data_size : 3776428 | 44 # data_size : 3776428 |
45 # data_off : 803228 (0x0c419c) | 45 # data_off : 803228 (0x0c419c) |
46 | 46 |
47 # For what these mean, refer to: | 47 # For what these mean, refer to: |
48 # https://source.android.com/devices/tech/dalvik/dex-format.html | 48 # https://source.android.com/devices/tech/dalvik/dex-format.html |
49 | 49 |
50 | 50 |
51 CONTRIBUTORS_TO_DEX_CACHE = {'type_ids_size': 'types', | 51 _CONTRIBUTORS_TO_DEX_CACHE = {'type_ids_size': 'types', |
52 'string_ids_size': 'strings', | 52 'string_ids_size': 'strings', |
53 'method_ids_size': 'methods', | 53 'method_ids_size': 'methods', |
54 'field_ids_size': 'fields'} | 54 'field_ids_size': 'fields'} |
55 | 55 |
56 | 56 |
57 def _ExtractSizesFromDexFile(dex_path): | 57 def _ExtractSizesFromDexFile(dex_path): |
58 counts = {} | 58 counts = {} |
59 for line in dexdump.DexDump(dex_path, file_summary=True): | 59 for line in dexdump.DexDump(dex_path, file_summary=True): |
60 if not line.strip(): | 60 if not line.strip(): |
61 # Each method, type, field, and string contributes 4 bytes (1 reference) | 61 # Each method, type, field, and string contributes 4 bytes (1 reference) |
62 # to our DexCache size. | 62 # to our DexCache size. |
63 counts['dex_cache_size'] = ( | 63 counts['dex_cache_size'] = ( |
64 sum(counts[x] for x in CONTRIBUTORS_TO_DEX_CACHE)) * 4 | 64 sum(counts[x] for x in _CONTRIBUTORS_TO_DEX_CACHE)) * 4 |
65 return counts | 65 return counts |
66 m = re.match(r'([a-z_]+_size) *: (\d+)', line) | 66 m = re.match(r'([a-z_]+_size) *: (\d+)', line) |
67 if m: | 67 if m: |
68 counts[m.group(1)] = int(m.group(2)) | 68 counts[m.group(1)] = int(m.group(2)) |
69 raise Exception('Unexpected end of output.') | 69 raise Exception('Unexpected end of output.') |
70 | 70 |
71 | 71 |
72 def ExtractSizesFromZip(path): | 72 def _ExtractSizesFromZip(path): |
73 tmpdir = tempfile.mkdtemp(suffix='_dex_extract') | 73 tmpdir = tempfile.mkdtemp(suffix='_dex_extract') |
74 try: | 74 try: |
75 counts = collections.defaultdict(int) | 75 counts = collections.defaultdict(int) |
76 with zipfile.ZipFile(path, 'r') as z: | 76 with zipfile.ZipFile(path, 'r') as z: |
77 for subpath in z.namelist(): | 77 for subpath in z.namelist(): |
78 if not subpath.endswith('.dex'): | 78 if not subpath.endswith('.dex'): |
79 continue | 79 continue |
80 extracted_path = z.extract(subpath, tmpdir) | 80 extracted_path = z.extract(subpath, tmpdir) |
81 cur_counts = _ExtractSizesFromDexFile(extracted_path) | 81 cur_counts = _ExtractSizesFromDexFile(extracted_path) |
82 for k in cur_counts: | 82 for k in cur_counts: |
(...skipping 19 matching lines...) Expand all Loading... |
102 if 'apk' in basename: | 102 if 'apk' in basename: |
103 args.apk_name = basename | 103 args.apk_name = basename |
104 break | 104 break |
105 dirname, basename = os.path.split(dirname) | 105 dirname, basename = os.path.split(dirname) |
106 else: | 106 else: |
107 parser.error( | 107 parser.error( |
108 'Unable to determine apk name from %s, ' | 108 'Unable to determine apk name from %s, ' |
109 'and --apk-name was not provided.' % args.dexfile) | 109 'and --apk-name was not provided.' % args.dexfile) |
110 | 110 |
111 if os.path.splitext(args.dexfile)[1] in ('.zip', '.apk', '.jar'): | 111 if os.path.splitext(args.dexfile)[1] in ('.zip', '.apk', '.jar'): |
112 sizes = ExtractSizesFromZip(args.dexfile) | 112 sizes = _ExtractSizesFromZip(args.dexfile) |
113 else: | 113 else: |
114 sizes = _ExtractSizesFromDexFile(args.dexfile) | 114 sizes = _ExtractSizesFromDexFile(args.dexfile) |
115 | 115 |
116 def print_result(name, value_key, description=None): | 116 def print_result(name, value_key, description=None): |
117 perf_tests_results_helper.PrintPerfResult( | 117 perf_tests_results_helper.PrintPerfResult( |
118 '%s_%s' % (args.apk_name, name), 'total', [sizes[value_key]], | 118 '%s_%s' % (args.apk_name, name), 'total', [sizes[value_key]], |
119 description or name) | 119 description or name) |
120 | 120 |
121 for dex_header_name, readable_name in CONTRIBUTORS_TO_DEX_CACHE.iteritems(): | 121 for dex_header_name, readable_name in _CONTRIBUTORS_TO_DEX_CACHE.iteritems(): |
122 print_result(readable_name, dex_header_name) | 122 print_result(readable_name, dex_header_name) |
123 print_result( | 123 print_result( |
124 'DexCache_size', 'dex_cache_size', 'bytes of permanent dirty memory') | 124 'DexCache_size', 'dex_cache_size', 'bytes of permanent dirty memory') |
125 return 0 | 125 return 0 |
126 | 126 |
127 if __name__ == '__main__': | 127 if __name__ == '__main__': |
128 sys.exit(main()) | 128 sys.exit(main()) |
129 | 129 |
OLD | NEW |