Flutter Engine
The Flutter Engine
parse_lottieweb_trace.py
Go to the documentation of this file.
1# Copyright 2024 Google LLC
2#
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6import json
7import sys
8
9trace_output = sys.argv[1]
10with open(trace_output, 'r') as f:
11 trace_json = json.load(f)
12output_json_file = sys.argv[2]
13renderer = sys.argv[3] # Unused for now but might be useful in the future.
14
15# Output data about the GPU that was used.
16print('GPU data:')
17print(trace_json['metadata'].get('gpu-gl-renderer'))
18print(trace_json['metadata'].get('gpu-driver'))
19print(trace_json['metadata'].get('gpu-gl-vendor'))
20
21erroneous_termination_statuses = [
22 'replaced_by_new_reporter_at_same_stage',
23 'did_not_produce_frame',
24]
25accepted_termination_statuses = [
26 'missed_frame',
27 'submitted_frame',
28 'main_frame_aborted'
29]
30
31current_frame_duration = 0
32total_frames = 0
33frame_id_to_start_ts = {}
34# Will contain tuples of frame_ids and their duration and status.
35completed_frame_id_and_duration_status = []
36# Will contain tuples of drawn frame_ids and their duration.
37drawn_frame_id_and_duration = []
38for trace in trace_json['traceEvents']:
39 if 'PipelineReporter' in trace['name']:
40 frame_id = trace['id']
41 args = trace.get('args')
42 if args and args.get('step') == 'BeginImplFrameToSendBeginMainFrame':
43 frame_id_to_start_ts[frame_id] = trace['ts']
44 elif args and (args.get('termination_status') in
45 accepted_termination_statuses):
46 if not frame_id_to_start_ts.get(frame_id):
47 print('[No start ts found for %s]' % frame_id)
48 continue
49 current_frame_duration = trace['ts'] - frame_id_to_start_ts[frame_id]
50 total_frames += 1
51 completed_frame_id_and_duration_status.append(
52 (frame_id, current_frame_duration, args['termination_status']))
53 if(args['termination_status'] == 'missed_frame' or
54 args['termination_status'] == 'submitted_frame'):
55 drawn_frame_id_and_duration.append((frame_id, current_frame_duration))
56
57 # We are done with this frame_id so remove it from the dict.
58 frame_id_to_start_ts.pop(frame_id)
59 print('%d (%s with %s): %d' % (
60 total_frames, frame_id, args['termination_status'],
61 current_frame_duration))
62 elif args and (args.get('termination_status') in
63 erroneous_termination_statuses):
64 # Invalidate previously collected results for this frame_id.
65 if frame_id_to_start_ts.get(frame_id):
66 print('[Invalidating %s due to %s]' % (
67 frame_id, args['termination_status']))
68 frame_id_to_start_ts.pop(frame_id)
69
70# Calculate metrics for total completed frames.
71total_completed_frames = len(completed_frame_id_and_duration_status)
72if total_completed_frames < 25:
73 raise Exception('Even with 3 loops found only %d frames' %
74 total_completed_frames)
75# Get frame avg/min/max for the middle 25 frames.
76start = (total_completed_frames - 25) // 2
77print('Got %d total completed frames. Using indexes [%d, %d).' % (
78 total_completed_frames, start, start+25))
79frame_max = 0
80frame_min = 0
81frame_cumulative = 0
82aborted_frames = 0
83for frame_id, duration, status in (
84 completed_frame_id_and_duration_status[start:start+25]):
85 frame_max = max(frame_max, duration)
86 frame_min = min(frame_min, duration) if frame_min else duration
87 frame_cumulative += duration
88 if status == 'main_frame_aborted':
89 aborted_frames += 1
90
91perf_results = {}
92perf_results['frame_max_us'] = frame_max
93perf_results['frame_min_us'] = frame_min
94perf_results['frame_avg_us'] = frame_cumulative/25
95perf_results['aborted_frames'] = aborted_frames
96
97# Now calculate metrics for only drawn frames.
98drawn_frame_max = 0
99drawn_frame_min = 0
100drawn_frame_cumulative = 0
101total_drawn_frames = len(drawn_frame_id_and_duration)
102if total_drawn_frames < 25:
103 raise Exception('Even with 3 loops found only %d drawn frames' %
104 total_drawn_frames)
105# Get drawn frame avg/min/max from the middle 25 frames.
106start = (total_drawn_frames - 25) // 2
107print('Got %d total drawn frames. Using indexes [%d-%d).' % (
108 total_drawn_frames, start, start+25))
109for frame_id, duration in drawn_frame_id_and_duration[start:start+25]:
110 drawn_frame_max = max(drawn_frame_max, duration)
111 drawn_frame_min = (min(drawn_frame_min, duration)
112 if drawn_frame_min else duration)
113 drawn_frame_cumulative += duration
114# Add metrics to perf_results.
115perf_results['drawn_frame_max_us'] = drawn_frame_max
116perf_results['drawn_frame_min_us'] = drawn_frame_min
117perf_results['drawn_frame_avg_us'] = drawn_frame_cumulative/25
118
119print('Final perf_results dict: %s' % perf_results)
120
121# Write perf_results to the output json.
122with open(output_json_file, 'w') as f:
123 f.write(json.dumps(perf_results))
if(end==-1)
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
const myers::Point & get(const myers::Segment &)
def print(*args, **kwargs)
Definition: run_tests.py:49