1*bbecb9d1SAndroid Build Coastguard Worker#!/usr/bin/python3 2*bbecb9d1SAndroid Build Coastguard Worker# 3*bbecb9d1SAndroid Build Coastguard Worker# Copyright (C) 2020 Collabora Ltd 4*bbecb9d1SAndroid Build Coastguard Worker# 5*bbecb9d1SAndroid Build Coastguard Worker# Permission is hereby granted, free of charge, to any person obtaining a 6*bbecb9d1SAndroid Build Coastguard Worker# copy of this software and associated documentation files (the "Software"), 7*bbecb9d1SAndroid Build Coastguard Worker# to deal in the Software without restriction, including without limitation 8*bbecb9d1SAndroid Build Coastguard Worker# the rights to use, copy, modify, merge, publish, distribute, sublicense, 9*bbecb9d1SAndroid Build Coastguard Worker# and/or sell copies of the Software, and to permit persons to whom the 10*bbecb9d1SAndroid Build Coastguard Worker# Software is furnished to do so, subject to the following conditions: 11*bbecb9d1SAndroid Build Coastguard Worker# 12*bbecb9d1SAndroid Build Coastguard Worker# The above copyright notice and this permission notice shall be included 13*bbecb9d1SAndroid Build Coastguard Worker# in all copies or substantial portions of the Software. 14*bbecb9d1SAndroid Build Coastguard Worker# 15*bbecb9d1SAndroid Build Coastguard Worker# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16*bbecb9d1SAndroid Build Coastguard Worker# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17*bbecb9d1SAndroid Build Coastguard Worker# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18*bbecb9d1SAndroid Build Coastguard Worker# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19*bbecb9d1SAndroid Build Coastguard Worker# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20*bbecb9d1SAndroid Build Coastguard Worker# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21*bbecb9d1SAndroid Build Coastguard Worker# OTHER DEALINGS IN THE SOFTWARE. 22*bbecb9d1SAndroid Build Coastguard Worker 23*bbecb9d1SAndroid Build Coastguard Workerfrom google import protobuf 24*bbecb9d1SAndroid Build Coastguard Workerimport protos.perfetto.trace.perfetto_trace_pb2 25*bbecb9d1SAndroid Build Coastguard Workerfrom protos.perfetto.trace.perfetto_trace_pb2 import BUILTIN_CLOCK_BOOTTIME 26*bbecb9d1SAndroid Build Coastguard Workerfrom protos.perfetto.trace.perfetto_trace_pb2 import BUILTIN_CLOCK_REALTIME 27*bbecb9d1SAndroid Build Coastguard Workerimport math 28*bbecb9d1SAndroid Build Coastguard Workerimport sys 29*bbecb9d1SAndroid Build Coastguard Workerimport operator 30*bbecb9d1SAndroid Build Coastguard Workerimport time 31*bbecb9d1SAndroid Build Coastguard Worker 32*bbecb9d1SAndroid Build Coastguard Workerdef add_ftrace_event(out_message, in_packet, in_event, max_host_sequence_id = 0): 33*bbecb9d1SAndroid Build Coastguard Worker out_packet = out_message.packet.add() 34*bbecb9d1SAndroid Build Coastguard Worker out_packet.ftrace_events.cpu = in_packet.ftrace_events.cpu 35*bbecb9d1SAndroid Build Coastguard Worker out_packet.trusted_uid = in_packet.trusted_uid 36*bbecb9d1SAndroid Build Coastguard Worker out_packet.trusted_packet_sequence_id += max_host_sequence_id 37*bbecb9d1SAndroid Build Coastguard Worker out_packet.ftrace_events.event.add().CopyFrom(in_event) 38*bbecb9d1SAndroid Build Coastguard Worker 39*bbecb9d1SAndroid Build Coastguard Workervirtio_gpu_pids = set() 40*bbecb9d1SAndroid Build Coastguard Worker 41*bbecb9d1SAndroid Build Coastguard Workerprint('%d Loading host trace' % time.time()) 42*bbecb9d1SAndroid Build Coastguard Worker 43*bbecb9d1SAndroid Build Coastguard Workerin_message = protos.perfetto.trace.perfetto_trace_pb2.Trace() 44*bbecb9d1SAndroid Build Coastguard Workerin_message.ParseFromString(open(sys.argv[1], 'rb').read()) 45*bbecb9d1SAndroid Build Coastguard Worker 46*bbecb9d1SAndroid Build Coastguard Workerprint('%d Copying host trace' % time.time()) 47*bbecb9d1SAndroid Build Coastguard Worker 48*bbecb9d1SAndroid Build Coastguard Workerout_message = protos.perfetto.trace.perfetto_trace_pb2.Trace() 49*bbecb9d1SAndroid Build Coastguard Workermax_host_sequence_id = 0 50*bbecb9d1SAndroid Build Coastguard Workerfirst_host_virtio_gpu_cmd = math.inf 51*bbecb9d1SAndroid Build Coastguard Workerhost_boot_ts = -1 52*bbecb9d1SAndroid Build Coastguard Workerfor in_packet in in_message.packet: 53*bbecb9d1SAndroid Build Coastguard Worker max_host_sequence_id = max(max_host_sequence_id, 54*bbecb9d1SAndroid Build Coastguard Worker in_packet.trusted_packet_sequence_id) 55*bbecb9d1SAndroid Build Coastguard Worker 56*bbecb9d1SAndroid Build Coastguard Worker if in_packet.HasField('ftrace_events'): 57*bbecb9d1SAndroid Build Coastguard Worker for event in in_packet.ftrace_events.event: 58*bbecb9d1SAndroid Build Coastguard Worker if event.HasField('sched_switch'): 59*bbecb9d1SAndroid Build Coastguard Worker if 'virtio_gpu' == event.sched_switch.prev_comm: 60*bbecb9d1SAndroid Build Coastguard Worker virtio_gpu_pids.add(event.sched_switch.prev_pid) 61*bbecb9d1SAndroid Build Coastguard Worker if 'virtio_gpu' == event.sched_switch.next_comm: 62*bbecb9d1SAndroid Build Coastguard Worker virtio_gpu_pids.add(event.sched_switch.next_pid) 63*bbecb9d1SAndroid Build Coastguard Worker 64*bbecb9d1SAndroid Build Coastguard Worker if event.sched_switch.prev_pid in virtio_gpu_pids or \ 65*bbecb9d1SAndroid Build Coastguard Worker event.sched_switch.next_pid in virtio_gpu_pids: 66*bbecb9d1SAndroid Build Coastguard Worker add_ftrace_event(out_message, in_packet, event) 67*bbecb9d1SAndroid Build Coastguard Worker elif event.HasField('sched_wakeup'): 68*bbecb9d1SAndroid Build Coastguard Worker if 'virtio_gpu' == event.sched_wakeup.comm: 69*bbecb9d1SAndroid Build Coastguard Worker virtio_gpu_pids.add(event.sched_wakeup.pid) 70*bbecb9d1SAndroid Build Coastguard Worker 71*bbecb9d1SAndroid Build Coastguard Worker if event.sched_wakeup.pid in virtio_gpu_pids: 72*bbecb9d1SAndroid Build Coastguard Worker add_ftrace_event(out_message, in_packet, event) 73*bbecb9d1SAndroid Build Coastguard Worker elif event.HasField('print'): 74*bbecb9d1SAndroid Build Coastguard Worker event_type, guest_pid, label, cookie = event.print.buf.split('|') 75*bbecb9d1SAndroid Build Coastguard Worker 76*bbecb9d1SAndroid Build Coastguard Worker # Replace host PID with the guest PID 77*bbecb9d1SAndroid Build Coastguard Worker event.pid = int(guest_pid) 78*bbecb9d1SAndroid Build Coastguard Worker add_ftrace_event(out_message, in_packet, event) 79*bbecb9d1SAndroid Build Coastguard Worker else: 80*bbecb9d1SAndroid Build Coastguard Worker if in_packet.HasField('track_descriptor'): 81*bbecb9d1SAndroid Build Coastguard Worker if in_packet.track_descriptor.HasField('name'): 82*bbecb9d1SAndroid Build Coastguard Worker in_packet.track_descriptor.name += ' (Host)' 83*bbecb9d1SAndroid Build Coastguard Worker elif in_packet.HasField('track_event'): 84*bbecb9d1SAndroid Build Coastguard Worker if in_packet.track_event.type == in_packet.track_event.TYPE_SLICE_BEGIN and \ 85*bbecb9d1SAndroid Build Coastguard Worker in_packet.track_event.name == 'GetCapset': 86*bbecb9d1SAndroid Build Coastguard Worker first_host_virtio_gpu_cmd = min(first_host_virtio_gpu_cmd, in_packet.timestamp) 87*bbecb9d1SAndroid Build Coastguard Worker elif host_boot_ts == -1 and in_packet.HasField('clock_snapshot'): 88*bbecb9d1SAndroid Build Coastguard Worker for clock in in_packet.clock_snapshot.clocks: 89*bbecb9d1SAndroid Build Coastguard Worker if clock.clock_id == BUILTIN_CLOCK_BOOTTIME: 90*bbecb9d1SAndroid Build Coastguard Worker host_boottime = clock.timestamp 91*bbecb9d1SAndroid Build Coastguard Worker elif clock.clock_id == BUILTIN_CLOCK_REALTIME: 92*bbecb9d1SAndroid Build Coastguard Worker host_realtime = clock.timestamp 93*bbecb9d1SAndroid Build Coastguard Worker host_boot_ts = host_realtime - host_boottime 94*bbecb9d1SAndroid Build Coastguard Worker out_packet = out_message.packet.add() 95*bbecb9d1SAndroid Build Coastguard Worker out_packet.CopyFrom(in_packet) 96*bbecb9d1SAndroid Build Coastguard Worker 97*bbecb9d1SAndroid Build Coastguard Workerprint('%d Loading guest trace' % time.time()) 98*bbecb9d1SAndroid Build Coastguard Workerin_message.ParseFromString(open(sys.argv[2], 'rb').read()) 99*bbecb9d1SAndroid Build Coastguard Worker 100*bbecb9d1SAndroid Build Coastguard Worker#print('%d Writing guest trace txt' % time.time()) 101*bbecb9d1SAndroid Build Coastguard Worker#open('../traces-db/perfetto-guest.txt', 'w').write(str(in_message)) 102*bbecb9d1SAndroid Build Coastguard Worker 103*bbecb9d1SAndroid Build Coastguard Workerfirst_guest_virtio_gpu_cmd = math.inf 104*bbecb9d1SAndroid Build Coastguard Workerguest_boot_ts = -1 105*bbecb9d1SAndroid Build Coastguard Workerfor in_packet in in_message.packet: 106*bbecb9d1SAndroid Build Coastguard Worker if guest_boot_ts == -1 and in_packet.HasField('clock_snapshot'): 107*bbecb9d1SAndroid Build Coastguard Worker for clock in in_packet.clock_snapshot.clocks: 108*bbecb9d1SAndroid Build Coastguard Worker if clock.clock_id == BUILTIN_CLOCK_BOOTTIME: 109*bbecb9d1SAndroid Build Coastguard Worker guest_boottime = clock.timestamp 110*bbecb9d1SAndroid Build Coastguard Worker elif clock.clock_id == BUILTIN_CLOCK_REALTIME: 111*bbecb9d1SAndroid Build Coastguard Worker guest_realtime = clock.timestamp 112*bbecb9d1SAndroid Build Coastguard Worker guest_boot_ts = guest_realtime - guest_boottime 113*bbecb9d1SAndroid Build Coastguard Worker elif in_packet.HasField('track_event'): 114*bbecb9d1SAndroid Build Coastguard Worker if in_packet.track_event.type == in_packet.track_event.TYPE_SLICE_BEGIN and \ 115*bbecb9d1SAndroid Build Coastguard Worker in_packet.track_event.name == 'DRM_IOCTL_VIRTGPU_GET_CAPS': 116*bbecb9d1SAndroid Build Coastguard Worker first_guest_virtio_gpu_cmd = min(first_guest_virtio_gpu_cmd, in_packet.timestamp) 117*bbecb9d1SAndroid Build Coastguard Worker 118*bbecb9d1SAndroid Build Coastguard Workerdelta = guest_boot_ts - host_boot_ts 119*bbecb9d1SAndroid Build Coastguard Workercmd_delta = first_host_virtio_gpu_cmd - first_guest_virtio_gpu_cmd - delta 120*bbecb9d1SAndroid Build Coastguard Workerprint("boottime delta %ds." % (delta / 1000 / 1000 / 1000)) 121*bbecb9d1SAndroid Build Coastguard Workerprint("cmd delta %dus." % (cmd_delta / 1000)) 122*bbecb9d1SAndroid Build Coastguard Worker 123*bbecb9d1SAndroid Build Coastguard Workerfor in_packet in in_message.packet: 124*bbecb9d1SAndroid Build Coastguard Worker if in_packet.HasField('process_tree') or \ 125*bbecb9d1SAndroid Build Coastguard Worker in_packet.HasField('service_event') or \ 126*bbecb9d1SAndroid Build Coastguard Worker in_packet.HasField('track_event') or \ 127*bbecb9d1SAndroid Build Coastguard Worker in_packet.HasField('trace_packet_defaults') or \ 128*bbecb9d1SAndroid Build Coastguard Worker in_packet.HasField('track_descriptor'): 129*bbecb9d1SAndroid Build Coastguard Worker out_packet = out_message.packet.add() 130*bbecb9d1SAndroid Build Coastguard Worker out_packet.CopyFrom(in_packet) 131*bbecb9d1SAndroid Build Coastguard Worker out_packet.trusted_packet_sequence_id += max_host_sequence_id 132*bbecb9d1SAndroid Build Coastguard Worker out_packet.timestamp += delta 133*bbecb9d1SAndroid Build Coastguard Worker if out_packet.HasField('track_descriptor'): 134*bbecb9d1SAndroid Build Coastguard Worker if out_packet.track_descriptor.HasField('name'): 135*bbecb9d1SAndroid Build Coastguard Worker out_packet.track_descriptor.name += ' (Guest)' 136*bbecb9d1SAndroid Build Coastguard Worker elif in_packet.HasField('ftrace_events'): 137*bbecb9d1SAndroid Build Coastguard Worker for event in in_packet.ftrace_events.event: 138*bbecb9d1SAndroid Build Coastguard Worker event.timestamp += delta 139*bbecb9d1SAndroid Build Coastguard Worker add_ftrace_event(out_message, in_packet, event, max_host_sequence_id) 140*bbecb9d1SAndroid Build Coastguard Worker 141*bbecb9d1SAndroid Build Coastguard Workerdef get_timestamp(packet): 142*bbecb9d1SAndroid Build Coastguard Worker if packet.HasField('timestamp'): 143*bbecb9d1SAndroid Build Coastguard Worker return packet.timestamp 144*bbecb9d1SAndroid Build Coastguard Worker elif packet.HasField('ftrace_events') and \ 145*bbecb9d1SAndroid Build Coastguard Worker packet.ftrace_events.event: 146*bbecb9d1SAndroid Build Coastguard Worker return packet.ftrace_events.event[0].timestamp 147*bbecb9d1SAndroid Build Coastguard Worker return 0 148*bbecb9d1SAndroid Build Coastguard Worker 149*bbecb9d1SAndroid Build Coastguard Workerout_message.packet.sort(key=get_timestamp) 150*bbecb9d1SAndroid Build Coastguard Workerprint('%d Writing merged trace' % time.time()) 151*bbecb9d1SAndroid Build Coastguard Workeropen(sys.argv[3], 'wb').write(out_message.SerializeToString()) 152*bbecb9d1SAndroid Build Coastguard Worker 153*bbecb9d1SAndroid Build Coastguard Worker#print('%d Writing merged trace txt' % time.time()) 154*bbecb9d1SAndroid Build Coastguard Worker#open('../traces-db/perfetto.txt', 'w').write(str(out_message)) 155