Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Unified Diff: runtime/vm/timeline.cc

Issue 2315353004: Record Timeline to Android Systrace (Closed)
Patch Set: Add TimelineEventSystraceRecorder Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: runtime/vm/timeline.cc
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 7e9ba2d179c9ec86ad6615ce49555b26a69e4eb9..01d56e58c99f36c4d41e3f9bb233dc596faa7ffb 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -4,6 +4,7 @@
#ifndef PRODUCT
+#include <fcntl.h>
#include <cstdlib>
#include "vm/atomic.h"
@@ -20,6 +21,7 @@ namespace dart {
DEFINE_FLAG(bool, complete_timeline, false, "Record the complete timeline");
DEFINE_FLAG(bool, startup_timeline, false, "Record the startup timeline");
+DEFINE_FLAG(bool, systrace_timeline, false, "Record the timeline to systrace");
DEFINE_FLAG(bool, trace_timeline, false,
"Trace timeline backend");
DEFINE_FLAG(bool, trace_timeline_analysis, false,
@@ -86,9 +88,19 @@ static TimelineEventRecorder* CreateTimelineRecorder() {
(FLAG_timeline_dir != NULL) || FLAG_timing || FLAG_complete_timeline;
const bool use_startup_recorder = FLAG_startup_timeline;
+ const bool use_systrace_recorder = FLAG_systrace_timeline;
const char* flag = FLAG_timeline_recorder;
+ if (use_systrace_recorder || (flag != NULL)) {
+ if (use_systrace_recorder || (strcmp("systrace", flag) == 0)) {
Chinmay 2016/09/08 17:58:11 Maybe these two if statements can be rewritten as
Cutch 2016/09/08 18:06:10 Acknowledged.
+ if (FLAG_trace_timeline) {
+ THR_Print("Using the Systrace timeline recorder.\n");
+ }
+ return new TimelineEventSystraceRecorder();
+ }
+ }
+
if (use_endless_recorder || (flag != NULL)) {
if (use_endless_recorder || (strcmp("endless", flag) == 0)) {
if (FLAG_trace_timeline) {
@@ -497,6 +509,39 @@ void TimelineEvent::StealArguments(intptr_t arguments_length,
}
+intptr_t TimelineEvent::PrintSystrace(char* buffer, intptr_t buffer_size) {
+ ASSERT(buffer != NULL);
+ ASSERT(buffer_size > 0);
+ buffer[0] = '\0';
+ intptr_t length = 0;
+ int64_t pid = OS::ProcessId();
+ switch (event_type()) {
+ case kBegin: {
+ length = snprintf(buffer, buffer_size, "B|%" Pd64 "|%s", pid, label());
+ }
+ break;
+ case kEnd: {
+ length = snprintf(buffer, buffer_size, "E");
+ }
+ break;
+ case kCounter: {
+ if (arguments_length_ > 0) {
+ // We only report the first counter value.
+ length = snprintf(buffer, buffer_size,
+ "C|%" Pd64 "|%s|%s",
+ pid,
+ label(),
+ arguments_[0].value);
+ }
+ }
+ default:
+ // Ignore event types that we cannot serialize to the Systrace format.
+ break;
+ }
+ return length;
+}
+
+
void TimelineEvent::Complete() {
TimelineEventRecorder* recorder = Timeline::recorder();
if (recorder != NULL) {
@@ -1354,6 +1399,60 @@ void TimelineEventFixedBufferRecorder::CompleteEvent(TimelineEvent* event) {
}
+static const char* kSystracePath = "/sys/kernel/debug/tracing/trace_marker";
+
+
+TimelineEventSystraceRecorder::TimelineEventSystraceRecorder(intptr_t capacity)
+ : TimelineEventFixedBufferRecorder(capacity),
+ systrace_fd_(-1) {
+ systrace_fd_ = open(kSystracePath, O_WRONLY);
+ if ((systrace_fd_ < 0) && FLAG_trace_timeline) {
+ OS::PrintErr("TimelineEventSystraceRecorder: Could not open `%s`\n",
+ kSystracePath);
+ }
+}
+
+
+TimelineEventSystraceRecorder::~TimelineEventSystraceRecorder() {
+ if (systrace_fd_ >= 0) {
+ close(systrace_fd_);
+ }
+}
+
+
+TimelineEventBlock* TimelineEventSystraceRecorder::GetNewBlockLocked() {
+ // TODO(johnmccutchan): This function should only hand out blocks
+ // which have been marked as finished.
+ if (block_cursor_ == num_blocks_) {
+ block_cursor_ = 0;
+ }
+ TimelineEventBlock* block = blocks_[block_cursor_++];
+ block->Reset();
+ block->Open();
+ return block;
+}
+
+
+void TimelineEventSystraceRecorder::CompleteEvent(TimelineEvent* event) {
+ if (event == NULL) {
+ return;
+ }
+ if (systrace_fd_ >= 0) {
+ // Serialize to the systrace format.
+ const intptr_t kBufferLength = 1024;
Chinmay 2016/09/08 17:58:11 This might be larger than necessary. I think systr
Cutch 2016/09/08 18:06:10 I took this number from Android's sources.
+ char buffer[kBufferLength];
+ const intptr_t event_length =
+ event->PrintSystrace(&buffer[0], kBufferLength);
+ if (event_length > 0) {
+ ssize_t result = write(systrace_fd_, buffer, event_length);
Chinmay 2016/09/08 17:58:11 Might be useful to not ignore at least EINTR. I fi
Cutch 2016/09/08 18:06:10 Done.
+ // Ignore failures writing to systrace_fd_.
+ USE(result);
+ }
+ }
+ ThreadBlockCompleteEvent(event);
+}
+
+
TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() {
// TODO(johnmccutchan): This function should only hand out blocks
// which have been marked as finished.
« runtime/vm/timeline.h ('K') | « runtime/vm/timeline.h ('k') | runtime/vm/timeline_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698