diff options
Diffstat (limited to 'compilation_stats.py')
-rwxr-xr-x | compilation_stats.py | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/compilation_stats.py b/compilation_stats.py new file mode 100755 index 0000000..78dea5f --- /dev/null +++ b/compilation_stats.py @@ -0,0 +1,101 @@ +#! /usr/bin/env python3 + +# Copyright (C) 2021 Linaro Limited. All rights received. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import os +import sys +import json +import tempfile +import shutil + +from collections import OrderedDict + +dir_benchs = os.path.dirname(os.path.realpath(__file__)) +dir_tools = os.path.join(dir_benchs, '..') +sys.path.insert(0, dir_tools) + +from tools import utils, utils_adb, utils_print, utils_stats + +def BuildOptions(): + parser = argparse.ArgumentParser( + description = "Collect compilation statistics.", + # Print default values. + formatter_class = argparse.ArgumentDefaultsHelpFormatter) + utils.AddCommonRunOptions(parser) + utils.AddOutputFormatOptions(parser, utils.default_output_formats) + args = parser.parse_args() + return args + +def SaveAndPrintResults(apk, + compilation_times, + section_sizes, + output_json_filename): + output_obj = utils.ReadJSON(output_json_filename) + + apk_basename = os.path.basename(apk) + output_obj[apk_basename] = dict() + + output_obj[apk_basename].update(compilation_times) + print("Compilation times (seconds):") + utils.PrintData(compilation_times) + + output_obj[apk_basename]["Executable size"] = section_sizes + print("Executable sizes (bytes):") + utils.PrintData(section_sizes) + + with open(output_json_filename, "w") as fp: + json.dump(output_obj, fp, indent=2) + +if __name__ == "__main__": + # create temp directory to pull executables from the device + # to measure their size + work_dir = tempfile.mkdtemp() + try: + args = BuildOptions() + apk = args.add_pathname[0] + apk_name = utils.TargetPathJoin(args.target_copy_path, apk) + # command is used to call a shell script using chroot + # this script calls dex2oat on a given APK and prints + # before/after timestamps + # after command is executed we pull the executable from the device + # and measure its size + if 'ART_COMMAND' in os.environ: + command = os.getenv('ART_COMMAND') + else: + utils.Error("ART_COMMAND is not set.") + format_data = {'workdir': os.path.dirname(apk_name)} + command = command.format(**format_data) + + compilation_times = [] + for i in range(args.iterations): + print("Compiling APK") + results = utils_adb.shell(command, args.target, exit_on_error=False) + lines = results[1] + compilation_time = utils.ExtractCompilationTimeFromOutput(lines) + compilation_times += [compilation_time] + print("Compilation took {:.2f}s\n".format(compilation_time)) + + # Pull the executable and get its size + local_oat = os.path.join(work_dir, apk + '.oat') + utils_adb.pull(args.output_oat, local_oat, args.target) + section_sizes = utils.GetSectionSizes(local_oat) + + compile_time_dict = OrderedDict([("Time", compilation_times)]) + SaveAndPrintResults(apk, compile_time_dict, section_sizes, args.output_json) + + finally: + shutil.rmtree(work_dir) + |