• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/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:])
140