[vm] Reduce duplication in timeline.cc
Place serialization code shared between fixed buffer and endless recorders into an abstract superclass. TEST=ci Change-Id: I643e606ec144b06406375b796f4f2b369b657d3c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/417200 Reviewed-by: Derek Xu <derekx@google.com> Commit-Queue: Slava Egorov <vegorov@google.com>
This commit is contained in:
committed by
Commit Queue
parent
0dd150bd27
commit
6659976329
+44
-105
@@ -669,7 +669,7 @@ void TimelineEvent::Init(EventType event_type, const char* label) {
|
||||
}
|
||||
|
||||
bool TimelineEvent::Within(int64_t time_origin_micros,
|
||||
int64_t time_extent_micros) {
|
||||
int64_t time_extent_micros) const {
|
||||
if ((time_origin_micros == -1) || (time_extent_micros == -1)) {
|
||||
// No time range specified.
|
||||
return true;
|
||||
@@ -1610,9 +1610,8 @@ intptr_t TimelineEventFixedBufferRecorder::Size() {
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void TimelineEventFixedBufferRecorder::PrintEventsCommon(
|
||||
const TimelineEventFilter& filter,
|
||||
std::function<void(const TimelineEvent&)>&& print_impl) {
|
||||
void TimelineEventFixedBufferRecorder::ForEachNonEmptyBlock(
|
||||
std::function<void(const TimelineEventBlock&)>&& handle_block) {
|
||||
// Acquire the recorder's lock to prevent the reclaimed blocks from being
|
||||
// handed out again until the trace has been serialized.
|
||||
MutexLocker ml(&lock_);
|
||||
@@ -1629,20 +1628,30 @@ void TimelineEventFixedBufferRecorder::PrintEventsCommon(
|
||||
if (!block->ContainsEventsThatCanBeSerializedLocked()) {
|
||||
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())) {
|
||||
ReportTime(event->LowTime());
|
||||
ReportTime(event->HighTime());
|
||||
print_impl(*event);
|
||||
}
|
||||
}
|
||||
handle_block(*block);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineEventFixedBufferRecorder::PrintJSONEvents(
|
||||
void TimelineEventBufferedRecorder::PrintEventsCommon(
|
||||
const TimelineEventFilter& filter,
|
||||
std::function<void(const TimelineEvent&)>&& print_impl) {
|
||||
ForEachNonEmptyBlock(
|
||||
[this, &filter, print_impl = std::move(print_impl)](auto& block) {
|
||||
for (intptr_t event_idx = 0, length = block.length();
|
||||
event_idx < length; event_idx++) {
|
||||
auto event = block.At(event_idx);
|
||||
if (filter.IncludeEvent(event) &&
|
||||
event->Within(filter.time_origin_micros(),
|
||||
filter.time_extent_micros())) {
|
||||
ReportTime(event->LowTime());
|
||||
ReportTime(event->HighTime());
|
||||
print_impl(*event);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void TimelineEventBufferedRecorder::PrintJSONEvents(
|
||||
const JSONArray& events,
|
||||
const TimelineEventFilter& filter) {
|
||||
PrintEventsCommon(filter, [&events](const TimelineEvent& event) {
|
||||
@@ -1704,7 +1713,7 @@ inline void PrintPerfettoEventCallbackBody(
|
||||
heap_buffered_packet->Reset();
|
||||
}
|
||||
|
||||
void TimelineEventFixedBufferRecorder::PrintPerfettoEvents(
|
||||
void TimelineEventBufferedRecorder::PrintPerfettoEvents(
|
||||
JSONBase64String* jsonBase64String,
|
||||
const TimelineEventFilter& filter) {
|
||||
PrintEventsCommon(
|
||||
@@ -1721,8 +1730,8 @@ void TimelineEventFixedBufferRecorder::PrintPerfettoEvents(
|
||||
}
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
|
||||
void TimelineEventFixedBufferRecorder::PrintJSON(JSONStream* js,
|
||||
TimelineEventFilter* filter) {
|
||||
void TimelineEventBufferedRecorder::PrintJSON(JSONStream* js,
|
||||
TimelineEventFilter* filter) {
|
||||
JSONObject topLevel(js);
|
||||
topLevel.AddProperty("type", "Timeline");
|
||||
{
|
||||
@@ -1734,30 +1743,26 @@ void TimelineEventFixedBufferRecorder::PrintJSON(JSONStream* js,
|
||||
topLevel.AddPropertyTimeMicros("timeExtentMicros", TimeExtentMicros());
|
||||
}
|
||||
|
||||
#define PRINT_PERFETTO_TIMELINE_BODY \
|
||||
JSONObject jsobj_topLevel(js); \
|
||||
jsobj_topLevel.AddProperty("type", "PerfettoTimeline"); \
|
||||
\
|
||||
js->AppendSerializedObject("\"trace\":"); \
|
||||
{ \
|
||||
JSONBase64String jsonBase64String(js); \
|
||||
PrintPerfettoMeta(&jsonBase64String); \
|
||||
PrintPerfettoEvents(&jsonBase64String, filter); \
|
||||
} \
|
||||
\
|
||||
jsobj_topLevel.AddPropertyTimeMicros("timeOriginMicros", \
|
||||
TimeOriginMicros()); \
|
||||
jsobj_topLevel.AddPropertyTimeMicros("timeExtentMicros", TimeExtentMicros());
|
||||
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
void TimelineEventFixedBufferRecorder::PrintPerfettoTimeline(
|
||||
void TimelineEventBufferedRecorder::PrintPerfettoTimeline(
|
||||
JSONStream* js,
|
||||
const TimelineEventFilter& filter) {
|
||||
PRINT_PERFETTO_TIMELINE_BODY
|
||||
JSONObject jsobj_topLevel(js);
|
||||
jsobj_topLevel.AddProperty("type", "PerfettoTimeline");
|
||||
|
||||
js->AppendSerializedObject("\"trace\":");
|
||||
{
|
||||
JSONBase64String jsonBase64String(js);
|
||||
PrintPerfettoMeta(&jsonBase64String);
|
||||
PrintPerfettoEvents(&jsonBase64String, filter);
|
||||
}
|
||||
|
||||
jsobj_topLevel.AddPropertyTimeMicros("timeOriginMicros", TimeOriginMicros());
|
||||
jsobj_topLevel.AddPropertyTimeMicros("timeExtentMicros", TimeExtentMicros());
|
||||
}
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
|
||||
void TimelineEventFixedBufferRecorder::PrintTraceEvent(
|
||||
void TimelineEventBufferedRecorder::PrintTraceEvent(
|
||||
JSONStream* js,
|
||||
TimelineEventFilter* filter) {
|
||||
JSONArray events(js);
|
||||
@@ -2225,9 +2230,8 @@ TimelineEventEndlessRecorder::~TimelineEventEndlessRecorder() {
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void TimelineEventEndlessRecorder::PrintEventsCommon(
|
||||
const TimelineEventFilter& filter,
|
||||
std::function<void(const TimelineEvent&)>&& print_impl) {
|
||||
void TimelineEventEndlessRecorder::ForEachNonEmptyBlock(
|
||||
std::function<void(const TimelineEventBlock&)>&& handle_block) {
|
||||
// Acquire the recorder's lock to prevent the reclaimed blocks from being
|
||||
// handed out again until the trace has been serialized.
|
||||
MutexLocker ml(&lock_);
|
||||
@@ -2238,74 +2242,9 @@ void TimelineEventEndlessRecorder::PrintEventsCommon(
|
||||
if (!current->ContainsEventsThatCanBeSerializedLocked()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
handle_block(*current);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineEventEndlessRecorder::PrintJSONEvents(
|
||||
const JSONArray& events,
|
||||
const TimelineEventFilter& filter) {
|
||||
PrintEventsCommon(filter, [&events](const TimelineEvent& event) {
|
||||
events.AddValue(&event);
|
||||
});
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
void TimelineEventEndlessRecorder::PrintPerfettoEvents(
|
||||
JSONBase64String* jsonBase64String,
|
||||
const TimelineEventFilter& filter) {
|
||||
PrintEventsCommon(
|
||||
filter, [this, &jsonBase64String](const TimelineEvent& event) {
|
||||
PrintPerfettoEventCallbackBody(
|
||||
&packet(), event,
|
||||
[&jsonBase64String](
|
||||
protozero::HeapBuffered<perfetto::protos::pbzero::TracePacket>*
|
||||
packet) {
|
||||
perfetto_utils::AppendPacketToJSONBase64String(jsonBase64String,
|
||||
packet);
|
||||
});
|
||||
});
|
||||
}
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
|
||||
void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js,
|
||||
TimelineEventFilter* filter) {
|
||||
JSONObject topLevel(js);
|
||||
topLevel.AddProperty("type", "Timeline");
|
||||
{
|
||||
JSONArray events(&topLevel, "traceEvents");
|
||||
PrintJSONMeta(events);
|
||||
PrintJSONEvents(events, *filter);
|
||||
}
|
||||
topLevel.AddPropertyTimeMicros("timeOriginMicros", TimeOriginMicros());
|
||||
topLevel.AddPropertyTimeMicros("timeExtentMicros", TimeExtentMicros());
|
||||
}
|
||||
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
void TimelineEventEndlessRecorder::PrintPerfettoTimeline(
|
||||
JSONStream* js,
|
||||
const TimelineEventFilter& filter) {
|
||||
PRINT_PERFETTO_TIMELINE_BODY
|
||||
}
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
|
||||
void TimelineEventEndlessRecorder::PrintTraceEvent(
|
||||
JSONStream* js,
|
||||
TimelineEventFilter* filter) {
|
||||
JSONArray events(js);
|
||||
PrintJSONMeta(events);
|
||||
PrintJSONEvents(events, *filter);
|
||||
}
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() {
|
||||
|
||||
+37
-46
@@ -533,7 +533,7 @@ class TimelineEvent {
|
||||
}
|
||||
}
|
||||
|
||||
bool Within(int64_t time_origin_micros, int64_t time_extent_micros);
|
||||
bool Within(int64_t time_origin_micros, int64_t time_extent_micros) const;
|
||||
|
||||
void set_owns_label(bool owns_label) {
|
||||
state_ = OwnsLabelBit::update(owns_label, state_);
|
||||
@@ -846,7 +846,7 @@ class TimelineEventFilter : public ValueObject {
|
||||
|
||||
virtual ~TimelineEventFilter();
|
||||
|
||||
virtual bool IncludeEvent(TimelineEvent* event) const {
|
||||
virtual bool IncludeEvent(const TimelineEvent* event) const {
|
||||
if (event == nullptr) {
|
||||
return false;
|
||||
}
|
||||
@@ -868,7 +868,7 @@ class IsolateTimelineEventFilter : public TimelineEventFilter {
|
||||
int64_t time_origin_micros = -1,
|
||||
int64_t time_extent_micros = -1);
|
||||
|
||||
bool IncludeEvent(TimelineEvent* event) const final {
|
||||
bool IncludeEvent(const TimelineEvent* event) const final {
|
||||
return event->IsValid() && (event->isolate_id() == isolate_id_);
|
||||
}
|
||||
|
||||
@@ -977,14 +977,9 @@ class TimelineEventRecorder : public MallocAllocated {
|
||||
DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder);
|
||||
};
|
||||
|
||||
// An abstract recorder that stores events in a buffer of fixed capacity.
|
||||
class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
|
||||
// An abstract recorder that buffers recorded events.
|
||||
class TimelineEventBufferedRecorder : public TimelineEventRecorder {
|
||||
public:
|
||||
static constexpr intptr_t kDefaultCapacity = 32 * KB; // Number of events.
|
||||
|
||||
explicit TimelineEventFixedBufferRecorder(intptr_t capacity);
|
||||
virtual ~TimelineEventFixedBufferRecorder();
|
||||
|
||||
#ifndef PRODUCT
|
||||
void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
@@ -992,7 +987,32 @@ class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
|
||||
const TimelineEventFilter& filter) final;
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
|
||||
|
||||
private:
|
||||
virtual void ForEachNonEmptyBlock(
|
||||
std::function<void(const TimelineEventBlock&)>&& handle_block) = 0;
|
||||
|
||||
void PrintJSONEvents(const JSONArray& array,
|
||||
const TimelineEventFilter& filter);
|
||||
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
void PrintPerfettoEvents(JSONBase64String* jsonBase64String,
|
||||
const TimelineEventFilter& filter);
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
|
||||
void PrintEventsCommon(
|
||||
const TimelineEventFilter& filter,
|
||||
std::function<void(const TimelineEvent&)>&& print_impl);
|
||||
#endif // !defined(PRODUCT)
|
||||
};
|
||||
|
||||
// An abstract recorder that stores events in a buffer of fixed capacity.
|
||||
class TimelineEventFixedBufferRecorder : public TimelineEventBufferedRecorder {
|
||||
public:
|
||||
static constexpr intptr_t kDefaultCapacity = 32 * KB; // Number of events.
|
||||
|
||||
explicit TimelineEventFixedBufferRecorder(intptr_t capacity);
|
||||
virtual ~TimelineEventFixedBufferRecorder();
|
||||
|
||||
intptr_t Size();
|
||||
|
||||
@@ -1004,15 +1024,6 @@ class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
|
||||
intptr_t FindOldestBlockIndexLocked() const;
|
||||
void ClearLocked();
|
||||
|
||||
#ifndef PRODUCT
|
||||
void PrintJSONEvents(const JSONArray& array,
|
||||
const TimelineEventFilter& filter);
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
void PrintPerfettoEvents(JSONBase64String* jsonBase64String,
|
||||
const TimelineEventFilter& filter);
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
VirtualMemory* memory_;
|
||||
TimelineEventBlock* blocks_;
|
||||
intptr_t capacity_;
|
||||
@@ -1020,10 +1031,9 @@ class TimelineEventFixedBufferRecorder : public TimelineEventRecorder {
|
||||
intptr_t block_cursor_;
|
||||
|
||||
private:
|
||||
#if !defined(PRODUCT)
|
||||
inline void PrintEventsCommon(
|
||||
const TimelineEventFilter& filter,
|
||||
std::function<void(const TimelineEvent&)>&& print_impl);
|
||||
#ifndef PRODUCT
|
||||
void ForEachNonEmptyBlock(
|
||||
std::function<void(const TimelineEventBlock&)>&& handle_block) final;
|
||||
#endif // !defined(PRODUCT)
|
||||
};
|
||||
|
||||
@@ -1109,20 +1119,11 @@ class TimelineEventNopRecorder : public TimelineEventCallbackRecorder {
|
||||
// A recorder that stores events in chains of blocks of events.
|
||||
// NOTE: This recorder will continue to allocate blocks until it exhausts
|
||||
// memory.
|
||||
class TimelineEventEndlessRecorder : public TimelineEventRecorder {
|
||||
class TimelineEventEndlessRecorder : public TimelineEventBufferedRecorder {
|
||||
public:
|
||||
TimelineEventEndlessRecorder();
|
||||
virtual ~TimelineEventEndlessRecorder();
|
||||
|
||||
#ifndef PRODUCT
|
||||
void PrintJSON(JSONStream* js, TimelineEventFilter* filter) final;
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
void PrintPerfettoTimeline(JSONStream* js,
|
||||
const TimelineEventFilter& filter) final;
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
void PrintTraceEvent(JSONStream* js, TimelineEventFilter* filter) final;
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
const char* name() const { return ENDLESS_RECORDER_NAME; }
|
||||
intptr_t Size() { return block_index_ * sizeof(TimelineEventBlock); }
|
||||
|
||||
@@ -1133,24 +1134,14 @@ class TimelineEventEndlessRecorder : public TimelineEventRecorder {
|
||||
TimelineEventBlock* GetHeadBlockLocked();
|
||||
void ClearLocked();
|
||||
|
||||
#ifndef PRODUCT
|
||||
void PrintJSONEvents(const JSONArray& array,
|
||||
const TimelineEventFilter& filter);
|
||||
#if defined(SUPPORT_PERFETTO)
|
||||
void PrintPerfettoEvents(JSONBase64String* jsonBase64String,
|
||||
const TimelineEventFilter& filter);
|
||||
#endif // defined(SUPPORT_PERFETTO)
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
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);
|
||||
#ifndef PRODUCT
|
||||
void ForEachNonEmptyBlock(
|
||||
std::function<void(const TimelineEventBlock&)>&& handle_block) final;
|
||||
#endif // !defined(PRODUCT)
|
||||
|
||||
friend class TimelineTestHelper;
|
||||
|
||||
Reference in New Issue
Block a user