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

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

Issue 1173333007: Refactor some Timeline interfaces to be simpler and support streaming (Closed) Base URL: git@github.com:dart-lang/sdk.git@timeline2
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
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <cstdlib> 5 #include <cstdlib>
6 6
7 #include "vm/isolate.h" 7 #include "vm/isolate.h"
8 #include "vm/json_stream.h" 8 #include "vm/json_stream.h"
9 #include "vm/object.h" 9 #include "vm/object.h"
10 #include "vm/thread.h" 10 #include "vm/thread.h"
(...skipping 22 matching lines...) Expand all
33 33
34 void TimelineEvent::Reset() { 34 void TimelineEvent::Reset() {
35 set_event_type(kNone); 35 set_event_type(kNone);
36 thread_ = NULL; 36 thread_ = NULL;
37 stream_ = NULL; 37 stream_ = NULL;
38 label_ = NULL; 38 label_ = NULL;
39 FreeArguments(); 39 FreeArguments();
40 } 40 }
41 41
42 42
43 int64_t TimelineEvent::AsyncBegin(TimelineStream* stream, const char* label) { 43 int64_t TimelineEvent::AsyncBegin(const char* label) {
44 Init(kAsyncBegin, stream, label); 44 Init(kAsyncBegin, label);
45 timestamp0_ = OS::GetCurrentTimeMicros(); 45 timestamp0_ = OS::GetCurrentTimeMicros();
46 int64_t async_id = stream->GetNextSeq(); 46 ASSERT(stream_ != NULL);
47 int64_t async_id = stream_->GetNextSeq();
47 // Overload timestamp1_ with the async_id. 48 // Overload timestamp1_ with the async_id.
48 timestamp1_ = async_id; 49 timestamp1_ = async_id;
49 return async_id; 50 return async_id;
50 } 51 }
51 52
52 53
53 void TimelineEvent::AsyncInstant(TimelineStream* stream, 54 void TimelineEvent::AsyncInstant(const char* label,
54 const char* label,
55 int64_t async_id) { 55 int64_t async_id) {
56 Init(kAsyncInstant, stream, label); 56 Init(kAsyncInstant, label);
57 timestamp0_ = OS::GetCurrentTimeMicros(); 57 timestamp0_ = OS::GetCurrentTimeMicros();
58 // Overload timestamp1_ with the async_id. 58 // Overload timestamp1_ with the async_id.
59 timestamp1_ = async_id; 59 timestamp1_ = async_id;
60 } 60 }
61 61
62 62
63 void TimelineEvent::AsyncEnd(TimelineStream* stream, 63 void TimelineEvent::AsyncEnd(const char* label,
64 const char* label,
65 int64_t async_id) { 64 int64_t async_id) {
66 Init(kAsyncEnd, stream, label); 65 Init(kAsyncEnd, label);
67 timestamp0_ = OS::GetCurrentTimeMicros(); 66 timestamp0_ = OS::GetCurrentTimeMicros();
68 // Overload timestamp1_ with the async_id. 67 // Overload timestamp1_ with the async_id.
69 timestamp1_ = async_id; 68 timestamp1_ = async_id;
70 } 69 }
71 70
72 71
73 void TimelineEvent::DurationBegin(TimelineStream* stream, const char* label) { 72 void TimelineEvent::DurationBegin(const char* label) {
74 Init(kDuration, stream, label); 73 Init(kDuration, label);
75 timestamp0_ = OS::GetCurrentTimeMicros(); 74 timestamp0_ = OS::GetCurrentTimeMicros();
76 } 75 }
77 76
78 77
79 void TimelineEvent::DurationEnd() { 78 void TimelineEvent::DurationEnd() {
80 timestamp1_ = OS::GetCurrentTimeMicros(); 79 timestamp1_ = OS::GetCurrentTimeMicros();
81 } 80 }
82 81
83 82
84 void TimelineEvent::Instant(TimelineStream* stream, 83 void TimelineEvent::Instant(const char* label) {
85 const char* label) { 84 Init(kInstant, label);
86 Init(kInstant, stream, label);
87 timestamp0_ = OS::GetCurrentTimeMicros(); 85 timestamp0_ = OS::GetCurrentTimeMicros();
88 } 86 }
89 87
90 88
91 void TimelineEvent::Duration(TimelineStream* stream, 89 void TimelineEvent::Duration(const char* label,
92 const char* label,
93 int64_t start_micros, 90 int64_t start_micros,
94 int64_t end_micros) { 91 int64_t end_micros) {
95 Init(kDuration, stream, label); 92 Init(kDuration, label);
96 timestamp0_ = start_micros; 93 timestamp0_ = start_micros;
97 timestamp1_ = end_micros; 94 timestamp1_ = end_micros;
98 } 95 }
99 96
100 97
101 void TimelineEvent::SetNumArguments(intptr_t length) { 98 void TimelineEvent::SetNumArguments(intptr_t length) {
102 // Cannot call this twice. 99 // Cannot call this twice.
103 ASSERT(arguments_ == NULL); 100 ASSERT(arguments_ == NULL);
104 ASSERT(arguments_length_ == 0); 101 ASSERT(arguments_length_ == 0);
105 arguments_length_ = length; 102 arguments_length_ = length;
(...skipping 29 matching lines...) Expand all
135 } 132 }
136 133
137 134
138 void TimelineEvent::CopyArgument(intptr_t i, 135 void TimelineEvent::CopyArgument(intptr_t i,
139 const char* name, 136 const char* name,
140 const char* argument) { 137 const char* argument) {
141 SetArgument(i, name, strdup(argument)); 138 SetArgument(i, name, strdup(argument));
142 } 139 }
143 140
144 141
142 void TimelineEvent::Complete() {
143 stream_->CompleteEvent(this);
144 }
145
146
145 void TimelineEvent::FreeArguments() { 147 void TimelineEvent::FreeArguments() {
146 if (arguments_ == NULL) { 148 if (arguments_ == NULL) {
147 return; 149 return;
148 } 150 }
149 for (intptr_t i = 0; i < arguments_length_; i++) { 151 for (intptr_t i = 0; i < arguments_length_; i++) {
150 free(arguments_[i].value); 152 free(arguments_[i].value);
151 } 153 }
152 free(arguments_); 154 free(arguments_);
153 arguments_ = NULL; 155 arguments_ = NULL;
154 arguments_length_ = 0; 156 arguments_length_ = 0;
155 } 157 }
156 158
159
160 void TimelineEvent::StreamInit(TimelineStream* stream) {
161 ASSERT(stream != NULL);
162 stream_ = stream;
163 }
164
165
157 void TimelineEvent::Init(EventType event_type, 166 void TimelineEvent::Init(EventType event_type,
158 TimelineStream* stream,
159 const char* label) { 167 const char* label) {
160 ASSERT(stream != NULL);
161 ASSERT(label != NULL); 168 ASSERT(label != NULL);
162 set_event_type(event_type); 169 set_event_type(event_type);
163 timestamp0_ = 0; 170 timestamp0_ = 0;
164 timestamp1_ = 0; 171 timestamp1_ = 0;
165 thread_ = Thread::Current(); 172 thread_ = Thread::Current();
166 stream_ = stream;
167 label_ = label; 173 label_ = label;
168 FreeArguments(); 174 FreeArguments();
169 } 175 }
170 176
171 177
172 static int64_t GetPid(Isolate* isolate) { 178 static int64_t GetPid(Isolate* isolate) {
173 // Some mapping from Isolate* to an integer process id. 179 // Some mapping from Isolate* to an integer process id.
174 // TODO(Cutch): Investigate if process ids can be strings. 180 // TODO(Cutch): Investigate if process ids can be strings.
175 return static_cast<int64_t>(reinterpret_cast<uintptr_t>(isolate)); 181 return static_cast<int64_t>(reinterpret_cast<uintptr_t>(isolate));
176 } 182 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 int64_t TimelineEvent::TimeDuration() const { 251 int64_t TimelineEvent::TimeDuration() const {
246 if (timestamp1_ == 0) { 252 if (timestamp1_ == 0) {
247 // This duration is still open, use current time as end. 253 // This duration is still open, use current time as end.
248 return OS::GetCurrentTimeMicros() - timestamp0_; 254 return OS::GetCurrentTimeMicros() - timestamp0_;
249 } 255 }
250 return timestamp1_ - timestamp0_; 256 return timestamp1_ - timestamp0_;
251 } 257 }
252 258
253 259
254 TimelineStream::TimelineStream() 260 TimelineStream::TimelineStream()
255 : buffer_(NULL), 261 : recorder_(NULL),
256 name_(NULL), 262 name_(NULL),
257 enabled_(false), 263 enabled_(false),
258 seq_(0) { 264 seq_(0) {
259 } 265 }
260 266
261 267
262 void TimelineStream::Init(const char* name, bool enabled) { 268 void TimelineStream::Init(const char* name, bool enabled) {
263 name_ = name; 269 name_ = name;
264 enabled_ = enabled; 270 enabled_ = enabled;
265 } 271 }
266 272
267 273
268 TimelineEvent* TimelineStream::RecordEvent(const Object& obj) { 274 TimelineEvent* TimelineStream::StartEvent(const Object& obj) {
269 if (!enabled_ || (buffer_ == NULL)) { 275 if (!enabled_ || (recorder_ == NULL)) {
270 return NULL; 276 return NULL;
271 } 277 }
272 ASSERT(name_ != NULL); 278 ASSERT(name_ != NULL);
273 ASSERT(buffer_ != NULL); 279 ASSERT(recorder_ != NULL);
274 return buffer_->RecordEvent(obj); 280 TimelineEvent* event = recorder_->StartEvent(obj);
281 if (event != NULL) {
282 event->StreamInit(this);
283 }
284 return event;
275 } 285 }
276 286
277 287
278 TimelineEvent* TimelineStream::RecordEvent() { 288 TimelineEvent* TimelineStream::StartEvent() {
279 if (!enabled_ || (buffer_ == NULL)) { 289 if (!enabled_ || (recorder_ == NULL)) {
280 return NULL; 290 return NULL;
281 } 291 }
282 ASSERT(name_ != NULL); 292 ASSERT(name_ != NULL);
283 return buffer_->RecordEvent(); 293 TimelineEvent* event = recorder_->StartEvent();
294 if (event != NULL) {
295 event->StreamInit(this);
296 }
297 return event;
284 } 298 }
285 299
286 300
301 void TimelineStream::CompleteEvent(TimelineEvent* event) {
302 if (!enabled_ || (recorder_ == NULL)) {
303 return;
304 }
305 recorder_->CompleteEvent(event);
306 }
307
308
287 int64_t TimelineStream::GetNextSeq() { 309 int64_t TimelineStream::GetNextSeq() {
288 seq_++; 310 seq_++;
289 if (seq_ < 0) { 311 if (seq_ < 0) {
290 seq_ = 0; 312 seq_ = 0;
291 } 313 }
292 return seq_; 314 return seq_;
293 } 315 }
294 316
295 317
296 void TimelineDurationScope::FormatArgument(intptr_t i, 318 void TimelineDurationScope::FormatArgument(intptr_t i,
(...skipping 10 matching lines...) Expand all
307 char* buffer = reinterpret_cast<char*>(malloc(len + 1)); 329 char* buffer = reinterpret_cast<char*>(malloc(len + 1));
308 va_list args2; 330 va_list args2;
309 va_start(args2, fmt); 331 va_start(args2, fmt);
310 OS::VSNPrint(buffer, (len + 1), fmt, args2); 332 OS::VSNPrint(buffer, (len + 1), fmt, args2);
311 va_end(args2); 333 va_end(args2);
312 334
313 event_->SetArgument(i, name, buffer); 335 event_->SetArgument(i, name, buffer);
314 } 336 }
315 337
316 338
317 intptr_t TimelineEventBuffer::SizeForCapacity(intptr_t capacity) { 339 TimelineEventRecorder::TimelineEventRecorder() {
340 }
341
342
343 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const {
344 Isolate* isolate = Isolate::Current();
345 JSONObject obj(events);
346 int64_t pid = GetPid(isolate);
347 obj.AddProperty("ph", "M");
348 obj.AddProperty64("pid", pid);
349 obj.AddProperty("name", "process_name");
350 {
351 JSONObject args(&obj, "args");
352 args.AddProperty("name", isolate->debugger_name());
353 }
354 }
355
356
357 void TimelineEventRecorder::WriteTo(const char* directory) {
358 Isolate* isolate = Isolate::Current();
359
360 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
361 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
362 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
363 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
364 return;
365 }
366
367 JSONStream js;
368 PrintJSON(&js);
369
370 const char* format = "%s/dart-timeline-%" Pd "-%" Pd ".json";
371 intptr_t pid = OS::ProcessId();
372 intptr_t len = OS::SNPrint(NULL, 0, format,
373 directory, pid, isolate->main_port());
374 char* filename = isolate->current_zone()->Alloc<char>(len + 1);
375 OS::SNPrint(filename, len + 1, format,
376 directory, pid, isolate->main_port());
377 void* file = (*file_open)(filename, true);
378 if (file == NULL) {
379 OS::Print("Failed to write timeline file: %s\n", filename);
380 return;
381 }
382 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file);
383 (*file_close)(file);
384 }
385
386
387 intptr_t TimelineEventRingRecorder::SizeForCapacity(intptr_t capacity) {
318 return sizeof(TimelineEvent) * capacity; 388 return sizeof(TimelineEvent) * capacity;
319 } 389 }
320 390
321 391
322 TimelineEventBuffer::TimelineEventBuffer(intptr_t capacity) 392 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity)
323 : events_(NULL), 393 : events_(NULL),
324 event_objects_(Array::null()), 394 event_objects_(Array::null()),
325 cursor_(0), 395 cursor_(0),
326 capacity_(capacity) { 396 capacity_(capacity) {
327 if (FLAG_trace_timeline) { 397 if (FLAG_trace_timeline) {
328 // 32-bit: 262,144 bytes per isolate. 398 // 32-bit: 262,144 bytes per isolate.
329 // 64-bit: 393,216 bytes per isolate. 399 // 64-bit: 393,216 bytes per isolate.
330 // NOTE: Internal isolates (vm and service) do not have a timeline 400 // NOTE: Internal isolates (vm and service) do not have a timeline
331 // event buffer. 401 // event buffer.
332 OS::Print("TimelineEventBuffer is %" Pd " bytes (%" Pd " events)\n", 402 OS::Print("TimelineEventRingRecorder is %" Pd " bytes (%" Pd " events)\n",
333 SizeForCapacity(capacity), 403 SizeForCapacity(capacity),
334 capacity); 404 capacity);
335 } 405 }
336 events_ = 406 events_ =
337 reinterpret_cast<TimelineEvent*>(calloc(capacity, sizeof(TimelineEvent))); 407 reinterpret_cast<TimelineEvent*>(calloc(capacity, sizeof(TimelineEvent)));
338 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld)); 408 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld));
339 event_objects_ = array.raw(); 409 event_objects_ = array.raw();
340 } 410 }
341 411
342 412
343 TimelineEventBuffer::~TimelineEventBuffer() { 413 TimelineEventRingRecorder::~TimelineEventRingRecorder() {
344 for (intptr_t i = 0; i < capacity_; i++) { 414 for (intptr_t i = 0; i < capacity_; i++) {
345 // Clear any extra data. 415 // Clear any extra data.
346 events_[i].Reset(); 416 events_[i].Reset();
347 } 417 }
348 free(events_); 418 free(events_);
349 event_objects_ = Array::null(); 419 event_objects_ = Array::null();
350 } 420 }
351 421
352 422
353 void TimelineEventBuffer::PrintJSONMeta(JSONArray* events) const { 423 void TimelineEventRingRecorder::PrintJSONEvents(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++) { 424 for (intptr_t i = 0; i < capacity_; i++) {
369 if (events_[i].IsValid()) { 425 if (events_[i].IsValid()) {
370 events->AddValue(&events_[i]); 426 events->AddValue(&events_[i]);
371 } 427 }
372 } 428 }
373 } 429 }
374 430
375 431
376 void TimelineEventBuffer::PrintJSON(JSONStream* js) const { 432 void TimelineEventRingRecorder::PrintJSON(JSONStream* js) const {
377 JSONObject topLevel(js); 433 JSONObject topLevel(js);
378 topLevel.AddProperty("type", "_Timeline"); 434 topLevel.AddProperty("type", "_Timeline");
379 { 435 {
380 JSONArray events(&topLevel, "traceEvents"); 436 JSONArray events(&topLevel, "traceEvents");
381 PrintJSONMeta(&events); 437 PrintJSONMeta(&events);
382 PrintJSONEvents(&events); 438 PrintJSONEvents(&events);
383 } 439 }
384 } 440 }
385 441
386 442
387 void TimelineEventBuffer::WriteTo(const char* directory) { 443 intptr_t TimelineEventRingRecorder::GetNextIndex() {
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_); 444 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_);
419 return cursor % capacity_; 445 return cursor % capacity_;
420 } 446 }
421 447
422 448
423 void TimelineEventBuffer::VisitObjectPointers(ObjectPointerVisitor* visitor) { 449 void TimelineEventRingRecorder::VisitObjectPointers(
450 ObjectPointerVisitor* visitor) {
424 visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_)); 451 visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_));
425 } 452 }
426 453
427 454
428 TimelineEvent* TimelineEventBuffer::RecordEvent(const Object& obj) { 455 TimelineEvent* TimelineEventRingRecorder::StartEvent(const Object& obj) {
429 ASSERT(events_ != NULL); 456 ASSERT(events_ != NULL);
430 uintptr_t index = GetNextIndex(); 457 uintptr_t index = GetNextIndex();
431 const Array& event_objects = Array::Handle(event_objects_); 458 const Array& event_objects = Array::Handle(event_objects_);
432 event_objects.SetAt(index, obj); 459 event_objects.SetAt(index, obj);
433 return &events_[index]; 460 return &events_[index];
434 } 461 }
435 462
436 463
437 TimelineEvent* TimelineEventBuffer::RecordEvent() { 464 TimelineEvent* TimelineEventRingRecorder::StartEvent() {
438 ASSERT(events_ != NULL); 465 ASSERT(events_ != NULL);
439 uintptr_t index = GetNextIndex(); 466 uintptr_t index = GetNextIndex();
440 return &events_[index]; 467 return &events_[index];
441 } 468 }
442 469
470 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) {
471 ASSERT(events_ != NULL);
472 // no-op.
473 }
474
475
476 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() {
477 }
478
479
480 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() {
481 }
482
483
484 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) const {
485 JSONObject topLevel(js);
486 topLevel.AddProperty("type", "_Timeline");
487 {
488 JSONArray events(&topLevel, "traceEvents");
489 PrintJSONMeta(&events);
490 }
491 }
492
493 void TimelineEventStreamingRecorder::VisitObjectPointers(
494 ObjectPointerVisitor* visitor) {
495 // no-op.
496 }
497
498
499 TimelineEvent* TimelineEventStreamingRecorder::StartEvent(
500 const Object& object) {
501 // The streaming recorder does not track Dart objects.
502 return StartEvent();
503 }
504
505
506 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() {
507 TimelineEvent* event = new TimelineEvent();
508 return event;
509 }
510
511
512 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) {
513 StreamEvent(event);
514 delete event;
515 }
516
443 } // namespace dart 517 } // 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