OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # Copyright 2017 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Merge the PGC files generated during the profiling step to the PGD database. | |
7 | |
8 This is required to workaround a flakyness in pgomgr.exe where it can run out | |
9 of address space while trying to merge all the PGC files at the same time. | |
10 """ | |
11 | |
12 import glob | |
13 import json | |
14 import optparse | |
15 import os | |
16 import subprocess | |
17 import sys | |
18 | |
19 | |
20 def find_pgomgr(chrome_checkout_dir, target_cpu): | |
21 """Find pgomgr.exe.""" | |
22 if target_cpu not in ('x86', 'x64'): | |
23 raise Exception('target_cpu should be x86 or x64.') | |
24 | |
25 win_toolchain_json_file = os.path.join(chrome_checkout_dir, 'build', | |
26 'win_toolchain.json') | |
27 if not os.path.exists(win_toolchain_json_file): | |
28 raise Exception('The toolchain JSON file is missing.') | |
29 with open(win_toolchain_json_file) as temp_f: | |
30 toolchain_data = json.load(temp_f) | |
31 if not os.path.isdir(toolchain_data['path']): | |
32 raise Exception('The toolchain JSON file is invalid.') | |
33 | |
34 pgomgr_dir = os.path.join(toolchain_data['path'], 'VC', 'bin') | |
35 if target_cpu == 'x64': | |
36 pgomgr_dir = os.path.join(pgomgr_dir, 'amd64') | |
37 | |
38 pgomgr_path = os.path.join(pgomgr_dir, 'pgomgr.exe') | |
39 if not os.path.exists(pgomgr_path): | |
40 raise Exception('pgomgr.exe is missing from %s.' % pgomgr_dir) | |
41 | |
42 return pgomgr_path | |
43 | |
44 | |
45 def main(): | |
46 parser = optparse.OptionParser(usage='%prog [options]') | |
47 parser.add_option('--checkout-dir', help='The Chrome checkout directory.') | |
48 parser.add_option('--target-cpu', help='The target\'s bitness.') | |
49 parser.add_option('--build-dir', help='Chrome build directory.') | |
50 parser.add_option('--binary-name', help='The binary for which the PGC files ' | |
51 'should be merged, without extension.') | |
52 options, _ = parser.parse_args() | |
53 | |
54 if not options.checkout_dir: | |
55 parser.error('--checkout-dir is required') | |
56 if not options.target_cpu: | |
57 parser.error('--target-cpu is required') | |
58 if not options.build_dir: | |
59 parser.error('--build-dir is required') | |
60 if not options.binary_name: | |
61 parser.error('--binary-name is required') | |
62 | |
63 # Starts by finding pgomgr.exe. | |
64 pgomgr_path = find_pgomgr(options.checkout_dir, options.target_cpu) | |
65 | |
66 pgc_files = glob.glob(os.path.join(options.build_dir, | |
67 '%s*.pgc' % options.binary_name)) | |
68 | |
69 # Number of PGC files that should be merged in each iterations, merging all | |
70 # the files one by one is really slow but merging more to 10 at a time doesn't | |
71 # really seem to impact the total time. | |
72 # | |
73 # Number of pgc merged per iteration | Time (in min) | |
74 # 1 | 27.2 | |
75 # 10 | 12.8 | |
76 # 20 | 12.0 | |
77 # 30 | 11.5 | |
78 # 40 | 11.4 | |
79 # 50 | 11.5 | |
80 # 60 | 11.6 | |
81 # 70 | 11.6 | |
82 # 80 | 11.7 | |
83 # | |
84 # TODO(sebmarchand): Measure the memory usage of pgomgr.exe to see how it get | |
85 # affected by the number of pgc files. | |
86 pgc_per_iter = 20 | |
87 iterations = int(len(pgc_files) / pgc_per_iter) + ( | |
scottmg
2017/02/04 02:44:09
This makes my head hurt. :) How about http://stack
Sébastien Marchand
2017/02/06 16:48:37
Done, it's much cleaner! Should I link to this pos
| |
88 1 if (len(pgc_files) % pgc_per_iter) != 0 else 0) | |
89 for i in xrange(0, iterations): | |
90 merge_command = [ | |
91 pgomgr_path, | |
92 '/merge' | |
93 ] | |
94 for j in xrange(i * pgc_per_iter, | |
95 min((i + 1) * pgc_per_iter, len(pgc_files))): | |
96 merge_command.append([ | |
97 os.path.join(options.build_dir, pgc_files[j]) | |
98 ]) | |
99 | |
100 merge_command.append([ | |
101 os.path.join(options.build_dir, '%s.pgd' % options.binary_name) | |
102 ]) | |
103 proc = subprocess.Popen(merge_command, stdout=subprocess.PIPE) | |
104 stdout, _ = proc.communicate() | |
105 if proc.returncode != 0: | |
106 raise Exception('Error while trying to merge the PGC files:\n%s' % stdout) | |
107 | |
108 | |
109 if __name__ == '__main__': | |
110 sys.exit(main()) | |
OLD | NEW |