File: emprofile.py

package info (click to toggle)
emscripten 3.1.6~dfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 114,112 kB
  • sloc: ansic: 583,052; cpp: 391,943; javascript: 79,361; python: 54,180; sh: 49,997; pascal: 4,658; makefile: 3,426; asm: 2,191; lisp: 1,869; ruby: 488; cs: 142
file content (112 lines) | stat: -rwxr-xr-x 3,622 bytes parent folder | download | duplicates (3)
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
#!/usr/bin/env python3
# Copyright 2016 The Emscripten Authors.  All rights reserved.
# Emscripten is available under two separate licenses, the MIT license and the
# University of Illinois/NCSA Open Source License.  Both these licenses can be
# found in the LICENSE file.

import json
import os
import shutil
import sys
import tempfile
import time
from pathlib import Path


profiler_logs_path = os.path.join(tempfile.gettempdir(), 'emscripten_toolchain_profiler_logs')


# Deletes all previously captured log files to make room for a new clean run.
def delete_profiler_logs():
  if os.path.exists(profiler_logs_path):
    shutil.rmtree(profiler_logs_path)


def list_files_in_directory(d):
  files = []
  if os.path.exists(d):
    for i in os.listdir(d):
      f = os.path.join(d, i)
      if os.path.isfile(f):
        files.append(f)
  return files


def create_profiling_graph(outfile):
  log_files = [f for f in list_files_in_directory(profiler_logs_path) if 'toolchain_profiler.pid_' in f]

  all_results = []
  if len(log_files):
    print(f'Processing {len(log_files)} profile log files in {profiler_logs_path}...')
  for f in log_files:
    print(f'Processing: {f}')
    json_data = Path(f).read_text()
    if len(json_data.strip()) == 0:
      continue
    lines = json_data.split('\n')
    lines = [x for x in lines if x != '[' and x != ']' and x != ',' and len(x.strip())]
    lines = [(x + ',') if not x.endswith(',') else x for x in lines]
    lines[-1] = lines[-1][:-1]
    json_data = '[' + '\n'.join(lines) + ']'
    try:
      all_results += json.loads(json_data)
    except json.JSONDecodeError as e:
      print(str(e), file=sys.stderr)
      print('Failed to parse JSON file "' + f + '"!', file=sys.stderr)
      return 1
  if len(all_results) == 0:
    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)
    return 1

  all_results.sort(key=lambda x: x['time'])

  emprofile_json_data = json.dumps(all_results, indent=2)

  html_file = outfile + '.html'
  html_contents = Path(os.path.dirname(os.path.realpath(__file__)), 'toolchain_profiler.results_template.html').read_text().replace('{{{ emprofile_json_data }}}', emprofile_json_data)
  Path(html_file).write_text(html_contents)
  print(f'Wrote "{html_file}"')
  return 0


def main(args):
  if '--help' in args:
    print('''\
Usage:
       emprofile.py --clear (or -c)
         Deletes all previously recorded profiling log files.
         Use this to abort/drop any previously collected
         profiling data for a new profiling run.

       emprofile.py [--no-clear]
         Draws a graph from all recorded profiling log files,
         and deletes the recorded profiling files, unless
         --no-clear is also passed.

Optional parameters:

        --outfile=x.html (or -o=x.html)
          Specifies the name of the results file to generate.
''')
    return 0

  if '--reset' in args or '--clear' in args or '-c' in args:
    delete_profiler_logs()
    return 0
  else:
    outfile = 'toolchain_profiler.results_' + time.strftime('%Y%m%d_%H%M')
    for i, arg in enumerate(args):
      if arg.startswith('--outfile=') or arg.startswith('-o='):
        outfile = arg.split('=', 1)[1].strip().replace('.html', '')
      elif arg == '-o':
        outfile = args[i + 1].strip().replace('.html', '')
    if create_profiling_graph(outfile):
      return 1
    if '--no-clear' not in args:
      delete_profiler_logs()

  return 0


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))