From 5978b607d24d1968ed6f589bf74fb502d32a13c2 Mon Sep 17 00:00:00 2001 From: Derek Xu Date: Mon, 24 Apr 2023 18:29:23 +0000 Subject: [PATCH] [VM/Timeline] Make a header file for perfetto_utils This is being done to allow us to access the utils from profiler_service.cc. TEST=Requested a trace using the getPerfettoVMTimeline RPC and confirmed that it still looked correct. Change-Id: Icfb7a5b41da0fc987a72098c4345e7e108b6566e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/297740 Reviewed-by: Ben Konyi Commit-Queue: Derek Xu --- runtime/vm/perfetto_utils.h | 117 ++++++++++++++++++++++++++++++++++++ runtime/vm/timeline.cc | 89 +-------------------------- runtime/vm/vm_sources.gni | 1 + 3 files changed, 119 insertions(+), 88 deletions(-) create mode 100644 runtime/vm/perfetto_utils.h diff --git a/runtime/vm/perfetto_utils.h b/runtime/vm/perfetto_utils.h new file mode 100644 index 00000000000..60bc9ab3deb --- /dev/null +++ b/runtime/vm/perfetto_utils.h @@ -0,0 +1,117 @@ +// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef RUNTIME_VM_PERFETTO_UTILS_H_ +#define RUNTIME_VM_PERFETTO_UTILS_H_ + +#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT) + +#include +#include +#include + +#include "perfetto/ext/tracing/core/trace_packet.h" +#include "perfetto/protozero/scattered_heap_buffer.h" +#include "vm/json_stream.h" +#include "vm/os.h" +#include "vm/protos/perfetto/common/builtin_clock.pbzero.h" +#include "vm/protos/perfetto/trace/clock_snapshot.pbzero.h" +#include "vm/protos/perfetto/trace/trace_packet.pbzero.h" +#include "vm/protos/perfetto/trace/track_event/process_descriptor.pbzero.h" +#include "vm/protos/perfetto/trace/track_event/track_descriptor.pbzero.h" + +namespace dart { + +namespace perfetto_utils { + +inline void SetTrustedPacketSequenceId( + perfetto::protos::pbzero::TracePacket* packet) { + // trusted_packet_sequence_id uniquely identifies a trace producer + writer + // pair. We set the trusted_packet_sequence_id of all packets that we write to + // the arbitrary value of 1. + packet->set_trusted_packet_sequence_id(1); +} + +inline void PopulateClockSnapshotPacket( + perfetto::protos::pbzero::TracePacket* packet) { + SetTrustedPacketSequenceId(packet); + + perfetto::protos::pbzero::ClockSnapshot& clock_snapshot = + *packet->set_clock_snapshot(); + clock_snapshot.set_primary_trace_clock( + perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MONOTONIC); + + perfetto::protos::pbzero::ClockSnapshot_Clock& clock = + *clock_snapshot.add_clocks(); + clock.set_clock_id( + perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MONOTONIC); + clock.set_timestamp(OS::GetCurrentMonotonicMicrosForTimeline() * 1000); +} + +inline void PopulateProcessDescriptorPacket( + perfetto::protos::pbzero::TracePacket* packet) { + perfetto_utils::SetTrustedPacketSequenceId(packet); + + perfetto::protos::pbzero::TrackDescriptor& track_descriptor = + *packet->set_track_descriptor(); + const int64_t pid = OS::ProcessId(); + track_descriptor.set_uuid(pid); + + perfetto::protos::pbzero::ProcessDescriptor& process_descriptor = + *track_descriptor.set_process(); + process_descriptor.set_pid(pid); + // TODO(derekx): Add the process name. +} + +inline const std::tuple, intptr_t> +GetProtoPreamble( + protozero::HeapBuffered* packet) { + ASSERT(packet != nullptr); + + intptr_t size = 0; + for (const protozero::ScatteredHeapBuffer::Slice& slice : + packet->GetSlices()) { + size += slice.size() - slice.unused_bytes(); + } + + std::unique_ptr preamble = + std::make_unique(perfetto::TracePacket::kMaxPreambleBytes); + uint8_t* ptr = &preamble[0]; + + const uint8_t tag = protozero::proto_utils::MakeTagLengthDelimited( + perfetto::TracePacket::kPacketFieldNumber); + static_assert(tag < 0x80, "TracePacket tag should fit in one byte"); + *(ptr++) = tag; + + ptr = protozero::proto_utils::WriteVarInt(size, ptr); + intptr_t preamble_size = reinterpret_cast(ptr) - + reinterpret_cast(&preamble[0]); + return std::make_tuple(std::move(preamble), preamble_size); +} + +inline void AppendPacketToJSONBase64String( + JSONBase64String* jsonBase64String, + protozero::HeapBuffered* packet) { + ASSERT(jsonBase64String != nullptr); + ASSERT(packet != nullptr); + + const std::tuple, intptr_t>& response = + perfetto_utils::GetProtoPreamble(packet); + const uint8_t* preamble = std::get<0>(response).get(); + const intptr_t preamble_length = std::get<1>(response); + jsonBase64String->AppendBytes(preamble, preamble_length); + for (const protozero::ScatteredHeapBuffer::Slice& slice : + packet->GetSlices()) { + jsonBase64String->AppendBytes(slice.start(), + slice.size() - slice.unused_bytes()); + } +} + +} // namespace perfetto_utils + +} // namespace dart + +#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT) + +#endif // RUNTIME_VM_PERFETTO_UTILS_H_ diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc index d884ef71184..b90b39de6fd 100644 --- a/runtime/vm/timeline.cc +++ b/runtime/vm/timeline.cc @@ -29,6 +29,7 @@ #if defined(SUPPORT_PERFETTO) && !defined(PRODUCT) #include "perfetto/ext/tracing/core/trace_packet.h" +#include "vm/perfetto_utils.h" #include "vm/protos/perfetto/common/builtin_clock.pbzero.h" #include "vm/protos/perfetto/trace/clock_snapshot.pbzero.h" #include "vm/protos/perfetto/trace/trace_packet.pbzero.h" @@ -41,94 +42,6 @@ namespace dart { -#if defined(SUPPORT_PERFETTO) && !defined(PRODUCT) -namespace perfetto_utils { - -inline void SetTrustedPacketSequenceId( - perfetto::protos::pbzero::TracePacket* packet) { - // trusted_packet_sequence_id uniquely identifies a trace producer + writer - // pair. We set the trusted_packet_sequence_id of all packets written by the - // Perfetto file recorder to the arbitrary value of 1. - packet->set_trusted_packet_sequence_id(1); -} - -inline void PopulateClockSnapshotPacket( - perfetto::protos::pbzero::TracePacket* packet) { - SetTrustedPacketSequenceId(packet); - - perfetto::protos::pbzero::ClockSnapshot& clock_snapshot = - *packet->set_clock_snapshot(); - clock_snapshot.set_primary_trace_clock( - perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MONOTONIC); - - perfetto::protos::pbzero::ClockSnapshot_Clock& clock = - *clock_snapshot.add_clocks(); - clock.set_clock_id( - perfetto::protos::pbzero::BuiltinClock::BUILTIN_CLOCK_MONOTONIC); - clock.set_timestamp(OS::GetCurrentMonotonicMicrosForTimeline() * 1000); -} - -inline void PopulateProcessDescriptorPacket( - perfetto::protos::pbzero::TracePacket* packet) { - perfetto_utils::SetTrustedPacketSequenceId(packet); - - perfetto::protos::pbzero::TrackDescriptor& track_descriptor = - *packet->set_track_descriptor(); - const int64_t pid = OS::ProcessId(); - track_descriptor.set_uuid(pid); - - perfetto::protos::pbzero::ProcessDescriptor& process_descriptor = - *track_descriptor.set_process(); - process_descriptor.set_pid(pid); - // TODO(derekx): Add the process name. -} - -inline const std::tuple, intptr_t> -GetProtoPreamble( - protozero::HeapBuffered* packet) { - ASSERT(packet != nullptr); - - intptr_t size = 0; - for (const protozero::ScatteredHeapBuffer::Slice& slice : - packet->GetSlices()) { - size += slice.size() - slice.unused_bytes(); - } - - std::unique_ptr preamble = - std::make_unique(perfetto::TracePacket::kMaxPreambleBytes); - uint8_t* ptr = &preamble[0]; - - const uint8_t tag = protozero::proto_utils::MakeTagLengthDelimited( - perfetto::TracePacket::kPacketFieldNumber); - static_assert(tag < 0x80, "TracePacket tag should fit in one byte"); - *(ptr++) = tag; - - ptr = protozero::proto_utils::WriteVarInt(size, ptr); - intptr_t preamble_size = reinterpret_cast(ptr) - - reinterpret_cast(&preamble[0]); - return std::make_tuple(std::move(preamble), preamble_size); -} - -inline void AppendPacketToJSONBase64String( - JSONBase64String* jsonBase64String, - protozero::HeapBuffered* packet) { - ASSERT(jsonBase64String != nullptr); - ASSERT(packet != nullptr); - - auto& response = perfetto_utils::GetProtoPreamble(packet); - const uint8_t* preamble = std::get<0>(response).get(); - const intptr_t preamble_length = std::get<1>(response); - jsonBase64String->AppendBytes(preamble, preamble_length); - for (const protozero::ScatteredHeapBuffer::Slice& slice : - packet->GetSlices()) { - jsonBase64String->AppendBytes(slice.start(), - slice.size() - slice.unused_bytes()); - } -} - -} // namespace perfetto_utils -#endif // defined(SUPPORT_PERFETTO) && !defined(PRODUCT) - #if defined(PRODUCT) #define DEFAULT_TIMELINE_RECORDER "none" #define SUPPORTED_TIMELINE_RECORDERS "systrace, file, callback" diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni index eee843820d3..edced357b81 100644 --- a/runtime/vm/vm_sources.gni +++ b/runtime/vm/vm_sources.gni @@ -221,6 +221,7 @@ vm_sources = [ "parser.h", "pending_deopts.cc", "pending_deopts.h", + "perfetto_utils.h", "pointer_tagging.h", "port.cc", "port.h",