#! /usr/bin/env python # Copyright 2015 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import argparse import os import re import sys import zipfile from pylib.constants import host_paths from pylib.dex import dex_parser sys.path.append(os.path.join(host_paths.DIR_SOURCE_ROOT, 'build', 'util', 'lib', 'common')) import perf_tests_results_helper # pylint: disable=import-error _CONTRIBUTORS_TO_DEX_CACHE = { 'type_ids_size': 'types', 'string_ids_size': 'strings', 'method_ids_size': 'methods', 'field_ids_size': 'fields' } def _ExtractSizesFromDexFile(dexfile): count_by_item = {} for item_name, readable_name in _CONTRIBUTORS_TO_DEX_CACHE.iteritems(): count_by_item[readable_name] = getattr(dexfile.header, item_name) return count_by_item, sum( count_by_item[x] for x in _CONTRIBUTORS_TO_DEX_CACHE.itervalues()) * 4 def ExtractSizesFromZip(path): dex_counts_by_file = {} dexcache_size = 0 dexfiles = {} with zipfile.ZipFile(path, 'r') as z: for subpath in z.namelist(): if not re.match(r'.*classes[0-9]*\.dex$', subpath): continue dexfile_name = os.path.basename(subpath) dexfiles[dexfile_name] = dex_parser.DexFile(bytearray(z.read(subpath))) for dexfile_name, dexfile in dexfiles.iteritems(): cur_dex_counts, cur_dexcache_size = _ExtractSizesFromDexFile(dexfile) dex_counts_by_file[dexfile_name] = cur_dex_counts dexcache_size += cur_dexcache_size num_unique_methods = dex_parser.CountUniqueDexMethods(dexfiles.values()) return dex_counts_by_file, dexcache_size, num_unique_methods def main(): parser = argparse.ArgumentParser() parser.add_argument('filename') args = parser.parse_args() if os.path.splitext(args.filename)[1] in ('.zip', '.apk', '.jar'): sizes, total_size, num_unique_methods = ExtractSizesFromZip(args.filename) else: with open(args.filename) as f: dexfile = dex_parser.DexFile(bytearray(f.read())) single_set_of_sizes, total_size = _ExtractSizesFromDexFile(dexfile) sizes = {"": single_set_of_sizes} num_unique_methods = single_set_of_sizes['methods'] file_basename = os.path.basename(args.filename) for classes_dex_file, classes_dex_sizes in sizes.iteritems(): for readable_name in _CONTRIBUTORS_TO_DEX_CACHE.itervalues(): if readable_name in classes_dex_sizes: perf_tests_results_helper.PrintPerfResult( '%s_%s_%s' % (file_basename, classes_dex_file, readable_name), 'total', [classes_dex_sizes[readable_name]], readable_name) perf_tests_results_helper.PrintPerfResult('%s_unique_methods' % file_basename, 'total', [num_unique_methods], 'unique methods') perf_tests_results_helper.PrintPerfResult( '%s_DexCache_size' % (file_basename), 'total', [total_size], 'bytes of permanent dirty memory') return 0 if __name__ == '__main__': sys.exit(main())