Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/tools/emprofile.py
4128 views
1
#!/usr/bin/env python3
2
# Copyright 2016 The Emscripten Authors. All rights reserved.
3
# Emscripten is available under two separate licenses, the MIT license and the
4
# University of Illinois/NCSA Open Source License. Both these licenses can be
5
# found in the LICENSE file.
6
7
import json
8
import os
9
import shutil
10
import sys
11
import tempfile
12
import time
13
from pathlib import Path
14
15
16
profiler_logs_path = os.path.join(tempfile.gettempdir(), 'emscripten_toolchain_profiler_logs')
17
18
19
# Deletes all previously captured log files to make room for a new clean run.
20
def delete_profiler_logs():
21
if os.path.exists(profiler_logs_path):
22
shutil.rmtree(profiler_logs_path)
23
24
25
def list_files_in_directory(d):
26
files = []
27
if os.path.exists(d):
28
for i in os.listdir(d):
29
f = os.path.join(d, i)
30
if os.path.isfile(f):
31
files.append(f)
32
return files
33
34
35
def create_profiling_graph(outfile):
36
log_files = [f for f in list_files_in_directory(profiler_logs_path) if 'toolchain_profiler.pid_' in f]
37
38
all_results = []
39
if log_files:
40
print(f'Processing {len(log_files)} profile log files in {profiler_logs_path}...')
41
for f in log_files:
42
print(f'Processing: {f}')
43
json_data = Path(f).read_text()
44
if len(json_data.strip()) == 0:
45
continue
46
lines = json_data.split('\n')
47
lines = [x for x in lines if x not in {'[', ']', ','} and len(x.strip())]
48
lines = [(x + ',') if not x.endswith(',') else x for x in lines]
49
lines[-1] = lines[-1][:-1]
50
json_data = '[' + '\n'.join(lines) + ']'
51
try:
52
all_results += json.loads(json_data)
53
except json.JSONDecodeError as e:
54
print(str(e), file=sys.stderr)
55
print('Failed to parse JSON file "' + f + '"!', file=sys.stderr)
56
return 1
57
if len(all_results) == 0:
58
print(f'No profiler logs were found in path: ${profiler_logs_path}.\nTry setting the environment variable EMPROFILE=1 and run some emcc commands, then re-run "emprofile.py --graph".', file=sys.stderr)
59
return 1
60
61
all_results.sort(key=lambda x: x['time'])
62
63
emprofile_json_data = json.dumps(all_results, indent=2)
64
65
html_file = outfile + '.html'
66
html_contents = Path(os.path.dirname(os.path.realpath(__file__)), 'toolchain_profiler.results_template.html').read_text().replace('{{{ emprofile_json_data }}}', emprofile_json_data)
67
Path(html_file).write_text(html_contents)
68
print(f'Wrote "{html_file}"')
69
return 0
70
71
72
def main(args):
73
if '--help' in args:
74
print('''\
75
Usage:
76
emprofile.py --clear (or -c)
77
Deletes all previously recorded profiling log files.
78
Use this to abort/drop any previously collected
79
profiling data for a new profiling run.
80
81
emprofile.py [--no-clear]
82
Draws a graph from all recorded profiling log files,
83
and deletes the recorded profiling files, unless
84
--no-clear is also passed.
85
86
Optional parameters:
87
88
--outfile=x.html (or -o=x.html)
89
Specifies the name of the results file to generate.
90
''')
91
return 0
92
93
if '--reset' in args or '--clear' in args or '-c' in args:
94
delete_profiler_logs()
95
return 0
96
else:
97
outfile = 'toolchain_profiler.results_' + time.strftime('%Y%m%d_%H%M')
98
for i, arg in enumerate(args):
99
if arg.startswith(('--outfile=', '-o=')):
100
outfile = arg.split('=', 1)[1].strip().replace('.html', '')
101
elif arg == '-o':
102
outfile = args[i + 1].strip().replace('.html', '')
103
if create_profiling_graph(outfile):
104
return 1
105
if '--no-clear' not in args:
106
delete_profiler_logs()
107
108
return 0
109
110
111
if __name__ == '__main__':
112
sys.exit(main(sys.argv[1:]))
113
114