aboutsummaryrefslogtreecommitdiff
path: root/compilation_stats.py
blob: 34fa3d7c29b17432f42f58e8ff2a280ce67112ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#! /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(target_file_key,
                        compilation_times,
                        section_sizes,
                        output_json_filename):
    output_obj = utils.ReadJSON(output_json_filename)
    output_obj[target_file_key] = dict()

    output_obj[target_file_key].update(compilation_times)
    print("Compilation times (seconds):")
    utils.PrintData(compilation_times)

    output_obj[target_file_key]["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()
        input_filename = args.add_pathname[0]
        # 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.")

        if input_filename != "boot.oat":
            apk_name = utils.TargetPathJoin(args.target_copy_path, input_filename)
            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))

        compile_time_dict = OrderedDict([("Time", compilation_times)])

        # Pull the executable and get its size
        for output_oat in args.output_oat:
            print("Getting size for {}".format(output_oat))
            output_filename = os.path.basename(output_oat)
            local_oat = os.path.join(work_dir, output_filename)
            utils_adb.pull(output_oat, local_oat, args.target)
            section_sizes = utils.GetSectionSizes(local_oat)

            SaveAndPrintResults(output_filename, compile_time_dict, section_sizes, args.output_json)
    finally:
        shutil.rmtree(work_dir)