blob: 4cf861386065fd0de7a9e2d768b01f841114034c [file] [log] [blame]
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +01001#!/usr/bin/env python3
2# Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
6import os
7import subprocess
8import sys
9
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020010
Christoffer Quist Adamsen2d973412023-08-18 14:57:10 +020011def get_trace_processor():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020012 try:
13 from perfetto.trace_processor import TraceProcessor
14 except ImportError:
15 sys.exit(
16 'Unable to analyze perfetto trace without the perfetto library. '
17 'Install instructions:\n'
18 ' sudo apt install python3-pip\n'
19 ' pip3 install perfetto')
20 return TraceProcessor
21
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +010022
23def ensure_record_android_trace(tmp_dir):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020024 record_android_trace_path = os.path.join(tmp_dir, 'record_android_trace')
25 if not os.path.exists(record_android_trace_path):
26 cmd = [
27 'curl', '--output', record_android_trace_path, '--silent',
28 'https://raw.githubusercontent.com/google/perfetto/master/tools/'
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +010029 'record_android_trace'
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020030 ]
31 subprocess.check_call(cmd)
32 assert os.path.exists(record_android_trace_path)
33 return record_android_trace_path
34
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +010035
Christoffer Quist Adamsen3f7e4282022-04-21 13:12:31 +020036def record_android_trace(out_dir, tmp_dir, device_id=None):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020037 record_android_trace_path = ensure_record_android_trace(tmp_dir)
38 config_path = os.path.join(os.path.dirname(__file__), 'config.pbtx')
39 perfetto_trace_path = os.path.join(out_dir, 'trace.perfetto-trace')
40 cmd = [
41 sys.executable, record_android_trace_path, '--config', config_path,
42 '--out', perfetto_trace_path, '--no-open'
43 ]
44 if device_id is not None:
45 cmd.extend(['--serial', device_id])
46 perfetto_process = subprocess.Popen(cmd,
47 stdout=subprocess.PIPE,
48 stderr=subprocess.PIPE)
49 lines = []
50 for line in perfetto_process.stdout:
51 line = line.decode('utf-8')
52 lines.append(line)
53 if 'enabled ftrace' in line.strip():
54 return perfetto_process, perfetto_trace_path
55 raise ValueError(
56 'Expected to find line containing: enabled ftrace, got: %s' % lines)
57
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +010058
59def stop_record_android_trace(perfetto_process, out_dir):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020060 if perfetto_process.poll() is not None:
61 raise ValueError('Expected perfetto process to be running')
62 # perfetto should terminate in at most 15 seconds,
63 perfetto_config_duration = 15
64 stdout, stderr = perfetto_process.communicate(
65 timeout=perfetto_config_duration * 2)
66 stdout = stdout.decode('utf-8')
67 stderr = stderr.decode('utf-8')
68 assert perfetto_process.returncode == 0
69 assert os.path.exists(os.path.join(out_dir, 'trace.perfetto-trace'))
70
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +010071
72# https://perfetto.dev/docs/analysis/sql-tables
73def find_slices_by_name(slice_name, options, trace_processor):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020074 return trace_processor.query(
75 'SELECT slice.dur, slice.ts FROM slice'
76 ' INNER JOIN thread_track ON (slice.track_id = thread_track.id)'
77 ' INNER JOIN thread using (utid)'
78 ' INNER JOIN process using (upid)'
79 ' WHERE slice.name = "%s"'
80 ' AND process.name = "%s"'
81 ' ORDER BY slice.ts ASC' % (slice_name, options.app_id))
82
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +010083
84def find_unique_slice_by_name(slice_name, options, trace_processor):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020085 query_it = find_slices_by_name(slice_name, options, trace_processor)
86 assert len(query_it) == 1
87 return next(query_it)
88
Christoffer Quist Adamsenfad33a02022-03-14 14:45:09 +010089
90def get_slice_end_since_start(slice, initial_slice):
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020091 return (slice.ts + slice.dur - initial_slice.ts) / 1000000