Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 #include "platform/globals.h" | |
| 6 #if defined(HOST_OS_FUCHSIA) && !defined(PRODUCT) | |
| 7 | |
| 8 #include "apps/tracing/lib/trace/cwriter.h" | |
| 9 #include "apps/tracing/lib/trace/event.h" | |
| 10 #include "vm/object.h" | |
| 11 #include "vm/timeline.h" | |
| 12 | |
| 13 namespace dart { | |
| 14 | |
| 15 // A recorder that sends events to Fuchsia's tracing app. Events are also stored | |
| 16 // in a buffer of fixed capacity. When the buffer is full, new events overwrite | |
| 17 // old events. | |
| 18 // See: https://fuchsia.googlesource.com/tracing/+/HEAD/docs/usage_guide.md | |
| 19 | |
| 20 TimelineEventPlatformRecorder::TimelineEventPlatformRecorder(intptr_t capacity) | |
| 21 : TimelineEventFixedBufferRecorder(capacity) {} | |
| 22 | |
| 23 TimelineEventPlatformRecorder::~TimelineEventPlatformRecorder() {} | |
| 24 | |
| 25 TimelineEventPlatformRecorder* | |
| 26 TimelineEventPlatformRecorder::CreatePlatformRecorder(intptr_t capacity) { | |
| 27 return new TimelineEventPlatformRecorder(capacity); | |
| 28 } | |
| 29 | |
| 30 const char* TimelineEventPlatformRecorder::name() const { | |
| 31 return "Fuchsia"; | |
| 32 } | |
| 33 | |
| 34 TimelineEventBlock* TimelineEventPlatformRecorder::GetNewBlockLocked() { | |
| 35 // TODO(johnmccutchan): This function should only hand out blocks | |
| 36 // which have been marked as finished. | |
| 37 if (block_cursor_ == num_blocks_) { | |
| 38 block_cursor_ = 0; | |
| 39 } | |
| 40 TimelineEventBlock* block = blocks_[block_cursor_++]; | |
| 41 block->Reset(); | |
| 42 block->Open(); | |
| 43 return block; | |
| 44 } | |
| 45 | |
| 46 void TimelineEventPlatformRecorder::CompleteEvent(TimelineEvent* event) { | |
| 47 if (event == NULL) { | |
| 48 return; | |
| 49 } | |
| 50 if (!ctrace_is_enabled()) { | |
| 51 ThreadBlockCompleteEvent(event); | |
| 52 return; | |
| 53 } | |
| 54 auto writer = ctrace_writer_acquire(); | |
| 55 | |
| 56 // XXX: use ctrace_register_category_string(); | |
| 57 ctrace_stringref_t category; | |
| 58 ctrace_register_string(writer, "dart", &category); | |
| 59 | |
| 60 ctrace_stringref_t name; | |
| 61 ctrace_register_string(writer, event->label(), &name); | |
| 62 | |
| 63 ctrace_threadref_t thread; | |
| 64 ctrace_register_current_thread(writer, &thread); | |
| 65 | |
| 66 ctrace_argspec_t args[2]; | |
| 67 ctrace_arglist_t arglist = {0, args}; | |
| 68 | |
| 69 if (event->arguments_length() >= 1) { | |
| 70 args[0].type = CTRACE_ARGUMENT_STRING; | |
| 71 args[0].name = event->arguments()[0].name; | |
| 72 args[0].u.s = event->arguments()[0].value; | |
| 73 arglist.n_args += 1; | |
| 74 } | |
| 75 if (event->arguments_length() >= 2) { | |
| 76 args[1].type = CTRACE_ARGUMENT_STRING; | |
| 77 args[1].name = event->arguments()[1].name; | |
| 78 args[1].u.s = event->arguments()[1].value; | |
| 79 arglist.n_args += 1; | |
| 80 } | |
| 81 | |
| 82 const uint64_t time_scale = mx_ticks_per_second() / kMicrosecondsPerSecond; | |
| 83 const uint64_t start_time = event->LowTime() * time_scale; | |
| 84 const uint64_t end_time = event->HighTime() * time_scale; | |
| 85 | |
| 86 // TODO(zra): The functions below emit Dart's timeline events all as category | |
| 87 // "dart". Instead, we could have finer-grained categories that make use of | |
| 88 // the name of the timeline stream, e.g. "VM", "GC", etc. | |
| 89 switch (event->event_type()) { | |
| 90 case TimelineEvent::kBegin: | |
| 91 ctrace_write_duration_begin_event_record(writer, start_time, &thread, | |
| 92 &category, &name, &arglist); | |
| 93 break; | |
| 94 case TimelineEvent::kEnd: | |
| 95 ctrace_write_duration_end_event_record(writer, end_time, &thread, | |
| 96 &category, &name, &arglist); | |
| 97 break; | |
| 98 case TimelineEvent::kInstant: | |
| 99 ctrace_write_instant_event_record(writer, start_time, &thread, &category, | |
| 100 &name, CTRACE_SCOPE_THREAD, &arglist); | |
| 101 break; | |
| 102 case TimelineEvent::kAsyncBegin: | |
| 103 ctrace_write_async_begin_event_record(writer, start_time, &thread, | |
| 104 &category, &name, event->AsyncId(), | |
| 105 &arglist); | |
| 106 break; | |
| 107 case TimelineEvent::kAsyncEnd: | |
| 108 ctrace_write_async_end_event_record(writer, end_time, &thread, &category, | |
| 109 &name, event->AsyncId(), &arglist); | |
| 110 break; | |
| 111 case TimelineEvent::kAsyncInstant: | |
| 112 ctrace_write_async_instant_event_record(writer, start_time, &thread, | |
| 113 &category, &name, | |
| 114 event->AsyncId(), &arglist); | |
| 115 break; | |
| 116 case TimelineEvent::kDuration: | |
| 117 ctrace_write_duration_event_record(writer, start_time, end_time, &thread, | |
| 118 &category, &name, &arglist); | |
| 119 break; | |
| 120 case TimelineEvent::kFlowBegin: | |
| 121 ctrace_write_flow_begin_event_record(writer, start_time, &thread, | |
| 122 &category, &name, event->AsyncId(), | |
| 123 &arglist); | |
| 124 break; | |
| 125 case TimelineEvent::kFlowStep: | |
| 126 ctrace_write_flow_step_event_record(writer, start_time, &thread, | |
| 127 &category, &name, event->AsyncId(), | |
| 128 &arglist); | |
| 129 break; | |
| 130 case TimelineEvent::kFlowEnd: | |
| 131 ctrace_write_flow_end_event_record(writer, start_time, &thread, &category, | |
| 132 &name, event->AsyncId(), &arglist); | |
| 133 break; | |
| 134 default: | |
| 135 // TODO(zra): Figure out what to do with kCounter and kMetadata. | |
| 136 break; | |
| 137 } | |
| 138 ctrace_writer_release(writer); | |
| 139 ThreadBlockCompleteEvent(event); | |
| 140 } | |
| 141 | |
| 142 void DartTimelineEventHelpers::ReportTaskEvent(Thread* thread, | |
| 143 Zone* zone, | |
| 144 TimelineEvent* event, | |
| 145 int64_t start, | |
| 146 int64_t id, | |
| 147 const char* phase, | |
| 148 const char* category, | |
| 149 const char* name, | |
| 150 const char* args) { | |
| 151 char* name_string = strdup(name); | |
| 152 ASSERT(phase != NULL); | |
| 153 ASSERT((phase[0] == 'n') || (phase[0] == 'b') || (phase[0] == 'e')); | |
| 154 ASSERT(phase[1] == '\0'); | |
| 155 switch (phase[0]) { | |
| 156 case 'n': | |
| 157 event->AsyncInstant(name_string, id, start); | |
| 158 break; | |
| 159 case 'b': | |
| 160 event->AsyncBegin(name_string, id, start); | |
| 161 break; | |
| 162 case 'e': | |
| 163 event->AsyncEnd(name_string, id, start); | |
| 164 break; | |
| 165 default: | |
| 166 UNREACHABLE(); | |
| 167 } | |
| 168 event->set_owns_label(true); | |
| 169 event->SetNumArguments(1); | |
| 170 event->CopyArgument(0, "args", args); | |
| 171 event->Complete(); | |
| 172 } | |
| 173 | |
| 174 void DartTimelineEventHelpers::ReportCompleteEvent(Thread* thread, | |
| 175 Zone* zone, | |
| 176 TimelineEvent* event, | |
| 177 int64_t start, | |
| 178 int64_t start_cpu, | |
| 179 const char* category, | |
| 180 const char* name, | |
| 181 const char* args) { | |
| 182 const int64_t end = OS::GetCurrentMonotonicMicros(); | |
| 183 const int64_t end_cpu = OS::GetCurrentThreadCPUMicros(); | |
| 184 event->Duration(strdup(name), start, end, start_cpu, end_cpu); | |
| 185 event->set_owns_label(true); | |
| 186 event->SetNumArguments(1); | |
| 187 event->CopyArgument(0, "args", args); | |
| 188 event->Complete(); | |
| 189 } | |
| 190 | |
| 191 void DartTimelineEventHelpers::ReportInstantEvent(Thread* thread, | |
| 192 Zone* zone, | |
| 193 TimelineEvent* event, | |
| 194 int64_t start, | |
| 195 const char* category, | |
| 196 const char* name, | |
| 197 const char* args) { | |
| 198 event->Instant(strdup(name), start); | |
| 199 event->set_owns_label(true); | |
| 200 event->SetNumArguments(1); | |
| 201 event->CopyArgument(0, "args", args); | |
| 202 event->Complete(); | |
| 203 } | |
| 204 | |
| 205 } // namespace dart | |
| 206 | |
| 207 #endif // !PRODUCT | |
|
siva
2017/07/21 00:29:52
ditto here and other files.
zra
2017/07/21 15:06:18
Done.
| |
| OLD | NEW |