blob: 27d5e5d6d3e221b64544a7659d97bedcae57bcfd [file] [log] [blame]
Zhizhou Yang726ded52017-08-23 22:47:50 -07001#!/usr/bin/python
2
3# Script to generate and collect PGO data based on benchmark
4from __future__ import print_function
5
6import argparse
7import config
8import logging
9import os
10import subprocess
11import sys
12import tempfile
13
14# Turn the logging level to INFO before importing other code, to avoid having
15# failed import logging messages confuse the user.
16logging.basicConfig(level=logging.INFO)
17
18def _parse_arguments_internal(argv):
19 """
20 Parse command line arguments
21
22 @param argv: argument list to parse
23
24 @returns: tuple of parsed arguments and argv suitable for remote runs
25
26 @raises SystemExit if arguments are malformed, or required arguments
27 are not present.
28 """
29
30 parser = argparse.ArgumentParser(description='Run this script to collect '
31 'PGO data.')
32
33 parser.add_argument('-b', '--bench',
34 help='Select which benchmark to collect profdata.')
35
36 parser.add_argument('-d', '--pathDUT', default='/data/local/tmp',
37 help='Specify where to generate PGO data on device, '
38 'set to /data/local/tmp by default.')
39
40 parser.add_argument('-p', '--path', default=config.bench_suite_dir,
41 help='Specify the location to put the profdata, set '
42 ' to bench_suite_dir by default.')
43
44 parser.add_argument('-s', '--serial',
45 help='Device serial number.')
46
47 parser.add_argument('-r', '--remote', default='localhost',
48 help='hostname[:port] if the ADB device is connected '
49 'to a remote machine. Ensure this workstation '
50 'is configured for passwordless ssh access as '
51 'users "root" or "adb"')
52 return parser.parse_args(argv)
53
54# Call run.py to build benchmark with -fprofile-generate flags and run on DUT
55def run_suite(bench, serial, remote, pathDUT):
56 logging.info('Build and run instrumented benchmark...')
57 run_cmd = ['./run.py', '-b=' + bench]
58 if serial:
59 run_cmd.append('-s=' + serial)
60 run_cmd.append('-r=' + remote)
61 run_cmd.append('-f=-fprofile-generate=%s' % pathDUT)
62 run_cmd.append('--ldflags=-fprofile-generate=%s' % pathDUT)
63 try:
64 subprocess.check_call(run_cmd)
65 except subprocess.CalledProcessError:
66 logging.error('Error running %s.', run_cmd)
67 raise
68
69# Pull profraw data from device using pull_device.py script in autotest utils.
70def pull_result(bench, serial, remote, pathDUT, path):
71 logging.info('Pulling profraw data from device to local')
72 pull_cmd = [os.path.join(config.android_home,
73 config.autotest_dir,
74 'site_utils/pull_device.py')]
75 pull_cmd.append('-b=' + bench)
76 pull_cmd.append('-r=' + remote)
77 if serial:
78 pull_cmd.append('-s=' + serial)
79 pull_cmd.append('-p=' + path)
80 pull_cmd.append('-d=' + pathDUT)
81 try:
82 subprocess.check_call(pull_cmd)
83 except:
84 logging.error('Error while pulling profraw data.')
85 raise
86
87# Use llvm-profdata tool to convert profraw data to the format llvm can
88# recgonize.
89def merge(bench, pathDUT, path):
90 logging.info('Generate profdata for PGO...')
91 # Untar the compressed rawdata file collected from device
92 tmp_dir = tempfile.mkdtemp()
93 untar_cmd = ['tar',
94 '-xf',
95 os.path.join(path, bench + '_profraw.tar'),
96 '-C',
97 tmp_dir]
98
99 # call llvm-profdata to merge the profraw data
100 profdata = os.path.join(path, bench + '.profdata')
101 merge_cmd = ['llvm-profdata',
102 'merge',
103 '-output=' + profdata,
104 tmp_dir + pathDUT]
105 try:
106 subprocess.check_call(untar_cmd)
107 subprocess.check_call(merge_cmd)
108 logging.info('Profdata is generated successfully, located at %s',
109 profdata)
110 except:
111 logging.error('Error while merging profraw data.')
112 raise
113 finally:
114 subprocess.check_call(['rm', '-rf', tmp_dir])
115
116def main(argv):
117 """
118 Entry point for nightly_run script.
119
120 @param argv: arguments list
121 """
122 arguments = _parse_arguments_internal(argv)
123
124 bench = arguments.bench
125 serial = arguments.serial
126 path = arguments.path
127 remote = arguments.remote
128
129 # Create a profraw directory to collect data
130 pathDUT = os.path.join(arguments.pathDUT, bench + '_profraw')
131
132 run_suite(bench, serial, remote, pathDUT)
133
134 pull_result(bench, serial, remote, pathDUT, path)
135
136 merge(bench, pathDUT, path)
137
138if __name__ == '__main__':
139 main(sys.argv[1:])