lin
2025-07-31 065ea569db06206874bbfa18eb25ff6121aec09b
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/python
 
# Script to generate and collect PGO data based on benchmark
from __future__ import print_function
 
import argparse
import config
import logging
import os
import subprocess
import sys
import tempfile
 
# Turn the logging level to INFO before importing other code, to avoid having
# failed import logging messages confuse the user.
logging.basicConfig(level=logging.INFO)
 
def _parse_arguments_internal(argv):
    """
    Parse command line arguments
 
    @param argv: argument list to parse
 
    @returns:    tuple of parsed arguments and argv suitable for remote runs
 
    @raises SystemExit if arguments are malformed, or required arguments
            are not present.
    """
 
    parser = argparse.ArgumentParser(description='Run this script to collect '
                                                 'PGO data.')
 
    parser.add_argument('-b', '--bench',
                        help='Select which benchmark to collect profdata.')
 
    parser.add_argument('-d', '--pathDUT', default='/data/local/tmp',
                        help='Specify where to generate PGO data on device, '
                             'set to /data/local/tmp by default.')
 
    parser.add_argument('-p', '--path', default=config.bench_suite_dir,
                        help='Specify the location to put the profdata, set '
                             ' to bench_suite_dir by default.')
 
    parser.add_argument('-s', '--serial',
                        help='Device serial number.')
 
    parser.add_argument('-r', '--remote', default='localhost',
                        help='hostname[:port] if the ADB device is connected '
                             'to a remote machine. Ensure this workstation '
                             'is configured for passwordless ssh access as '
                             'users "root" or "adb"')
    return parser.parse_args(argv)
 
# Call run.py to build benchmark with -fprofile-generate flags and run on DUT
def run_suite(bench, serial, remote, pathDUT):
    logging.info('Build and run instrumented benchmark...')
    run_cmd = ['./run.py', '-b=' + bench]
    if serial:
        run_cmd.append('-s=' + serial)
    run_cmd.append('-r=' + remote)
    run_cmd.append('-f=-fprofile-generate=%s' % pathDUT)
    run_cmd.append('--ldflags=-fprofile-generate=%s' % pathDUT)
    try:
        subprocess.check_call(run_cmd)
    except subprocess.CalledProcessError:
        logging.error('Error running %s.', run_cmd)
        raise
 
# Pull profraw data from device using pull_device.py script in autotest utils.
def pull_result(bench, serial, remote, pathDUT, path):
    logging.info('Pulling profraw data from device to local')
    pull_cmd = [os.path.join(config.android_home,
                             config.autotest_dir,
                             'site_utils/pull_device.py')]
    pull_cmd.append('-b=' + bench)
    pull_cmd.append('-r=' + remote)
    if serial:
        pull_cmd.append('-s=' + serial)
    pull_cmd.append('-p=' + path)
    pull_cmd.append('-d=' + pathDUT)
    try:
        subprocess.check_call(pull_cmd)
    except:
        logging.error('Error while pulling profraw data.')
        raise
 
# Use llvm-profdata tool to convert profraw data to the format llvm can
# recgonize.
def merge(bench, pathDUT, path):
    logging.info('Generate profdata for PGO...')
    # Untar the compressed rawdata file collected from device
    tmp_dir = tempfile.mkdtemp()
    untar_cmd = ['tar',
                 '-xf',
                 os.path.join(path, bench + '_profraw.tar'),
                 '-C',
                 tmp_dir]
 
    # call llvm-profdata to merge the profraw data
    profdata = os.path.join(path, bench + '.profdata')
    merge_cmd = ['llvm-profdata',
                 'merge',
                 '-output=' + profdata,
                 tmp_dir + pathDUT]
    try:
        subprocess.check_call(untar_cmd)
        subprocess.check_call(merge_cmd)
        logging.info('Profdata is generated successfully, located at %s',
                     profdata)
    except:
        logging.error('Error while merging profraw data.')
        raise
    finally:
        subprocess.check_call(['rm', '-rf', tmp_dir])
 
def main(argv):
    """
    Entry point for nightly_run script.
 
    @param argv: arguments list
    """
    arguments = _parse_arguments_internal(argv)
 
    bench = arguments.bench
    serial = arguments.serial
    path = arguments.path
    remote = arguments.remote
 
    # Create a profraw directory to collect data
    pathDUT = os.path.join(arguments.pathDUT, bench + '_profraw')
 
    run_suite(bench, serial, remote, pathDUT)
 
    pull_result(bench, serial, remote, pathDUT, path)
 
    merge(bench, pathDUT, path)
 
if __name__ == '__main__':
    main(sys.argv[1:])