[VM/Timeline] Factor out the parts of recorders' PrintJSON methods that iterate over events

This will allow us to reuse the shared logic when returning Perfetto
traces through the service. This CL also changes some pointer parameters
to const reference parameters.

TEST=manually verified that traces recorded with the JSON file
recorder still contained correct information, CI

Change-Id: I70ac5183959dd8c6efeb55d4891a8e00d3550ca5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/288060
Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Derek Xu 2023-04-20 16:42:23 +00:00 committed by Commit Queue
parent ac415f30c5
commit 20a8899318
2 changed files with 81 additions and 48 deletions

View file

@ -11,6 +11,7 @@
#include <fcntl.h>
#include <cstdlib>
#include <functional>
#include <memory>
#include <tuple>
#include <utility>
@ -1588,9 +1589,9 @@ intptr_t TimelineEventFixedBufferRecorder::Size() {
}
#ifndef PRODUCT
void TimelineEventFixedBufferRecorder::PrintJSONEvents(
JSONArray* events,
TimelineEventFilter* filter) {
void TimelineEventFixedBufferRecorder::PrintEventsCommon(
const TimelineEventFilter& filter,
std::function<void(const TimelineEvent&)> print_impl) {
MutexLocker ml(&lock_);
ResetTimeTracking();
intptr_t block_offset = FindOldestBlockIndex();
@ -1601,22 +1602,30 @@ void TimelineEventFixedBufferRecorder::PrintJSONEvents(
for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
TimelineEventBlock* block =
&blocks_[(block_idx + block_offset) % num_blocks_];
if (!filter->IncludeBlock(block)) {
if (!filter.IncludeBlock(block)) {
continue;
}
for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) {
TimelineEvent* event = block->At(event_idx);
if (filter->IncludeEvent(event) &&
event->Within(filter->time_origin_micros(),
filter->time_extent_micros())) {
if (filter.IncludeEvent(event) &&
event->Within(filter.time_origin_micros(),
filter.time_extent_micros())) {
ReportTime(event->LowTime());
ReportTime(event->HighTime());
events->AddValue(event);
print_impl(*event);
}
}
}
}
void TimelineEventFixedBufferRecorder::PrintJSONEvents(
const JSONArray& events,
const TimelineEventFilter& filter) {
PrintEventsCommon(filter, [&events](const TimelineEvent& event) {
events.AddValue(&event);
});
}
void TimelineEventFixedBufferRecorder::PrintJSON(JSONStream* js,
TimelineEventFilter* filter) {
JSONObject topLevel(js);
@ -1624,7 +1633,7 @@ void TimelineEventFixedBufferRecorder::PrintJSON(JSONStream* js,
{
JSONArray events(&topLevel, "traceEvents");
PrintJSONMeta(events);
PrintJSONEvents(&events, filter);
PrintJSONEvents(events, *filter);
}
topLevel.AddPropertyTimeMicros("timeOriginMicros", TimeOriginMicros());
topLevel.AddPropertyTimeMicros("timeExtentMicros", TimeExtentMicros());
@ -1635,7 +1644,7 @@ void TimelineEventFixedBufferRecorder::PrintTraceEvent(
TimelineEventFilter* filter) {
JSONArray events(js);
PrintJSONMeta(events);
PrintJSONEvents(&events, filter);
PrintJSONEvents(events, *filter);
}
#endif
@ -2048,6 +2057,38 @@ TimelineEventEndlessRecorder::TimelineEventEndlessRecorder()
TimelineEventEndlessRecorder::~TimelineEventEndlessRecorder() {}
#ifndef PRODUCT
void TimelineEventEndlessRecorder::PrintEventsCommon(
const TimelineEventFilter& filter,
std::function<void(const TimelineEvent&)> print_impl) {
MutexLocker ml(&lock_);
ResetTimeTracking();
for (TimelineEventBlock* current = head_; current != nullptr;
current = current->next()) {
if (!filter.IncludeBlock(current)) {
continue;
}
intptr_t length = current->length();
for (intptr_t i = 0; i < length; i++) {
TimelineEvent* event = current->At(i);
if (filter.IncludeEvent(event) &&
event->Within(filter.time_origin_micros(),
filter.time_extent_micros())) {
ReportTime(event->LowTime());
ReportTime(event->HighTime());
print_impl(*event);
}
}
}
}
void TimelineEventEndlessRecorder::PrintJSONEvents(
const JSONArray& events,
const TimelineEventFilter& filter) {
PrintEventsCommon(filter, [&events](const TimelineEvent& event) {
events.AddValue(&event);
});
}
void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js,
TimelineEventFilter* filter) {
JSONObject topLevel(js);
@ -2055,7 +2096,7 @@ void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js,
{
JSONArray events(&topLevel, "traceEvents");
PrintJSONMeta(events);
PrintJSONEvents(&events, filter);
PrintJSONEvents(events, *filter);
}
topLevel.AddPropertyTimeMicros("timeOriginMicros", TimeOriginMicros());
topLevel.AddPropertyTimeMicros("timeExtentMicros", TimeExtentMicros());
@ -2066,7 +2107,7 @@ void TimelineEventEndlessRecorder::PrintTraceEvent(
TimelineEventFilter* filter) {
JSONArray events(js);
PrintJSONMeta(events);
PrintJSONEvents(&events, filter);
PrintJSONEvents(events, *filter);
}
#endif
@ -2100,32 +2141,6 @@ TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() {
return block;
}
#ifndef PRODUCT
void TimelineEventEndlessRecorder::PrintJSONEvents(
JSONArray* events,
TimelineEventFilter* filter) {
MutexLocker ml(&lock_);
ResetTimeTracking();
for (TimelineEventBlock* current = head_; current != nullptr;
current = current->next()) {
if (!filter->IncludeBlock(current)) {
continue;
}
intptr_t length = current->length();
for (intptr_t i = 0; i < length; i++) {
TimelineEvent* event = current->At(i);
if (filter->IncludeEvent(event) &&
event->Within(filter->time_origin_micros(),
filter->time_extent_micros())) {
ReportTime(event->LowTime());
ReportTime(event->HighTime());
events->AddValue(event);
}
}
}
}
#endif
void TimelineEventEndlessRecorder::Clear() {
MutexLocker ml(&lock_);
TimelineEventBlock* current = head_;

View file

@ -5,6 +5,8 @@
#ifndef RUNTIME_VM_TIMELINE_H_
#define RUNTIME_VM_TIMELINE_H_
#include <functional>
#include "include/dart_tools_api.h"
#include "platform/atomic.h"
@ -832,7 +834,7 @@ class TimelineEventFilter : public ValueObject {
virtual ~TimelineEventFilter();
virtual bool IncludeBlock(TimelineEventBlock* block) {
virtual bool IncludeBlock(TimelineEventBlock* block) const {
if (block == nullptr) {
return false;
}
@ -840,7 +842,7 @@ class TimelineEventFilter : public ValueObject {
return !block->IsEmpty() && !block->in_use();
}
virtual bool IncludeEvent(TimelineEvent* event) {
virtual bool IncludeEvent(TimelineEvent* event) const {
if (event == nullptr) {
return false;
}
@ -862,7 +864,7 @@ class IsolateTimelineEventFilter : public TimelineEventFilter {
int64_t time_origin_micros = -1,
int64_t time_extent_micros = -1);
bool IncludeBlock(TimelineEventBlock* block) {
bool IncludeBlock(TimelineEventBlock* block) const final {
if (block == nullptr) {
return false;
}
@ -870,7 +872,7 @@ class IsolateTimelineEventFilter : public TimelineEventFilter {
return !block->IsEmpty() && !block->in_use();
}
bool IncludeEvent(TimelineEvent* event) {
bool IncludeEvent(TimelineEvent* event) const final {
return event->IsValid() && (event->isolate_id() == isolate_id_);
}
@ -957,8 +959,8 @@ class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
virtual ~TimelineEventFixedBufferRecorder();
#ifndef PRODUCT
void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter);
void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
#endif
intptr_t Size();
@ -971,7 +973,8 @@ class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
void Clear();
#ifndef PRODUCT
void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter);
void PrintJSONEvents(const JSONArray& array,
const TimelineEventFilter& filter);
#endif
VirtualMemory* memory_;
@ -979,6 +982,13 @@ class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
intptr_t capacity_;
intptr_t num_blocks_;
intptr_t block_cursor_;
private:
#if !defined(PRODUCT)
inline void PrintEventsCommon(
const TimelineEventFilter& filter,
std::function<void(const TimelineEvent&)> print_impl);
#endif // !defined(PRODUCT)
};
// A recorder that stores events in a buffer of fixed capacity. When the buffer
@ -1067,8 +1077,8 @@ class TimelineEventEndlessRecorder : public TimelineEventRecorder {
virtual ~TimelineEventEndlessRecorder();
#ifndef PRODUCT
void PrintJSON(JSONStream* js, TimelineEventFilter* filter);
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter);
void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
#endif
const char* name() const { return ENDLESS_RECORDER_NAME; }
@ -1082,13 +1092,21 @@ class TimelineEventEndlessRecorder : public TimelineEventRecorder {
void Clear();
#ifndef PRODUCT
void PrintJSONEvents(JSONArray* array, TimelineEventFilter* filter);
void PrintJSONEvents(const JSONArray& array,
const TimelineEventFilter& filter);
#endif
TimelineEventBlock* head_;
TimelineEventBlock* tail_;
intptr_t block_index_;
private:
#if !defined(PRODUCT)
inline void PrintEventsCommon(
const TimelineEventFilter& filter,
std::function<void(const TimelineEvent&)> print_impl);
#endif // !defined(PRODUCT)
friend class TimelineTestHelper;
};