diff options
Diffstat (limited to 'perf-testing/Docker/merge_traces.py')
-rwxr-xr-x | perf-testing/Docker/merge_traces.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/perf-testing/Docker/merge_traces.py b/perf-testing/Docker/merge_traces.py new file mode 100755 index 00000000..0d2f7a3a --- /dev/null +++ b/perf-testing/Docker/merge_traces.py @@ -0,0 +1,154 @@ +#!/usr/bin/python3 +# +# Copyright (C) 2020 Collabora Ltd +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +from google import protobuf +import protos.perfetto.trace.perfetto_trace_pb2 +from protos.perfetto.trace.perfetto_trace_pb2 import BUILTIN_CLOCK_BOOTTIME +from protos.perfetto.trace.perfetto_trace_pb2 import BUILTIN_CLOCK_REALTIME +import math +import sys +import operator +import time + +def add_ftrace_event(out_message, in_packet, in_event, max_host_sequence_id = 0): + out_packet = out_message.packet.add() + out_packet.ftrace_events.cpu = in_packet.ftrace_events.cpu + out_packet.trusted_uid = in_packet.trusted_uid + out_packet.trusted_packet_sequence_id += max_host_sequence_id + out_packet.ftrace_events.event.add().CopyFrom(in_event) + +virtio_gpu_pids = set() + +print('%d Loading host trace' % time.time()) + +in_message = protos.perfetto.trace.perfetto_trace_pb2.Trace() +in_message.ParseFromString(open(sys.argv[1], 'rb').read()) + +print('%d Copying host trace' % time.time()) + +out_message = protos.perfetto.trace.perfetto_trace_pb2.Trace() +max_host_sequence_id = 0 +first_host_virtio_gpu_cmd = math.inf +host_boot_ts = -1 +for in_packet in in_message.packet: + max_host_sequence_id = max(max_host_sequence_id, + in_packet.trusted_packet_sequence_id) + + if in_packet.HasField('ftrace_events'): + for event in in_packet.ftrace_events.event: + if event.HasField('sched_switch'): + if 'virtio_gpu' == event.sched_switch.prev_comm: + virtio_gpu_pids.add(event.sched_switch.prev_pid) + if 'virtio_gpu' == event.sched_switch.next_comm: + virtio_gpu_pids.add(event.sched_switch.next_pid) + + if event.sched_switch.prev_pid in virtio_gpu_pids or \ + event.sched_switch.next_pid in virtio_gpu_pids: + add_ftrace_event(out_message, in_packet, event) + elif event.HasField('sched_wakeup'): + if 'virtio_gpu' == event.sched_wakeup.comm: + virtio_gpu_pids.add(event.sched_wakeup.pid) + + if event.sched_wakeup.pid in virtio_gpu_pids: + add_ftrace_event(out_message, in_packet, event) + elif event.HasField('print'): + event_type, guest_pid, label, cookie = event.print.buf.split('|') + + # Replace host PID with the guest PID + event.pid = int(guest_pid) + add_ftrace_event(out_message, in_packet, event) + else: + if in_packet.HasField('track_descriptor'): + if in_packet.track_descriptor.HasField('name'): + in_packet.track_descriptor.name += ' (Host)' + elif in_packet.HasField('track_event'): + if in_packet.track_event.type == in_packet.track_event.TYPE_SLICE_BEGIN and \ + in_packet.track_event.name == 'GetCapset': + first_host_virtio_gpu_cmd = min(first_host_virtio_gpu_cmd, in_packet.timestamp) + elif host_boot_ts == -1 and in_packet.HasField('clock_snapshot'): + for clock in in_packet.clock_snapshot.clocks: + if clock.clock_id == BUILTIN_CLOCK_BOOTTIME: + host_boottime = clock.timestamp + elif clock.clock_id == BUILTIN_CLOCK_REALTIME: + host_realtime = clock.timestamp + host_boot_ts = host_realtime - host_boottime + out_packet = out_message.packet.add() + out_packet.CopyFrom(in_packet) + +print('%d Loading guest trace' % time.time()) +in_message.ParseFromString(open(sys.argv[2], 'rb').read()) + +#print('%d Writing guest trace txt' % time.time()) +#open('../traces-db/perfetto-guest.txt', 'w').write(str(in_message)) + +first_guest_virtio_gpu_cmd = math.inf +guest_boot_ts = -1 +for in_packet in in_message.packet: + if guest_boot_ts == -1 and in_packet.HasField('clock_snapshot'): + for clock in in_packet.clock_snapshot.clocks: + if clock.clock_id == BUILTIN_CLOCK_BOOTTIME: + guest_boottime = clock.timestamp + elif clock.clock_id == BUILTIN_CLOCK_REALTIME: + guest_realtime = clock.timestamp + guest_boot_ts = guest_realtime - guest_boottime + elif in_packet.HasField('track_event'): + if in_packet.track_event.type == in_packet.track_event.TYPE_SLICE_BEGIN and \ + in_packet.track_event.name == 'DRM_IOCTL_VIRTGPU_GET_CAPS': + first_guest_virtio_gpu_cmd = min(first_guest_virtio_gpu_cmd, in_packet.timestamp) + +delta = guest_boot_ts - host_boot_ts +cmd_delta = first_host_virtio_gpu_cmd - first_guest_virtio_gpu_cmd - delta +print("boottime delta %ds." % (delta / 1000 / 1000 / 1000)) +print("cmd delta %dus." % (cmd_delta / 1000)) + +for in_packet in in_message.packet: + if in_packet.HasField('process_tree') or \ + in_packet.HasField('service_event') or \ + in_packet.HasField('track_event') or \ + in_packet.HasField('trace_packet_defaults') or \ + in_packet.HasField('track_descriptor'): + out_packet = out_message.packet.add() + out_packet.CopyFrom(in_packet) + out_packet.trusted_packet_sequence_id += max_host_sequence_id + out_packet.timestamp += delta + if out_packet.HasField('track_descriptor'): + if out_packet.track_descriptor.HasField('name'): + out_packet.track_descriptor.name += ' (Guest)' + elif in_packet.HasField('ftrace_events'): + for event in in_packet.ftrace_events.event: + event.timestamp += delta + add_ftrace_event(out_message, in_packet, event, max_host_sequence_id) + +def get_timestamp(packet): + if packet.HasField('timestamp'): + return packet.timestamp + elif packet.HasField('ftrace_events') and \ + packet.ftrace_events.event: + return packet.ftrace_events.event[0].timestamp + return 0 + +out_message.packet.sort(key=get_timestamp) +print('%d Writing merged trace' % time.time()) +open(sys.argv[3], 'wb').write(out_message.SerializeToString()) + +#print('%d Writing merged trace txt' % time.time()) +#open('../traces-db/perfetto.txt', 'w').write(str(out_message)) |