#!/usr/bin/env python # -*- coding: utf-8 -*- # ===--- bench_code_size -------------------------------------------------===// # # This source file is part of the Swift.org open source project # # Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors # Licensed under Apache License v2.0 with Runtime Library Exception # # See https://swift.org/LICENSE.txt for license information # See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors # # ===---------------------------------------------------------------------===// # # Reports code size differences of two benchmark build directories # # ===---------------------------------------------------------------------===// from __future__ import print_function import argparse import glob import os import subprocess import sys def main(): argparser = argparse.ArgumentParser() argparser.add_argument( '-O', action='append_const', const='O', dest='opt_levels', help='report code size of -O benchmarks') argparser.add_argument( '-Osize', action='append_const', const='Osize', dest='opt_levels', help='report code size of -Osize benchmarks') argparser.add_argument( '-Onone', action='append_const', const='Onone', dest='opt_levels', help='report code size of -Onone benchmarks') argparser.add_argument( '-swiftlibs', action='append_const', const='swiftlibs', dest='opt_levels', help='report code size of swift dylibs') argparser.add_argument( 'oldbuilddir', nargs=1, type=str, help='old benchmark build directory') argparser.add_argument( 'newbuilddir', nargs=1, type=str, help='new benchmark build directory') argparser.add_argument( '-platform', type=str, help='The benchmark build platform', default='macosx') args = argparser.parse_args() for opt_level in args.opt_levels or ['O', 'Osize', 'Onone']: report_code_size(opt_level, args.oldbuilddir[0], args.newbuilddir[0], args.platform) return 0 def report_code_size(opt_level, old_dir, new_dir, platform): def log_filename(bench_dir): return os.path.join(bench_dir, 'result_' + opt_level + '_size') old_logf = open(log_filename(old_dir), 'w') new_logf = open(log_filename(new_dir), 'w') if opt_level == 'swiftlibs': files = glob.glob(os.path.join(old_dir, 'lib', 'swift', platform, '*.dylib')) else: files = glob.glob(os.path.join(old_dir, opt_level + '-*' + platform + '*', '*.o')) idx = 1 for oldfile in files: newfile = oldfile.replace(old_dir, new_dir, 1) if os.path.isfile(newfile): oldsize = get_codesize(oldfile) newsize = get_codesize(newfile) bname = os.path.basename(oldfile) def write_line(value, logf): v = ',' + str(value) logf.write(str(idx) + ',' + bname + ',1' + (v * 3) + ',0' + v + '\n') write_line(oldsize, old_logf) write_line(newsize, new_logf) idx += 1 old_logf.close() new_logf.close() print('Logfiles written to ' + log_filename(old_dir) + ' and ' + log_filename(new_dir)) def get_codesize(filename): output = subprocess.check_output(['size', filename]).splitlines() header_line = output[0] data_line = output[1] if header_line.find('__TEXT') != 0: sys.exit('unexpected output from size command:\n' + output) return int(data_line.split('\t')[0]) if __name__ == '__main__': sys.exit(main())