Index: runtime/vm/timeline.cc |
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc |
index 51fcd71dcbb12f29393ff1591bc83b534cbd8e5d..2fc14408b2754e9b4dbbc306b08e3e8b45d8b7ca 100644 |
--- a/runtime/vm/timeline.cc |
+++ b/runtime/vm/timeline.cc |
@@ -40,38 +40,37 @@ void TimelineEvent::Reset() { |
} |
-int64_t TimelineEvent::AsyncBegin(TimelineStream* stream, const char* label) { |
- Init(kAsyncBegin, stream, label); |
+int64_t TimelineEvent::AsyncBegin(const char* label) { |
+ Init(kAsyncBegin, label); |
timestamp0_ = OS::GetCurrentTimeMicros(); |
- int64_t async_id = stream->GetNextSeq(); |
+ ASSERT(stream_ != NULL); |
+ int64_t async_id = stream_->GetNextSeq(); |
// Overload timestamp1_ with the async_id. |
timestamp1_ = async_id; |
return async_id; |
} |
-void TimelineEvent::AsyncInstant(TimelineStream* stream, |
- const char* label, |
+void TimelineEvent::AsyncInstant(const char* label, |
int64_t async_id) { |
- Init(kAsyncInstant, stream, label); |
+ Init(kAsyncInstant, label); |
timestamp0_ = OS::GetCurrentTimeMicros(); |
// Overload timestamp1_ with the async_id. |
timestamp1_ = async_id; |
} |
-void TimelineEvent::AsyncEnd(TimelineStream* stream, |
- const char* label, |
+void TimelineEvent::AsyncEnd(const char* label, |
int64_t async_id) { |
- Init(kAsyncEnd, stream, label); |
+ Init(kAsyncEnd, label); |
timestamp0_ = OS::GetCurrentTimeMicros(); |
// Overload timestamp1_ with the async_id. |
timestamp1_ = async_id; |
} |
-void TimelineEvent::DurationBegin(TimelineStream* stream, const char* label) { |
- Init(kDuration, stream, label); |
+void TimelineEvent::DurationBegin(const char* label) { |
+ Init(kDuration, label); |
timestamp0_ = OS::GetCurrentTimeMicros(); |
} |
@@ -81,18 +80,16 @@ void TimelineEvent::DurationEnd() { |
} |
-void TimelineEvent::Instant(TimelineStream* stream, |
- const char* label) { |
- Init(kInstant, stream, label); |
+void TimelineEvent::Instant(const char* label) { |
+ Init(kInstant, label); |
timestamp0_ = OS::GetCurrentTimeMicros(); |
} |
-void TimelineEvent::Duration(TimelineStream* stream, |
- const char* label, |
+void TimelineEvent::Duration(const char* label, |
int64_t start_micros, |
int64_t end_micros) { |
- Init(kDuration, stream, label); |
+ Init(kDuration, label); |
timestamp0_ = start_micros; |
timestamp1_ = end_micros; |
} |
@@ -142,6 +139,11 @@ void TimelineEvent::CopyArgument(intptr_t i, |
} |
+void TimelineEvent::Complete() { |
+ stream_->CompleteEvent(this); |
+} |
+ |
+ |
void TimelineEvent::FreeArguments() { |
if (arguments_ == NULL) { |
return; |
@@ -154,16 +156,20 @@ void TimelineEvent::FreeArguments() { |
arguments_length_ = 0; |
} |
+ |
+void TimelineEvent::StreamInit(TimelineStream* stream) { |
+ ASSERT(stream != NULL); |
+ stream_ = stream; |
+} |
+ |
+ |
void TimelineEvent::Init(EventType event_type, |
- TimelineStream* stream, |
const char* label) { |
- ASSERT(stream != NULL); |
ASSERT(label != NULL); |
set_event_type(event_type); |
timestamp0_ = 0; |
timestamp1_ = 0; |
thread_ = Thread::Current(); |
- stream_ = stream; |
label_ = label; |
FreeArguments(); |
} |
@@ -252,7 +258,7 @@ int64_t TimelineEvent::TimeDuration() const { |
TimelineStream::TimelineStream() |
- : buffer_(NULL), |
+ : recorder_(NULL), |
name_(NULL), |
enabled_(false), |
seq_(0) { |
@@ -265,22 +271,38 @@ void TimelineStream::Init(const char* name, bool enabled) { |
} |
-TimelineEvent* TimelineStream::RecordEvent(const Object& obj) { |
- if (!enabled_ || (buffer_ == NULL)) { |
+TimelineEvent* TimelineStream::StartEvent(const Object& obj) { |
+ if (!enabled_ || (recorder_ == NULL)) { |
return NULL; |
} |
ASSERT(name_ != NULL); |
- ASSERT(buffer_ != NULL); |
- return buffer_->RecordEvent(obj); |
+ ASSERT(recorder_ != NULL); |
+ TimelineEvent* event = recorder_->StartEvent(obj); |
+ if (event != NULL) { |
+ event->StreamInit(this); |
+ } |
+ return event; |
} |
-TimelineEvent* TimelineStream::RecordEvent() { |
- if (!enabled_ || (buffer_ == NULL)) { |
+TimelineEvent* TimelineStream::StartEvent() { |
+ if (!enabled_ || (recorder_ == NULL)) { |
return NULL; |
} |
ASSERT(name_ != NULL); |
- return buffer_->RecordEvent(); |
+ TimelineEvent* event = recorder_->StartEvent(); |
+ if (event != NULL) { |
+ event->StreamInit(this); |
+ } |
+ return event; |
+} |
+ |
+ |
+void TimelineStream::CompleteEvent(TimelineEvent* event) { |
+ if (!enabled_ || (recorder_ == NULL)) { |
+ return; |
+ } |
+ recorder_->CompleteEvent(event); |
} |
@@ -314,12 +336,60 @@ void TimelineDurationScope::FormatArgument(intptr_t i, |
} |
-intptr_t TimelineEventBuffer::SizeForCapacity(intptr_t capacity) { |
+TimelineEventRecorder::TimelineEventRecorder() { |
+} |
+ |
+ |
+void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { |
+ Isolate* isolate = Isolate::Current(); |
+ JSONObject obj(events); |
+ int64_t pid = GetPid(isolate); |
+ obj.AddProperty("ph", "M"); |
+ obj.AddProperty64("pid", pid); |
+ obj.AddProperty("name", "process_name"); |
+ { |
+ JSONObject args(&obj, "args"); |
+ args.AddProperty("name", isolate->debugger_name()); |
+ } |
+} |
+ |
+ |
+void TimelineEventRecorder::WriteTo(const char* directory) { |
+ Isolate* isolate = Isolate::Current(); |
+ |
+ Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
+ Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
+ Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
+ if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { |
+ return; |
+ } |
+ |
+ JSONStream js; |
+ PrintJSON(&js); |
+ |
+ const char* format = "%s/dart-timeline-%" Pd "-%" Pd ".json"; |
+ intptr_t pid = OS::ProcessId(); |
+ intptr_t len = OS::SNPrint(NULL, 0, format, |
+ directory, pid, isolate->main_port()); |
+ char* filename = isolate->current_zone()->Alloc<char>(len + 1); |
+ OS::SNPrint(filename, len + 1, format, |
+ directory, pid, isolate->main_port()); |
+ void* file = (*file_open)(filename, true); |
+ if (file == NULL) { |
+ OS::Print("Failed to write timeline file: %s\n", filename); |
+ return; |
+ } |
+ (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); |
+ (*file_close)(file); |
+} |
+ |
+ |
+intptr_t TimelineEventRingRecorder::SizeForCapacity(intptr_t capacity) { |
return sizeof(TimelineEvent) * capacity; |
} |
-TimelineEventBuffer::TimelineEventBuffer(intptr_t capacity) |
+TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) |
: events_(NULL), |
event_objects_(Array::null()), |
cursor_(0), |
@@ -329,7 +399,7 @@ TimelineEventBuffer::TimelineEventBuffer(intptr_t capacity) |
// 64-bit: 393,216 bytes per isolate. |
// NOTE: Internal isolates (vm and service) do not have a timeline |
// event buffer. |
- OS::Print("TimelineEventBuffer is %" Pd " bytes (%" Pd " events)\n", |
+ OS::Print("TimelineEventRingRecorder is %" Pd " bytes (%" Pd " events)\n", |
SizeForCapacity(capacity), |
capacity); |
} |
@@ -340,7 +410,7 @@ TimelineEventBuffer::TimelineEventBuffer(intptr_t capacity) |
} |
-TimelineEventBuffer::~TimelineEventBuffer() { |
+TimelineEventRingRecorder::~TimelineEventRingRecorder() { |
for (intptr_t i = 0; i < capacity_; i++) { |
// Clear any extra data. |
events_[i].Reset(); |
@@ -350,21 +420,7 @@ TimelineEventBuffer::~TimelineEventBuffer() { |
} |
-void TimelineEventBuffer::PrintJSONMeta(JSONArray* events) const { |
- Isolate* isolate = Isolate::Current(); |
- JSONObject obj(events); |
- int64_t pid = GetPid(isolate); |
- obj.AddProperty("ph", "M"); |
- obj.AddProperty64("pid", pid); |
- obj.AddProperty("name", "process_name"); |
- { |
- JSONObject args(&obj, "args"); |
- args.AddProperty("name", isolate->debugger_name()); |
- } |
-} |
- |
- |
-void TimelineEventBuffer::PrintJSONEvents(JSONArray* events) const { |
+void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const { |
for (intptr_t i = 0; i < capacity_; i++) { |
if (events_[i].IsValid()) { |
events->AddValue(&events_[i]); |
@@ -373,7 +429,7 @@ void TimelineEventBuffer::PrintJSONEvents(JSONArray* events) const { |
} |
-void TimelineEventBuffer::PrintJSON(JSONStream* js) const { |
+void TimelineEventRingRecorder::PrintJSON(JSONStream* js) const { |
JSONObject topLevel(js); |
topLevel.AddProperty("type", "_Timeline"); |
{ |
@@ -384,48 +440,19 @@ void TimelineEventBuffer::PrintJSON(JSONStream* js) const { |
} |
-void TimelineEventBuffer::WriteTo(const char* directory) { |
- Isolate* isolate = Isolate::Current(); |
- |
- Dart_FileOpenCallback file_open = Isolate::file_open_callback(); |
- Dart_FileWriteCallback file_write = Isolate::file_write_callback(); |
- Dart_FileCloseCallback file_close = Isolate::file_close_callback(); |
- if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { |
- return; |
- } |
- |
- JSONStream js; |
- PrintJSON(&js); |
- |
- const char* format = "%s/dart-timeline-%" Pd "-%" Pd ".json"; |
- intptr_t pid = OS::ProcessId(); |
- intptr_t len = OS::SNPrint(NULL, 0, format, |
- directory, pid, isolate->main_port()); |
- char* filename = isolate->current_zone()->Alloc<char>(len + 1); |
- OS::SNPrint(filename, len + 1, format, |
- directory, pid, isolate->main_port()); |
- void* file = (*file_open)(filename, true); |
- if (file == NULL) { |
- OS::Print("Failed to write timeline file: %s\n", filename); |
- return; |
- } |
- (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); |
- (*file_close)(file); |
-} |
- |
- |
-intptr_t TimelineEventBuffer::GetNextIndex() { |
+intptr_t TimelineEventRingRecorder::GetNextIndex() { |
uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); |
return cursor % capacity_; |
} |
-void TimelineEventBuffer::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
+void TimelineEventRingRecorder::VisitObjectPointers( |
+ ObjectPointerVisitor* visitor) { |
visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_)); |
} |
-TimelineEvent* TimelineEventBuffer::RecordEvent(const Object& obj) { |
+TimelineEvent* TimelineEventRingRecorder::StartEvent(const Object& obj) { |
ASSERT(events_ != NULL); |
uintptr_t index = GetNextIndex(); |
const Array& event_objects = Array::Handle(event_objects_); |
@@ -434,10 +461,57 @@ TimelineEvent* TimelineEventBuffer::RecordEvent(const Object& obj) { |
} |
-TimelineEvent* TimelineEventBuffer::RecordEvent() { |
+TimelineEvent* TimelineEventRingRecorder::StartEvent() { |
ASSERT(events_ != NULL); |
uintptr_t index = GetNextIndex(); |
return &events_[index]; |
} |
+void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { |
+ ASSERT(events_ != NULL); |
+ // no-op. |
+} |
+ |
+ |
+TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { |
+} |
+ |
+ |
+TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { |
+} |
+ |
+ |
+void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) const { |
+ JSONObject topLevel(js); |
+ topLevel.AddProperty("type", "_Timeline"); |
+ { |
+ JSONArray events(&topLevel, "traceEvents"); |
+ PrintJSONMeta(&events); |
+ } |
+} |
+ |
+void TimelineEventStreamingRecorder::VisitObjectPointers( |
+ ObjectPointerVisitor* visitor) { |
+ // no-op. |
+} |
+ |
+ |
+TimelineEvent* TimelineEventStreamingRecorder::StartEvent( |
+ const Object& object) { |
+ // The streaming recorder does not track Dart objects. |
+ return StartEvent(); |
+} |
+ |
+ |
+TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { |
+ TimelineEvent* event = new TimelineEvent(); |
+ return event; |
+} |
+ |
+ |
+void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { |
+ StreamEvent(event); |
+ delete event; |
+} |
+ |
} // namespace dart |