xref: /aosp_15_r20/tools/asuite/atest/profiler.py (revision c2e18aaa1096c836b086f94603d04f4eb9cf37f5)
1*c2e18aaaSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2022, The Android Open Source Project
3*c2e18aaaSAndroid Build Coastguard Worker#
4*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
5*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
6*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at
7*c2e18aaaSAndroid Build Coastguard Worker#
8*c2e18aaaSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
9*c2e18aaaSAndroid Build Coastguard Worker#
10*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
11*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
12*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
14*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License.
15*c2e18aaaSAndroid Build Coastguard Worker
16*c2e18aaaSAndroid Build Coastguard Worker"""Script of Atest Profiler."""
17*c2e18aaaSAndroid Build Coastguard Worker
18*c2e18aaaSAndroid Build Coastguard Workerimport argparse
19*c2e18aaaSAndroid Build Coastguard Workerimport os
20*c2e18aaaSAndroid Build Coastguard Workerimport shutil
21*c2e18aaaSAndroid Build Coastguard Workerimport subprocess
22*c2e18aaaSAndroid Build Coastguard Workerimport sys
23*c2e18aaaSAndroid Build Coastguard Workerimport tempfile
24*c2e18aaaSAndroid Build Coastguard Workerimport zipfile
25*c2e18aaaSAndroid Build Coastguard Worker
26*c2e18aaaSAndroid Build Coastguard Worker# This is mostly a copy of Soong's stub_template_host.txt, but with changes to
27*c2e18aaaSAndroid Build Coastguard Worker# run soong python executables via a profiler tool. This is just a hack, soong
28*c2e18aaaSAndroid Build Coastguard Worker# should really have the ability to build profiled binaries directly.
29*c2e18aaaSAndroid Build Coastguard Worker
30*c2e18aaaSAndroid Build Coastguard Worker
31*c2e18aaaSAndroid Build Coastguard Workerdef main():
32*c2e18aaaSAndroid Build Coastguard Worker  """Main method that runs python profilers."""
33*c2e18aaaSAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(
34*c2e18aaaSAndroid Build Coastguard Worker      description='Runs a soong-built python binary under a profiler.'
35*c2e18aaaSAndroid Build Coastguard Worker  )
36*c2e18aaaSAndroid Build Coastguard Worker  parser.add_argument(
37*c2e18aaaSAndroid Build Coastguard Worker      'profiler',
38*c2e18aaaSAndroid Build Coastguard Worker      choices=['pyinstrument', 'cProfile'],
39*c2e18aaaSAndroid Build Coastguard Worker      help='The profiler to use',
40*c2e18aaaSAndroid Build Coastguard Worker  )
41*c2e18aaaSAndroid Build Coastguard Worker  parser.add_argument('profile_file', help='The output file of the profiler')
42*c2e18aaaSAndroid Build Coastguard Worker  parser.add_argument(
43*c2e18aaaSAndroid Build Coastguard Worker      'executable',
44*c2e18aaaSAndroid Build Coastguard Worker      help='The soong-built python binary (with embedded_launcher: false)',
45*c2e18aaaSAndroid Build Coastguard Worker  )
46*c2e18aaaSAndroid Build Coastguard Worker  args, args_for_executable = parser.parse_known_args()
47*c2e18aaaSAndroid Build Coastguard Worker
48*c2e18aaaSAndroid Build Coastguard Worker  if not os.path.isfile(args.executable):
49*c2e18aaaSAndroid Build Coastguard Worker    sys.exit(f'{args.executable}: File not found')
50*c2e18aaaSAndroid Build Coastguard Worker  os.makedirs(os.path.dirname(args.profile_file), exist_ok=True)
51*c2e18aaaSAndroid Build Coastguard Worker
52*c2e18aaaSAndroid Build Coastguard Worker  runfiles_path = tempfile.mkdtemp(prefix='Soong.python_')
53*c2e18aaaSAndroid Build Coastguard Worker  try:
54*c2e18aaaSAndroid Build Coastguard Worker    _zf = zipfile.ZipFile(args.executable)
55*c2e18aaaSAndroid Build Coastguard Worker    _zf.extractall(runfiles_path)
56*c2e18aaaSAndroid Build Coastguard Worker    _zf.close()
57*c2e18aaaSAndroid Build Coastguard Worker
58*c2e18aaaSAndroid Build Coastguard Worker    sys.exit(
59*c2e18aaaSAndroid Build Coastguard Worker        subprocess.call(
60*c2e18aaaSAndroid Build Coastguard Worker            [
61*c2e18aaaSAndroid Build Coastguard Worker                'python3',
62*c2e18aaaSAndroid Build Coastguard Worker                '-m',
63*c2e18aaaSAndroid Build Coastguard Worker                args.profiler,
64*c2e18aaaSAndroid Build Coastguard Worker                '-o',
65*c2e18aaaSAndroid Build Coastguard Worker                args.profile_file,
66*c2e18aaaSAndroid Build Coastguard Worker                os.path.join(
67*c2e18aaaSAndroid Build Coastguard Worker                    runfiles_path, '__soong_entrypoint_redirector__.py'
68*c2e18aaaSAndroid Build Coastguard Worker                ),
69*c2e18aaaSAndroid Build Coastguard Worker            ]
70*c2e18aaaSAndroid Build Coastguard Worker            + args_for_executable,
71*c2e18aaaSAndroid Build Coastguard Worker            close_fds=False,
72*c2e18aaaSAndroid Build Coastguard Worker        )
73*c2e18aaaSAndroid Build Coastguard Worker    )
74*c2e18aaaSAndroid Build Coastguard Worker
75*c2e18aaaSAndroid Build Coastguard Worker  finally:
76*c2e18aaaSAndroid Build Coastguard Worker    shutil.rmtree(runfiles_path, ignore_errors=True)
77*c2e18aaaSAndroid Build Coastguard Worker
78*c2e18aaaSAndroid Build Coastguard Worker
79*c2e18aaaSAndroid Build Coastguard Workerif __name__ == '__main__':
80*c2e18aaaSAndroid Build Coastguard Worker  main()
81