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 |