Index: runtime/vm/timeline.h |
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h |
index d248c40950298f75d529c6dd8b50e2e5ccb3cfb2..81977ad06474bf772e876f9c86667cec317b9182 100644 |
--- a/runtime/vm/timeline.h |
+++ b/runtime/vm/timeline.h |
@@ -14,9 +14,10 @@ class Object; |
class RawArray; |
class Thread; |
class TimelineEvent; |
-class TimelineEventBuffer; |
+class TimelineEventRecorder; |
class TimelineStream; |
+// You should get a |TimelineEvent| from a |TimelineStream|. |
class TimelineEvent { |
public: |
// Keep in sync with StateBits below. |
@@ -41,22 +42,19 @@ class TimelineEvent { |
// Marks the beginning of an asynchronous operation. |
// Returns |async_id| which must be passed to |AsyncInstant| and |AsyncEnd|. |
- int64_t AsyncBegin(TimelineStream* stream, const char* label); |
+ int64_t AsyncBegin(const char* label); |
// Marks an instantaneous event associated with |async_id|. |
- void AsyncInstant(TimelineStream* stream, |
- const char* label, |
+ void AsyncInstant(const char* label, |
int64_t async_id); |
// Marks the end of an asynchronous operation associated with |async_id|. |
- void AsyncEnd(TimelineStream* stream, |
- const char* label, |
+ void AsyncEnd(const char* label, |
int64_t async_id); |
- void DurationBegin(TimelineStream* stream, const char* label); |
+ void DurationBegin(const char* label); |
void DurationEnd(); |
- void Instant(TimelineStream* stream, const char* label); |
+ void Instant(const char* label); |
- void Duration(TimelineStream* stream, |
- const char* label, |
+ void Duration(const char* label, |
int64_t start_micros, |
int64_t end_micros); |
@@ -70,6 +68,10 @@ class TimelineEvent { |
void FormatArgument(intptr_t i, |
const char* name, |
const char* fmt, ...) PRINTF_ATTRIBUTE(4, 5); |
+ |
+ // Mandatory to call when this event is completely filled out. |
+ void Complete(); |
+ |
EventType event_type() const { |
return EventTypeField::decode(state_); |
} |
@@ -97,7 +99,8 @@ class TimelineEvent { |
void FreeArguments(); |
- void Init(EventType event_type, TimelineStream* stream, const char* label); |
+ void StreamInit(TimelineStream* stream); |
+ void Init(EventType event_type, const char* label); |
void set_event_type(EventType event_type) { |
state_ = EventTypeField::update(event_type, state_); |
@@ -111,6 +114,8 @@ class TimelineEvent { |
class EventTypeField : public BitField<EventType, kEventTypeBit, 4> {}; |
+ friend class TimelineTestHelper; |
+ friend class TimelineStream; |
DISALLOW_COPY_AND_ASSIGN(TimelineEvent); |
}; |
@@ -135,28 +140,30 @@ class TimelineStream { |
enabled_ = enabled; |
} |
- TimelineEventBuffer* buffer() const { |
- return buffer_; |
+ TimelineEventRecorder* recorder() const { |
+ return recorder_; |
} |
- void set_buffer(TimelineEventBuffer* buffer) { |
- buffer_ = buffer; |
+ // TODO(johnmccutchan): Disallow setting recorder after Init? |
+ void set_recorder(TimelineEventRecorder* recorder) { |
+ recorder_ = recorder; |
} |
// Records an event. Will return |NULL| if not enabled. The returned |
// |TimelineEvent| is in an undefined state and must be initialized. |
// |obj| is associated with the returned |TimelineEvent|. |
- TimelineEvent* RecordEvent(const Object& obj); |
+ TimelineEvent* StartEvent(const Object& obj); |
// Records an event. Will return |NULL| if not enabled. The returned |
// |TimelineEvent| is in an undefined state and must be initialized. |
- TimelineEvent* RecordEvent(); |
+ TimelineEvent* StartEvent(); |
+ |
+ void CompleteEvent(TimelineEvent* event); |
int64_t GetNextSeq(); |
private: |
- // Buffer of TimelineEvents. |
- TimelineEventBuffer* buffer_; |
+ TimelineEventRecorder* recorder_; |
const char* name_; |
bool enabled_; |
int64_t seq_; |
@@ -190,11 +197,11 @@ class TimelineDurationScope : public StackResource { |
TimelineStream* stream, |
const char* label) |
: StackResource(isolate) { |
- event_ = stream->RecordEvent(); |
+ event_ = stream->StartEvent(); |
if (event_ == NULL) { |
return; |
} |
- event_->DurationBegin(stream, label); |
+ event_->DurationBegin(label); |
} |
bool enabled() const { |
@@ -231,6 +238,7 @@ class TimelineDurationScope : public StackResource { |
return; |
} |
event_->DurationEnd(); |
+ event_->Complete(); |
} |
private: |
@@ -238,37 +246,83 @@ class TimelineDurationScope : public StackResource { |
}; |
-class TimelineEventBuffer { |
+// Recorder of |TimelineEvent|s. |
+class TimelineEventRecorder { |
+ public: |
+ TimelineEventRecorder(); |
+ virtual ~TimelineEventRecorder() {} |
+ |
+ // Interface method(s) which must be implemented. |
+ virtual void PrintJSON(JSONStream* js) const = 0; |
+ |
+ void WriteTo(const char* directory); |
+ |
+ protected: |
+ // Interface method(s) which must be implemented. |
+ virtual void VisitObjectPointers(ObjectPointerVisitor* visitor) = 0; |
+ virtual TimelineEvent* StartEvent(const Object& object) = 0; |
+ virtual TimelineEvent* StartEvent() = 0; |
+ virtual void CompleteEvent(TimelineEvent* event) = 0; |
+ |
+ // Utility method(s). |
+ void PrintJSONMeta(JSONArray* array) const; |
+ |
+ friend class TimelineStream; |
+ friend class Isolate; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(TimelineEventRecorder); |
+}; |
+ |
+ |
+// A recorder that stores events in a ring buffer of fixed capacity. |
+class TimelineEventRingRecorder : public TimelineEventRecorder { |
public: |
static const intptr_t kDefaultCapacity = 8192; |
static intptr_t SizeForCapacity(intptr_t capacity); |
- explicit TimelineEventBuffer(intptr_t capacity = kDefaultCapacity); |
- ~TimelineEventBuffer(); |
+ explicit TimelineEventRingRecorder(intptr_t capacity = kDefaultCapacity); |
+ ~TimelineEventRingRecorder(); |
void PrintJSON(JSONStream* js) const; |
- void WriteTo(const char* directory); |
+ protected: |
+ void VisitObjectPointers(ObjectPointerVisitor* visitor); |
+ TimelineEvent* StartEvent(const Object& object); |
+ TimelineEvent* StartEvent(); |
+ void CompleteEvent(TimelineEvent* event); |
+ |
+ void PrintJSONEvents(JSONArray* array) const; |
+ |
+ intptr_t GetNextIndex(); |
- private: |
// events_[i] and event_objects_[i] are indexed together. |
TimelineEvent* events_; |
RawArray* event_objects_; |
uintptr_t cursor_; |
intptr_t capacity_; |
+}; |
- void PrintJSONMeta(JSONArray* array) const; |
- void PrintJSONEvents(JSONArray* array) const; |
- intptr_t GetNextIndex(); |
- void VisitObjectPointers(ObjectPointerVisitor* visitor); |
- TimelineEvent* RecordEvent(const Object& obj); |
- TimelineEvent* RecordEvent(); |
+// An abstract recorder that calls |StreamEvent| whenever an event is complete. |
+// This recorder does not track Dart objects. |
+class TimelineEventStreamingRecorder : public TimelineEventRecorder { |
+ public: |
+ TimelineEventStreamingRecorder(); |
+ ~TimelineEventStreamingRecorder(); |
- friend class TimelineStream; |
- friend class Isolate; |
- DISALLOW_COPY_AND_ASSIGN(TimelineEventBuffer); |
+ void PrintJSON(JSONStream* js) const; |
+ |
+ // Called when |event| is ready to be streamed. It is unsafe to keep a |
+ // reference to |event| as it may be freed as soon as this function returns. |
+ virtual void StreamEvent(TimelineEvent* event) = 0; |
+ |
+ protected: |
+ void VisitObjectPointers(ObjectPointerVisitor* visitor); |
+ TimelineEvent* StartEvent(const Object& object); |
+ TimelineEvent* StartEvent(); |
+ void CompleteEvent(TimelineEvent* event); |
}; |
} // namespace dart |