[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 <bkonyi@google.com>
Commit-Queue: Derek Xu <derekx@google.com>
This commit is contained in:
Derek Xu 2023-04-24 18:29:23 +00:00 committed by Commit Queue
parent 903be31b05
commit 5978b607d2
3 changed files with 119 additions and 88 deletions

117
runtime/vm/perfetto_utils.h Normal file
View file

@ -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 <memory>
#include <tuple>
#include <utility>
#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<std::unique_ptr<const uint8_t[]>, intptr_t>
GetProtoPreamble(
protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>* 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<uint8_t[]> preamble =
std::make_unique<uint8_t[]>(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<intptr_t>(ptr) -
reinterpret_cast<intptr_t>(&preamble[0]);
return std::make_tuple(std::move(preamble), preamble_size);
}
inline void AppendPacketToJSONBase64String(
JSONBase64String* jsonBase64String,
protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>* packet) {
ASSERT(jsonBase64String != nullptr);
ASSERT(packet != nullptr);
const std::tuple<std::unique_ptr<const uint8_t[]>, 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_

View file

@ -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<std::unique_ptr<const uint8_t[]>, intptr_t>
GetProtoPreamble(
protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>* 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<uint8_t[]> preamble =
std::make_unique<uint8_t[]>(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<intptr_t>(ptr) -
reinterpret_cast<intptr_t>(&preamble[0]);
return std::make_tuple(std::move(preamble), preamble_size);
}
inline void AppendPacketToJSONBase64String(
JSONBase64String* jsonBase64String,
protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>* 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"

View file

@ -221,6 +221,7 @@ vm_sources = [
"parser.h",
"pending_deopts.cc",
"pending_deopts.h",
"perfetto_utils.h",
"pointer_tagging.h",
"port.cc",
"port.h",