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

Side by Side Diff: runtime/vm/timeline.cc

Issue 1170503004: Initial Timeline Events (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 6 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 unified diff | Download patch
« no previous file with comments | « runtime/vm/timeline.h ('k') | runtime/vm/timeline_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, 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 <cstdlib>
6
7 #include "vm/isolate.h"
8 #include "vm/json_stream.h"
9 #include "vm/object.h"
10 #include "vm/thread.h"
11 #include "vm/timeline.h"
12
13 namespace dart {
14
15 DEFINE_FLAG(bool, trace_timeline, false, "Timeline trace");
16
17 TimelineEvent::TimelineEvent()
18 : timestamp0_(0),
19 timestamp1_(0),
20 arguments_(NULL),
21 arguments_length_(0),
22 state_(0),
23 label_(NULL),
24 stream_(NULL),
25 thread_(NULL) {
26 }
27
28
29 TimelineEvent::~TimelineEvent() {
30 Reset();
31 }
32
33
34 void TimelineEvent::Reset() {
35 set_event_type(kNone);
36 thread_ = NULL;
37 stream_ = NULL;
38 label_ = NULL;
39 FreeArguments();
40 }
41
42
43 int64_t TimelineEvent::AsyncBegin(TimelineStream* stream, const char* label) {
44 Init(kAsyncBegin, stream, label);
45 timestamp0_ = OS::GetCurrentTimeMicros();
46 int64_t async_id = stream->GetNextSeq();
47 // Overload timestamp1_ with the async_id.
48 timestamp1_ = async_id;
49 return async_id;
50 }
51
52
53 void TimelineEvent::AsyncInstant(TimelineStream* stream,
54 const char* label,
55 int64_t async_id) {
56 Init(kAsyncInstant, stream, label);
57 timestamp0_ = OS::GetCurrentTimeMicros();
58 // Overload timestamp1_ with the async_id.
59 timestamp1_ = async_id;
60 }
61
62
63 void TimelineEvent::AsyncEnd(TimelineStream* stream,
64 const char* label,
65 int64_t async_id) {
66 Init(kAsyncEnd, stream, label);
67 timestamp0_ = OS::GetCurrentTimeMicros();
68 // Overload timestamp1_ with the async_id.
69 timestamp1_ = async_id;
70 }
71
72
73 void TimelineEvent::DurationBegin(TimelineStream* stream, const char* label) {
74 Init(kDuration, stream, label);
75 timestamp0_ = OS::GetCurrentTimeMicros();
76 }
77
78
79 void TimelineEvent::DurationEnd() {
80 timestamp1_ = OS::GetCurrentTimeMicros();
81 }
82
83
84 void TimelineEvent::Instant(TimelineStream* stream,
85 const char* label) {
86 Init(kInstant, stream, label);
87 timestamp0_ = OS::GetCurrentTimeMicros();
88 }
89
90
91 void TimelineEvent::Duration(TimelineStream* stream,
92 const char* label,
93 int64_t start_micros,
94 int64_t end_micros) {
95 Init(kDuration, stream, label);
96 timestamp0_ = start_micros;
97 timestamp1_ = end_micros;
98 }
99
100
101 void TimelineEvent::SetNumArguments(intptr_t length) {
102 // Cannot call this twice.
103 ASSERT(arguments_ == NULL);
104 ASSERT(arguments_length_ == 0);
105 arguments_length_ = length;
106 arguments_ = reinterpret_cast<TimelineEventArgument*>(
107 calloc(sizeof(TimelineEventArgument), length));
108 }
109
110
111 void TimelineEvent::SetArgument(intptr_t i, const char* name, char* argument) {
112 ASSERT(i >= 0);
113 ASSERT(i < arguments_length_);
114 arguments_[i].name = name;
115 arguments_[i].value = argument;
116 }
117
118
119 void TimelineEvent::FormatArgument(intptr_t i, const char* name,
120 const char* fmt, ...) {
121 ASSERT(i >= 0);
122 ASSERT(i < arguments_length_);
123 va_list args;
124 va_start(args, fmt);
125 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
126 va_end(args);
127
128 char* buffer = reinterpret_cast<char*>(malloc(len + 1));
129 va_list args2;
130 va_start(args2, fmt);
131 OS::VSNPrint(buffer, (len + 1), fmt, args2);
132 va_end(args2);
133
134 SetArgument(i, name, buffer);
135 }
136
137
138 void TimelineEvent::CopyArgument(intptr_t i,
139 const char* name,
140 const char* argument) {
141 SetArgument(i, name, strdup(argument));
142 }
143
144
145 void TimelineEvent::FreeArguments() {
146 if (arguments_ == NULL) {
147 return;
148 }
149 for (intptr_t i = 0; i < arguments_length_; i++) {
150 free(arguments_[i].value);
151 }
152 free(arguments_);
153 arguments_ = NULL;
154 arguments_length_ = 0;
155 }
156
157 void TimelineEvent::Init(EventType event_type,
158 TimelineStream* stream,
159 const char* label) {
160 ASSERT(stream != NULL);
161 ASSERT(label != NULL);
162 set_event_type(event_type);
163 timestamp0_ = 0;
164 timestamp1_ = 0;
165 thread_ = Thread::Current();
166 stream_ = stream;
167 label_ = label;
168 FreeArguments();
169 }
170
171
172 static int64_t GetPid(Isolate* isolate) {
173 // Some mapping from Isolate* to an integer process id.
174 // TODO(Cutch): Investigate if process ids can be strings.
175 return static_cast<int64_t>(reinterpret_cast<uintptr_t>(isolate));
176 }
177
178
179 static int64_t GetTid(Thread* thread) {
180 // Some mapping from Thread* to an integer thread id.
181 // TODO(Cutch): Investigate if process ids can be strings.
182 return static_cast<int64_t>(reinterpret_cast<uintptr_t>(thread));
183 }
184
185
186 void TimelineEvent::PrintJSON(JSONStream* stream) const {
187 JSONObject obj(stream);
188 int64_t pid = GetPid(Isolate::Current());
189 int64_t tid = GetTid(thread_);
190 obj.AddProperty("name", label_);
191 obj.AddProperty("cat", stream_->name());
192 obj.AddProperty64("tid", tid);
193 obj.AddProperty64("pid", pid);
194 obj.AddProperty("ts", static_cast<double>(TimeOrigin()));
195
196 switch (event_type()) {
197 case kDuration: {
198 obj.AddProperty("ph", "X");
199 obj.AddProperty("dur", static_cast<double>(TimeDuration()));
200 }
201 break;
202 case kInstant: {
203 obj.AddProperty("ph", "i");
204 obj.AddProperty("s", "p");
205 }
206 break;
207 case kAsyncBegin: {
208 obj.AddProperty("ph", "b");
209 obj.AddPropertyF("id", "%" Px64 "", AsyncId());
210 }
211 break;
212 case kAsyncInstant: {
213 obj.AddProperty("ph", "n");
214 obj.AddPropertyF("id", "%" Px64 "", AsyncId());
215 }
216 break;
217 case kAsyncEnd: {
218 obj.AddProperty("ph", "e");
219 obj.AddPropertyF("id", "%" Px64 "", AsyncId());
220 }
221 break;
222 default:
223 UNIMPLEMENTED();
224 }
225 {
226 JSONObject args(&obj, "args");
227 for (intptr_t i = 0; i < arguments_length_; i++) {
228 const TimelineEventArgument& arg = arguments_[i];
229 args.AddProperty(arg.name, arg.value);
230 }
231 }
232 }
233
234
235 int64_t TimelineEvent::TimeOrigin() const {
236 return timestamp0_;
237 }
238
239
240 int64_t TimelineEvent::AsyncId() const {
241 return timestamp1_;
242 }
243
244
245 int64_t TimelineEvent::TimeDuration() const {
246 if (timestamp1_ == 0) {
247 // This duration is still open, use current time as end.
248 return OS::GetCurrentTimeMicros() - timestamp0_;
249 }
250 return timestamp1_ - timestamp0_;
251 }
252
253
254 TimelineStream::TimelineStream()
255 : buffer_(NULL),
256 name_(NULL),
257 enabled_(false),
258 seq_(0) {
259 }
260
261
262 void TimelineStream::Init(const char* name, bool enabled) {
263 name_ = name;
264 enabled_ = enabled;
265 }
266
267
268 TimelineEvent* TimelineStream::RecordEvent(const Object& obj) {
269 if (!enabled_ || (buffer_ == NULL)) {
270 return NULL;
271 }
272 ASSERT(name_ != NULL);
273 ASSERT(buffer_ != NULL);
274 return buffer_->RecordEvent(obj);
275 }
276
277
278 TimelineEvent* TimelineStream::RecordEvent() {
279 if (!enabled_ || (buffer_ == NULL)) {
280 return NULL;
281 }
282 ASSERT(name_ != NULL);
283 return buffer_->RecordEvent();
284 }
285
286
287 int64_t TimelineStream::GetNextSeq() {
288 seq_++;
289 if (seq_ < 0) {
290 seq_ = 0;
291 }
292 return seq_;
293 }
294
295
296 void TimelineDurationScope::FormatArgument(intptr_t i,
297 const char* name,
298 const char* fmt, ...) {
299 if (event_ == NULL) {
300 return;
301 }
302 va_list args;
303 va_start(args, fmt);
304 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
305 va_end(args);
306
307 char* buffer = reinterpret_cast<char*>(malloc(len + 1));
308 va_list args2;
309 va_start(args2, fmt);
310 OS::VSNPrint(buffer, (len + 1), fmt, args2);
311 va_end(args2);
312
313 event_->SetArgument(i, name, buffer);
314 }
315
316
317 intptr_t TimelineEventBuffer::SizeForCapacity(intptr_t capacity) {
318 return sizeof(TimelineEvent) * capacity;
319 }
320
321
322 TimelineEventBuffer::TimelineEventBuffer(intptr_t capacity)
323 : events_(NULL),
324 event_objects_(Array::null()),
325 cursor_(0),
326 capacity_(capacity) {
327 if (FLAG_trace_timeline) {
328 // 32-bit: 262,144 bytes per isolate.
329 // 64-bit: 393,216 bytes per isolate.
330 // NOTE: Internal isolates (vm and service) do not have a timeline
331 // event buffer.
332 OS::Print("TimelineEventBuffer is %" Pd " bytes (%" Pd " events)\n",
333 SizeForCapacity(capacity),
334 capacity);
335 }
336 events_ =
337 reinterpret_cast<TimelineEvent*>(calloc(capacity, sizeof(TimelineEvent)));
338 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld));
339 event_objects_ = array.raw();
340 }
341
342
343 TimelineEventBuffer::~TimelineEventBuffer() {
344 for (intptr_t i = 0; i < capacity_; i++) {
345 // Clear any extra data.
346 events_[i].Reset();
347 }
348 free(events_);
349 event_objects_ = Array::null();
350 }
351
352
353 void TimelineEventBuffer::PrintJSONMeta(JSONArray* events) const {
354 Isolate* isolate = Isolate::Current();
355 JSONObject obj(events);
356 int64_t pid = GetPid(isolate);
357 obj.AddProperty("ph", "M");
358 obj.AddProperty64("pid", pid);
359 obj.AddProperty("name", "process_name");
360 {
361 JSONObject args(&obj, "args");
362 args.AddProperty("name", isolate->debugger_name());
363 }
364 }
365
366
367 void TimelineEventBuffer::PrintJSONEvents(JSONArray* events) const {
368 for (intptr_t i = 0; i < capacity_; i++) {
369 if (events_[i].IsValid()) {
370 events->AddValue(&events_[i]);
371 }
372 }
373 }
374
375
376 void TimelineEventBuffer::PrintJSON(JSONStream* js) const {
377 JSONObject topLevel(js);
378 topLevel.AddProperty("type", "_Timeline");
379 {
380 JSONArray events(&topLevel, "traceEvents");
381 PrintJSONMeta(&events);
382 PrintJSONEvents(&events);
383 }
384 }
385
386
387 void TimelineEventBuffer::WriteTo(const char* directory) {
388 Isolate* isolate = Isolate::Current();
389
390 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
391 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
392 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
393 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
394 return;
395 }
396
397 JSONStream js;
398 PrintJSON(&js);
399
400 const char* format = "%s/dart-timeline-%" Pd "-%" Pd ".json";
401 intptr_t pid = OS::ProcessId();
402 intptr_t len = OS::SNPrint(NULL, 0, format,
403 directory, pid, isolate->main_port());
404 char* filename = isolate->current_zone()->Alloc<char>(len + 1);
405 OS::SNPrint(filename, len + 1, format,
406 directory, pid, isolate->main_port());
407 void* file = (*file_open)(filename, true);
408 if (file == NULL) {
409 OS::Print("Failed to write timeline file: %s\n", filename);
410 return;
411 }
412 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file);
413 (*file_close)(file);
414 }
415
416
417 intptr_t TimelineEventBuffer::GetNextIndex() {
418 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
419 return cursor % capacity_;
420 }
421
422
423 void TimelineEventBuffer::VisitObjectPointers(ObjectPointerVisitor* visitor) {
424 visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_));
425 }
426
427
428 TimelineEvent* TimelineEventBuffer::RecordEvent(const Object& obj) {
429 ASSERT(events_ != NULL);
430 uintptr_t index = GetNextIndex();
431 const Array& event_objects = Array::Handle(event_objects_);
432 event_objects.SetAt(index, obj);
433 return &events_[index];
434 }
435
436
437 TimelineEvent* TimelineEventBuffer::RecordEvent() {
438 ASSERT(events_ != NULL);
439 uintptr_t index = GetNextIndex();
440 return &events_[index];
441 }
442
443 } // namespace dart
OLDNEW
« 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