| 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 """ |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 173 | 173 |
| 174 def __init__(self, name): | 174 def __init__(self, name): |
| 175 self.name = name | 175 self.name = name |
| 176 self._zip_infos = [] | 176 self._zip_infos = [] |
| 177 self._extracted = [] | 177 self._extracted = [] |
| 178 | 178 |
| 179 def AddZipInfo(self, zip_info, extracted=False): | 179 def AddZipInfo(self, zip_info, extracted=False): |
| 180 self._zip_infos.append(zip_info) | 180 self._zip_infos.append(zip_info) |
| 181 self._extracted.append(extracted) | 181 self._extracted.append(extracted) |
| 182 | 182 |
| 183 def AllEntries(self): |
| 184 return iter(self._zip_infos) |
| 185 |
| 183 def GetNumEntries(self): | 186 def GetNumEntries(self): |
| 184 return len(self._zip_infos) | 187 return len(self._zip_infos) |
| 185 | 188 |
| 186 def FindByPattern(self, pattern): | 189 def FindByPattern(self, pattern): |
| 187 return next((i for i in self._zip_infos if re.match(pattern, i.filename)), | 190 return next((i for i in self._zip_infos if re.match(pattern, i.filename)), |
| 188 None) | 191 None) |
| 189 | 192 |
| 190 def FindLargest(self): | 193 def FindLargest(self): |
| 191 return max(self._zip_infos, key=lambda i: i.file_size) | 194 return max(self._zip_infos, key=lambda i: i.file_size) |
| 192 | 195 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 220 java_code = make_group('Java code') | 223 java_code = make_group('Java code') |
| 221 native_resources_no_translations = make_group('Native resources (no l10n)') | 224 native_resources_no_translations = make_group('Native resources (no l10n)') |
| 222 translations = make_group('Native resources (l10n)') | 225 translations = make_group('Native resources (l10n)') |
| 223 icu_data = make_group('ICU (i18n library) data') | 226 icu_data = make_group('ICU (i18n library) data') |
| 224 v8_snapshots = make_group('V8 Snapshots') | 227 v8_snapshots = make_group('V8 Snapshots') |
| 225 png_drawables = make_group('PNG drawables') | 228 png_drawables = make_group('PNG drawables') |
| 226 res_directory = make_group('Non-compiled Android resources') | 229 res_directory = make_group('Non-compiled Android resources') |
| 227 arsc = make_group('Compiled Android resources') | 230 arsc = make_group('Compiled Android resources') |
| 228 metadata = make_group('Package metadata') | 231 metadata = make_group('Package metadata') |
| 229 unknown = make_group('Unknown files') | 232 unknown = make_group('Unknown files') |
| 233 notices = make_group('licenses.notice file') |
| 230 | 234 |
| 231 apk = zipfile.ZipFile(apk_filename, 'r') | 235 apk = zipfile.ZipFile(apk_filename, 'r') |
| 232 try: | 236 try: |
| 233 apk_contents = apk.infolist() | 237 apk_contents = apk.infolist() |
| 234 finally: | 238 finally: |
| 235 apk.close() | 239 apk.close() |
| 236 | 240 |
| 237 total_apk_size = os.path.getsize(apk_filename) | 241 total_apk_size = os.path.getsize(apk_filename) |
| 238 apk_basename = os.path.basename(apk_filename) | 242 apk_basename = os.path.basename(apk_filename) |
| 239 | 243 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 255 elif filename.endswith('.bin'): | 259 elif filename.endswith('.bin'): |
| 256 v8_snapshots.AddZipInfo(member) | 260 v8_snapshots.AddZipInfo(member) |
| 257 elif filename.endswith('.png') or filename.endswith('.webp'): | 261 elif filename.endswith('.png') or filename.endswith('.webp'): |
| 258 png_drawables.AddZipInfo(member) | 262 png_drawables.AddZipInfo(member) |
| 259 elif filename.startswith('res/'): | 263 elif filename.startswith('res/'): |
| 260 res_directory.AddZipInfo(member) | 264 res_directory.AddZipInfo(member) |
| 261 elif filename.endswith('.arsc'): | 265 elif filename.endswith('.arsc'): |
| 262 arsc.AddZipInfo(member) | 266 arsc.AddZipInfo(member) |
| 263 elif filename.startswith('META-INF') or filename == 'AndroidManifest.xml': | 267 elif filename.startswith('META-INF') or filename == 'AndroidManifest.xml': |
| 264 metadata.AddZipInfo(member) | 268 metadata.AddZipInfo(member) |
| 269 elif filename.endswith('.notice'): |
| 270 notices.AddZipInfo(member) |
| 265 else: | 271 else: |
| 266 unknown.AddZipInfo(member) | 272 unknown.AddZipInfo(member) |
| 267 | 273 |
| 268 total_install_size = total_apk_size | 274 total_install_size = total_apk_size |
| 269 | 275 |
| 270 for group in file_groups: | 276 for group in file_groups: |
| 271 install_size = group.ComputeInstallSize() | 277 install_size = group.ComputeInstallSize() |
| 272 total_install_size += group.ComputeExtractedSize() | 278 total_install_size += group.ComputeExtractedSize() |
| 273 | 279 |
| 274 ReportPerfResult(chartjson, apk_basename + '_Breakdown', | 280 ReportPerfResult(chartjson, apk_basename + '_Breakdown', |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 normalized_apk_size = total_apk_size | 317 normalized_apk_size = total_apk_size |
| 312 # Always look at uncompressed .dex & .so. | 318 # Always look at uncompressed .dex & .so. |
| 313 normalized_apk_size -= java_code.ComputeZippedSize() | 319 normalized_apk_size -= java_code.ComputeZippedSize() |
| 314 normalized_apk_size += java_code.ComputeUncompressedSize() | 320 normalized_apk_size += java_code.ComputeUncompressedSize() |
| 315 normalized_apk_size -= native_code.ComputeZippedSize() | 321 normalized_apk_size -= native_code.ComputeZippedSize() |
| 316 normalized_apk_size += native_code.ComputeUncompressedSize() | 322 normalized_apk_size += native_code.ComputeUncompressedSize() |
| 317 # Avoid noise caused when strings change and translations haven't yet been | 323 # Avoid noise caused when strings change and translations haven't yet been |
| 318 # updated. | 324 # updated. |
| 319 english_pak = translations.FindByPattern(r'.*/en[-_][Uu][Ss]\.l?pak') | 325 english_pak = translations.FindByPattern(r'.*/en[-_][Uu][Ss]\.l?pak') |
| 320 if english_pak: | 326 if english_pak: |
| 327 # TODO(agrieve): This should also analyze .arsc file to remove non-en |
| 328 # configs. http://crbug.com/677966 |
| 321 normalized_apk_size -= translations.ComputeZippedSize() | 329 normalized_apk_size -= translations.ComputeZippedSize() |
| 322 # 1.17 found by looking at Chrome.apk and seeing how much smaller en-US.pak | 330 # 1.17 found by looking at Chrome.apk and seeing how much smaller en-US.pak |
| 323 # is relative to the average locale .pak. | 331 # is relative to the average locale .pak. |
| 324 normalized_apk_size += int( | 332 normalized_apk_size += int( |
| 325 english_pak.compress_size * translations.GetNumEntries() * 1.17) | 333 english_pak.compress_size * translations.GetNumEntries() * 1.17) |
| 326 | 334 |
| 327 ReportPerfResult(chartjson, apk_basename + '_Specifics', | 335 ReportPerfResult(chartjson, apk_basename + '_Specifics', |
| 328 'normalized apk size', normalized_apk_size, 'bytes') | 336 'normalized apk size', normalized_apk_size, 'bytes') |
| 329 | 337 |
| 330 ReportPerfResult(chartjson, apk_basename + '_Specifics', | 338 ReportPerfResult(chartjson, apk_basename + '_Specifics', |
| 331 'file count', len(apk_contents), 'zip entries') | 339 'file count', len(apk_contents), 'zip entries') |
| 332 | 340 |
| 341 for info in unknown.AllEntries(): |
| 342 print 'Unknown entry:', info.filename, info.compress_size |
| 343 |
| 333 | 344 |
| 334 def IsPakFileName(file_name): | 345 def IsPakFileName(file_name): |
| 335 """Returns whether the given file name ends with .pak or .lpak.""" | 346 """Returns whether the given file name ends with .pak or .lpak.""" |
| 336 return file_name.endswith('.pak') or file_name.endswith('.lpak') | 347 return file_name.endswith('.pak') or file_name.endswith('.lpak') |
| 337 | 348 |
| 338 | 349 |
| 339 def PrintPakAnalysis(apk_filename, min_pak_resource_size): | 350 def PrintPakAnalysis(apk_filename, min_pak_resource_size): |
| 340 """Print sizes of all resources in all pak files in |apk_filename|.""" | 351 """Print sizes of all resources in all pak files in |apk_filename|.""" |
| 341 print | 352 print |
| 342 print 'Analyzing pak files in %s...' % apk_filename | 353 print 'Analyzing pak files in %s...' % apk_filename |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 | 604 |
| 594 if chartjson: | 605 if chartjson: |
| 595 results_path = os.path.join(options.output_dir, 'results-chart.json') | 606 results_path = os.path.join(options.output_dir, 'results-chart.json') |
| 596 logging.critical('Dumping json to %s', results_path) | 607 logging.critical('Dumping json to %s', results_path) |
| 597 with open(results_path, 'w') as json_file: | 608 with open(results_path, 'w') as json_file: |
| 598 json.dump(chartjson, json_file) | 609 json.dump(chartjson, json_file) |
| 599 | 610 |
| 600 | 611 |
| 601 if __name__ == '__main__': | 612 if __name__ == '__main__': |
| 602 sys.exit(main(sys.argv)) | 613 sys.exit(main(sys.argv)) |
| OLD | NEW |