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

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

Issue 2302903002: Revert of 🚀 Add dex info and static initializers to resource_sizes.py (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 3 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
« no previous file with comments | « build/android/method_count.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 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 struct
20 import sys 20 import sys
21 import tempfile 21 import tempfile
22 import zipfile 22 import zipfile
23 import zlib 23 import zlib
24 24
25 import devil_chromium 25 import devil_chromium
26 from devil.utils import cmd_helper 26 from devil.utils import cmd_helper
27 import method_count
28 from pylib import constants 27 from pylib import constants
29 from pylib.constants import host_paths 28 from pylib.constants import host_paths
30 29
31 _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')
32 31
33 # Prepend the grit module from the source tree so it takes precedence over other 32 # Prepend the grit module from the source tree so it takes precedence over other
34 # grit versions that might present in the search path. 33 # grit versions that might present in the search path.
35 with host_paths.SysPath(_GRIT_PATH, 1): 34 with host_paths.SysPath(_GRIT_PATH, 1):
36 from grit.format import data_pack # pylint: disable=import-error 35 from grit.format import data_pack # pylint: disable=import-error
37 36
38 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH): 37 with host_paths.SysPath(host_paths.BUILD_COMMON_PATH):
39 import perf_tests_results_helper # pylint: disable=import-error 38 import perf_tests_results_helper # pylint: disable=import-error
40 39
41
42 # Python had a bug in zipinfo parsing that triggers on ChromeModern.apk 40 # Python had a bug in zipinfo parsing that triggers on ChromeModern.apk
43 # https://bugs.python.org/issue14315 41 # https://bugs.python.org/issue14315
44 def _PatchedDecodeExtra(self): 42 def _PatchedDecodeExtra(self):
45 # Try to decode the extra field. 43 # Try to decode the extra field.
46 extra = self.extra 44 extra = self.extra
47 unpack = struct.unpack 45 unpack = struct.unpack
48 while len(extra) >= 4: 46 while len(extra) >= 4:
49 tp, ln = unpack('<HH', extra[:4]) 47 tp, ln = unpack('<HH', extra[:4])
50 if tp == 1: 48 if tp == 1:
51 if ln >= 24: 49 if ln >= 24:
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 if m: 347 if m:
350 i = int(m.group('id')) 348 i = int(m.group('id'))
351 name = m.group('name') 349 name = m.group('name')
352 if i in id_name_map and name != id_name_map[i]: 350 if i in id_name_map and name != id_name_map[i]:
353 print 'WARNING: Resource ID conflict %s (%s vs %s)' % ( 351 print 'WARNING: Resource ID conflict %s (%s vs %s)' % (
354 i, id_name_map[i], name) 352 i, id_name_map[i], name)
355 id_name_map[i] = name 353 id_name_map[i] = name
356 return id_name_map 354 return id_name_map
357 355
358 356
359 def _PrintStaticInitializersCountFromApk(apk_filename, chartjson=None): 357 def PrintStaticInitializersCount(so_with_symbols_path, chartjson=None):
360 print 'Finding static initializers (can take a minute)' 358 """Emits the performance result for static initializers found in the provided
361 with zipfile.ZipFile(apk_filename) as z: 359 shared library. Additionally, files for which static initializers were
362 infolist = z.infolist() 360 found are printed on the standard output.
363 out_dir = constants.GetOutDirectory()
364 si_count = 0
365 for zip_info in infolist:
366 # Check file size to account for placeholder libraries.
367 if zip_info.filename.endswith('.so') and zip_info.file_size > 0:
368 unstripped_path = os.path.join(out_dir, 'lib.unstripped',
369 os.path.basename(zip_info.filename))
370 if os.path.exists(unstripped_path):
371 si_count += _PrintStaticInitializersCount(unstripped_path)
372 else:
373 raise Exception('Unstripped .so not found. Looked here: %s',
374 unstripped_path)
375 ReportPerfResult(chartjson, 'StaticInitializersCount', 'count', si_count,
376 'count')
377
378
379 def _PrintStaticInitializersCount(so_with_symbols_path):
380 """Counts the number of static initializers in the given shared library.
381 Additionally, files for which static initializers were found are printed
382 on the standard output.
383 361
384 Args: 362 Args:
385 so_with_symbols_path: Path to the unstripped libchrome.so file. 363 so_with_symbols_path: Path to the unstripped libchrome.so file.
386
387 Returns:
388 The number of static initializers found.
389 """ 364 """
390 # GetStaticInitializers uses get-static-initializers.py to get a list of all 365 # GetStaticInitializers uses get-static-initializers.py to get a list of all
391 # static initializers. This does not work on all archs (particularly arm). 366 # static initializers. This does not work on all archs (particularly arm).
392 # TODO(rnephew): Get rid of warning when crbug.com/585588 is fixed. 367 # TODO(rnephew): Get rid of warning when crbug.com/585588 is fixed.
393 si_count = CountStaticInitializers(so_with_symbols_path) 368 si_count = CountStaticInitializers(so_with_symbols_path)
394 static_initializers = GetStaticInitializers(so_with_symbols_path) 369 static_initializers = GetStaticInitializers(so_with_symbols_path)
395 static_initializers_count = len(static_initializers) - 1 # Minus summary. 370 if si_count != len(static_initializers):
396 if si_count != static_initializers_count:
397 print ('There are %d files with static initializers, but ' 371 print ('There are %d files with static initializers, but '
398 'dump-static-initializers found %d:' % 372 'dump-static-initializers found %d:' %
399 (si_count, static_initializers_count)) 373 (si_count, len(static_initializers)))
400 else: 374 else:
401 print '%s - Found %d files with static initializers:' % ( 375 print 'Found %d files with static initializers:' % si_count
402 os.path.basename(so_with_symbols_path), si_count)
403 print '\n'.join(static_initializers) 376 print '\n'.join(static_initializers)
404 377
405 return si_count 378 ReportPerfResult(chartjson, 'StaticInitializersCount', 'count',
379 si_count, 'count')
406 380
407 def _FormatBytes(byts): 381 def _FormatBytes(byts):
408 """Pretty-print a number of bytes.""" 382 """Pretty-print a number of bytes."""
409 if byts > 2**20.0: 383 if byts > 2**20.0:
410 byts /= 2**20.0 384 byts /= 2**20.0
411 return '%.2fm' % byts 385 return '%.2fm' % byts
412 if byts > 2**10.0: 386 if byts > 2**10.0:
413 byts /= 2**10.0 387 byts /= 2**10.0
414 return '%.2fk' % byts 388 return '%.2fk' % byts
415 return str(byts) 389 return str(byts)
416 390
417 391
418 def _CalculateCompressedSize(file_path): 392 def _CalculateCompressedSize(file_path):
419 CHUNK_SIZE = 256 * 1024 393 CHUNK_SIZE = 256 * 1024
420 compressor = zlib.compressobj() 394 compressor = zlib.compressobj()
421 total_size = 0 395 total_size = 0
422 with open(file_path, 'rb') as f: 396 with open(file_path, 'rb') as f:
423 for chunk in iter(lambda: f.read(CHUNK_SIZE), ''): 397 for chunk in iter(lambda: f.read(CHUNK_SIZE), ''):
424 total_size += len(compressor.compress(chunk)) 398 total_size += len(compressor.compress(chunk))
425 total_size += len(compressor.flush()) 399 total_size += len(compressor.flush())
426 return total_size 400 return total_size
427 401
428 402
429 def _PrintDexAnalysis(apk_filename, chartjson=None):
430 sizes = method_count.ExtractSizesFromZip(apk_filename)
431
432 graph_title = os.path.basename(apk_filename) + '_Dex'
433 dex_metrics = method_count.CONTRIBUTORS_TO_DEX_CACHE
434 for key, label in dex_metrics.iteritems():
435 ReportPerfResult(chartjson, graph_title, label, sizes[key], 'entries')
436
437 graph_title = '%sCache' % graph_title
438 ReportPerfResult(chartjson, graph_title, 'DexCache', sizes['dex_cache_size'],
439 'bytes')
440
441
442 def main(argv): 403 def main(argv):
443 usage = """Usage: %prog [options] file1 file2 ... 404 usage = """Usage: %prog [options] file1 file2 ...
444 405
445 Pass any number of files to graph their sizes. Any files with the extension 406 Pass any number of files to graph their sizes. Any files with the extension
446 '.apk' will be broken down into their components on a separate graph.""" 407 '.apk' will be broken down into their components on a separate graph."""
447 option_parser = optparse.OptionParser(usage=usage) 408 option_parser = optparse.OptionParser(usage=usage)
448 option_parser.add_option('--so-path', 409 option_parser.add_option('--so-path', help='Path to libchrome.so.')
449 help='Obsolete. Pass .so as positional arg instead.')
450 option_parser.add_option('--so-with-symbols-path', 410 option_parser.add_option('--so-with-symbols-path',
451 help='Mostly obsolete. Use .so within .apk instead.') 411 help='Path to libchrome.so with symbols.')
452 option_parser.add_option('--min-pak-resource-size', type='int', 412 option_parser.add_option('--min-pak-resource-size', type='int',
453 default=20*1024, 413 default=20*1024,
454 help='Minimum byte size of displayed pak resources.') 414 help='Minimum byte size of displayed pak resources.')
455 option_parser.add_option('--build_type', dest='build_type', default='Debug', 415 option_parser.add_option('--build_type', dest='build_type', default='Debug',
456 help='Obsoleted by --chromium-output-directory.') 416 help='Sets the build type, default is Debug.')
457 option_parser.add_option('--chromium-output-directory', 417 option_parser.add_option('--chromium-output-directory',
458 help='Location of the build artifacts. ' 418 help='Location of the build artifacts. '
459 'Takes precidence over --build_type.') 419 'Takes precidence over --build_type.')
460 option_parser.add_option('--chartjson', action="store_true", 420 option_parser.add_option('--chartjson', action="store_true",
461 help='Sets output mode to chartjson.') 421 help='Sets output mode to chartjson.')
462 option_parser.add_option('--output-dir', default='.', 422 option_parser.add_option('--output-dir', default='.',
463 help='Directory to save chartjson to.') 423 help='Directory to save chartjson to.')
464 option_parser.add_option('-d', '--device', 424 option_parser.add_option('-d', '--device',
465 help='Dummy option for perf runner.') 425 help='Dummy option for perf runner.')
466 options, args = option_parser.parse_args(argv) 426 options, args = option_parser.parse_args(argv)
(...skipping 10 matching lines...) Expand all
477 # more. 437 # more.
478 if options.so_path: 438 if options.so_path:
479 files.append(options.so_path) 439 files.append(options.so_path)
480 440
481 if not files: 441 if not files:
482 option_parser.error('Must specify a file') 442 option_parser.error('Must specify a file')
483 443
484 devil_chromium.Initialize() 444 devil_chromium.Initialize()
485 445
486 if options.so_with_symbols_path: 446 if options.so_with_symbols_path:
487 si_count = _PrintStaticInitializersCount(options.so_with_symbols_path) 447 PrintStaticInitializersCount(
488 ReportPerfResult(chartjson, 'StaticInitializersCount', 'count', si_count, 448 options.so_with_symbols_path, chartjson=chartjson)
489 'count')
490 449
491 PrintResourceSizes(files, chartjson=chartjson) 450 PrintResourceSizes(files, chartjson=chartjson)
492 451
493 for f in files: 452 for f in files:
494 if f.endswith('.apk'): 453 if f.endswith('.apk'):
495 PrintApkAnalysis(f, chartjson=chartjson) 454 PrintApkAnalysis(f, chartjson=chartjson)
496 PrintPakAnalysis(f, options.min_pak_resource_size) 455 PrintPakAnalysis(f, options.min_pak_resource_size)
497 _PrintDexAnalysis(f, chartjson=chartjson)
498 if not options.so_with_symbols_path:
499 _PrintStaticInitializersCountFromApk(f, chartjson=chartjson)
500 456
501 if chartjson: 457 if chartjson:
502 results_path = os.path.join(options.output_dir, 'results-chart.json') 458 results_path = os.path.join(options.output_dir, 'results-chart.json')
503 logging.critical('Dumping json to %s', results_path) 459 logging.critical('Dumping json to %s', results_path)
504 with open(results_path, 'w') as json_file: 460 with open(results_path, 'w') as json_file:
505 json.dump(chartjson, json_file) 461 json.dump(chartjson, json_file)
506 462
507 463
508 if __name__ == '__main__': 464 if __name__ == '__main__':
509 sys.exit(main(sys.argv)) 465 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « build/android/method_count.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698