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

Unified Diff: runtime/vm/timeline.cc

Issue 2315353004: Record Timeline to Android Systrace (Closed)
Patch Set: rmacnak review 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
« no previous file with comments | « runtime/vm/timeline.h ('k') | runtime/vm/timeline_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/timeline.cc
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index 7e9ba2d179c9ec86ad6615ce49555b26a69e4eb9..8d3a966d70cea24ecd5e604d05b68ba8ed5c7576 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -4,6 +4,8 @@
#ifndef PRODUCT
+#include <errno.h>
+#include <fcntl.h>
#include <cstdlib>
#include "vm/atomic.h"
@@ -20,6 +22,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,
@@ -35,7 +38,7 @@ DEFINE_FLAG(charp, timeline_streams, NULL,
"GC, Isolate, and VM.");
DEFINE_FLAG(charp, timeline_recorder, "ring",
"Select the timeline recorder used. "
- "Valid values: ring, endless, and startup.")
+ "Valid values: ring, endless, startup, and systrace.")
// Implementation notes:
//
@@ -86,9 +89,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)) {
+ 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 +510,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 = OS::SNPrint(buffer, buffer_size, "B|%" Pd64 "|%s", pid, label());
+ }
+ break;
+ case kEnd: {
+ length = OS::SNPrint(buffer, buffer_size, "E");
+ }
+ break;
+ case kCounter: {
+ if (arguments_length_ > 0) {
+ // We only report the first counter value.
+ length = OS::SNPrint(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 +1400,69 @@ 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) {
+#if defined(TARGET_OS_ANDROID) || defined(TARGET_OS_LINUX)
+ systrace_fd_ = open(kSystracePath, O_WRONLY);
+ if ((systrace_fd_ < 0) && FLAG_trace_timeline) {
+ OS::PrintErr("TimelineEventSystraceRecorder: Could not open `%s`\n",
+ kSystracePath);
+ }
+#else
+ OS::PrintErr("Warning: The systrace timeline recorder is equivalent to the"
+ "ring recorder on this platform.");
+#endif
+}
+
+
+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 defined(TARGET_OS_ANDROID) || defined(TARGET_OS_LINUX)
+ if (systrace_fd_ >= 0) {
+ // Serialize to the systrace format.
+ const intptr_t kBufferLength = 1024;
+ char buffer[kBufferLength];
+ const intptr_t event_length =
+ event->PrintSystrace(&buffer[0], kBufferLength);
+ if (event_length > 0) {
+ ssize_t __result;
+ // Repeatedly attempt the write while we are being interrupted.
+ do {
+ __result = write(systrace_fd_, buffer, event_length);
+ } while ((__result == -1L) && (errno == EINTR));
+ }
+ }
+#endif
+ ThreadBlockCompleteEvent(event);
+}
+
+
TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() {
// TODO(johnmccutchan): This function should only hand out blocks
// which have been marked as finished.
« no previous file with comments | « 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