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

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

Issue 1287383002: Make TimelineRingRecorder use TimelineEventBlocks (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 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') | no next file » | 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/lockers.h" 9 #include "vm/lockers.h"
10 #include "vm/object.h" 10 #include "vm/object.h"
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 325
326 326
327 TimelineEventRecorder::TimelineEventRecorder() { 327 TimelineEventRecorder::TimelineEventRecorder() {
328 } 328 }
329 329
330 330
331 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { 331 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const {
332 } 332 }
333 333
334 334
335 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() {
336 // Grab the thread's timeline event block.
337 Thread* thread = Thread::Current();
338 TimelineEventBlock* thread_block = thread->timeline_block();
339 if ((thread_block == NULL) || thread_block->IsFull()) {
340 // If it is full, request a new block.
341 thread_block = GetNewBlock();
342 thread->set_timeline_block(thread_block);
343 }
344 if (thread_block == NULL) {
345 // Could not allocate block.
346 return NULL;
347 }
348 ASSERT(thread_block != NULL);
349 ASSERT(!thread_block->IsFull());
350 return thread_block->StartEvent();
351 }
352
353
335 void TimelineEventRecorder::WriteTo(const char* directory) { 354 void TimelineEventRecorder::WriteTo(const char* directory) {
336 Isolate* isolate = Isolate::Current(); 355 Isolate* isolate = Isolate::Current();
337 356
338 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); 357 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
339 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); 358 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
340 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); 359 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
341 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { 360 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
342 return; 361 return;
343 } 362 }
344 363
(...skipping 10 matching lines...) Expand all
355 void* file = (*file_open)(filename, true); 374 void* file = (*file_open)(filename, true);
356 if (file == NULL) { 375 if (file == NULL) {
357 OS::Print("Failed to write timeline file: %s\n", filename); 376 OS::Print("Failed to write timeline file: %s\n", filename);
358 return; 377 return;
359 } 378 }
360 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); 379 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file);
361 (*file_close)(file); 380 (*file_close)(file);
362 } 381 }
363 382
364 383
365 intptr_t TimelineEventRingRecorder::SizeForCapacity(intptr_t capacity) {
366 return sizeof(TimelineEvent) * capacity;
367 }
368
369 384
370 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) 385 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity)
371 : events_(NULL), 386 : blocks_(NULL),
372 event_objects_(Array::null()), 387 event_objects_(Array::null()),
373 cursor_(0), 388 capacity_(capacity),
374 capacity_(capacity) { 389 num_blocks_(0),
375 if (FLAG_trace_timeline) { 390 block_cursor_(0) {
376 // 32-bit: 262,144 bytes per isolate. 391 // Capacity must be a multiple of TimelineEventBlock::kBlockSize
377 // 64-bit: 393,216 bytes per isolate. 392 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0);
378 // NOTE: Internal isolates (vm and service) do not have a timeline 393 // Allocate blocks array.
379 // event buffer. 394 num_blocks_ = capacity / TimelineEventBlock::kBlockSize;
380 OS::Print("TimelineEventRingRecorder is %" Pd " bytes (%" Pd " events)\n", 395 blocks_ =
381 SizeForCapacity(capacity), 396 reinterpret_cast<TimelineEventBlock**>(
382 capacity); 397 calloc(num_blocks_, sizeof(TimelineEventBlock*)));
398 // Allocate each block.
399 for (intptr_t i = 0; i < num_blocks_; i++) {
400 blocks_[i] = new TimelineEventBlock(i);
383 } 401 }
384 events_ = 402 // Chain blocks together.
385 reinterpret_cast<TimelineEvent*>(calloc(capacity, sizeof(TimelineEvent))); 403 for (intptr_t i = 0; i < num_blocks_ - 1; i++) {
404 blocks_[i]->set_next(blocks_[i + 1]);
405 }
386 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld)); 406 const Array& array = Array::Handle(Array::New(capacity, Heap::kOld));
387 event_objects_ = array.raw(); 407 event_objects_ = array.raw();
388 } 408 }
389 409
390 410
391 TimelineEventRingRecorder::~TimelineEventRingRecorder() { 411 TimelineEventRingRecorder::~TimelineEventRingRecorder() {
392 for (intptr_t i = 0; i < capacity_; i++) { 412 // Delete all blocks.
393 // Clear any extra data. 413 for (intptr_t i = 0; i < num_blocks_; i++) {
394 events_[i].Reset(); 414 TimelineEventBlock* block = blocks_[i];
415 delete block;
395 } 416 }
396 free(events_); 417 free(blocks_);
397 event_objects_ = Array::null(); 418 event_objects_ = Array::null();
398 } 419 }
399 420
400 421
401 void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const { 422 void TimelineEventRingRecorder::PrintJSONEvents(JSONArray* events) const {
402 for (intptr_t i = 0; i < capacity_; i++) { 423 // TODO(johnmccutchan): This output needs to start with the oldest block
403 if (events_[i].IsValid()) { 424 // first.
404 events->AddValue(&events_[i]); 425 for (intptr_t block_idx = 0; block_idx < num_blocks_; block_idx++) {
426 TimelineEventBlock* block = blocks_[block_idx];
427 if (block->IsEmpty()) {
428 // Skip empty blocks.
429 continue;
430 }
431 for (intptr_t event_idx = 0; event_idx < block->length(); event_idx++) {
432 TimelineEvent* event = block->At(event_idx);
433 if (event->IsValid()) {
434 events->AddValue(event);
435 }
405 } 436 }
406 } 437 }
407 } 438 }
408 439
409 440
410 void TimelineEventRingRecorder::PrintJSON(JSONStream* js) { 441 void TimelineEventRingRecorder::PrintJSON(JSONStream* js) {
442 MutexLocker ml(&lock_);
411 JSONObject topLevel(js); 443 JSONObject topLevel(js);
412 topLevel.AddProperty("type", "_Timeline"); 444 topLevel.AddProperty("type", "_Timeline");
413 { 445 {
414 JSONArray events(&topLevel, "traceEvents"); 446 JSONArray events(&topLevel, "traceEvents");
415 PrintJSONMeta(&events); 447 PrintJSONMeta(&events);
416 PrintJSONEvents(&events); 448 PrintJSONEvents(&events);
417 } 449 }
418 } 450 }
419 451
420 452
421 intptr_t TimelineEventRingRecorder::GetNextIndex() { 453 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlock() {
422 uintptr_t cursor = AtomicOperations::FetchAndIncrement(&cursor_); 454 MutexLocker ml(&lock_);
423 return cursor % capacity_; 455 return GetNewBlockLocked();
424 } 456 }
425 457
426 458
459 TimelineEventBlock* TimelineEventRingRecorder::GetNewBlockLocked() {
460 if (block_cursor_ == num_blocks_) {
461 block_cursor_ = 0;
462 }
463 TimelineEventBlock* block = blocks_[block_cursor_++];
464 block->Reset();
465 return block;
466 }
467
468
427 void TimelineEventRingRecorder::VisitObjectPointers( 469 void TimelineEventRingRecorder::VisitObjectPointers(
428 ObjectPointerVisitor* visitor) { 470 ObjectPointerVisitor* visitor) {
429 visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_)); 471 visitor->VisitPointer(reinterpret_cast<RawObject**>(&event_objects_));
430 } 472 }
431 473
432 474
433 TimelineEvent* TimelineEventRingRecorder::StartEvent(const Object& obj) { 475 TimelineEvent* TimelineEventRingRecorder::StartEvent(const Object& obj) {
434 ASSERT(events_ != NULL); 476 TimelineEvent* event = StartEvent();
435 uintptr_t index = GetNextIndex(); 477 if (event == NULL) {
478 return NULL;
479 }
480 // Grab the thread's timeline event block which contains |event|.
481 Thread* thread = Thread::Current();
482 TimelineEventBlock* thread_block = thread->timeline_block();
483 ASSERT(thread_block != NULL);
484 ASSERT(thread_block->length() > 0);
485 const intptr_t block_index = thread_block->block_index();
486 const intptr_t event_objects_index =
487 block_index * TimelineEventBlock::kBlockSize + thread_block->length() - 1;
436 const Array& event_objects = Array::Handle(event_objects_); 488 const Array& event_objects = Array::Handle(event_objects_);
437 event_objects.SetAt(index, obj); 489 event_objects.SetAt(event_objects_index, obj);
438 return &events_[index]; 490 return event;
439 } 491 }
440 492
441 493
442 TimelineEvent* TimelineEventRingRecorder::StartEvent() { 494 TimelineEvent* TimelineEventRingRecorder::StartEvent() {
443 ASSERT(events_ != NULL); 495 return ThreadBlockStartEvent();
444 uintptr_t index = GetNextIndex();
445 return &events_[index];
446 } 496 }
447 497
498
448 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { 499 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) {
449 ASSERT(events_ != NULL);
450 // no-op. 500 // no-op.
451 } 501 }
452 502
453 503
454 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { 504 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() {
455 } 505 }
456 506
457 507
458 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { 508 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() {
459 } 509 }
460 510
461 511
462 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) { 512 void TimelineEventStreamingRecorder::PrintJSON(JSONStream* js) {
463 JSONObject topLevel(js); 513 JSONObject topLevel(js);
464 topLevel.AddProperty("type", "_Timeline"); 514 topLevel.AddProperty("type", "_Timeline");
465 { 515 {
466 JSONArray events(&topLevel, "traceEvents"); 516 JSONArray events(&topLevel, "traceEvents");
467 PrintJSONMeta(&events); 517 PrintJSONMeta(&events);
468 } 518 }
469 } 519 }
470 520
521
471 void TimelineEventStreamingRecorder::VisitObjectPointers( 522 void TimelineEventStreamingRecorder::VisitObjectPointers(
472 ObjectPointerVisitor* visitor) { 523 ObjectPointerVisitor* visitor) {
473 // no-op. 524 // no-op.
474 } 525 }
475 526
476 527
477 TimelineEvent* TimelineEventStreamingRecorder::StartEvent( 528 TimelineEvent* TimelineEventStreamingRecorder::StartEvent(
478 const Object& object) { 529 const Object& object) {
479 // The streaming recorder does not track Dart objects. 530 // The streaming recorder does not track Dart objects.
480 return StartEvent(); 531 return StartEvent();
481 } 532 }
482 533
483 534
484 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { 535 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() {
485 TimelineEvent* event = new TimelineEvent(); 536 TimelineEvent* event = new TimelineEvent();
486 return event; 537 return event;
487 } 538 }
488 539
489 540
490 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { 541 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) {
491 StreamEvent(event); 542 StreamEvent(event);
492 delete event; 543 delete event;
493 } 544 }
494 545
495 546
496 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() 547 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder()
497 : head_(NULL) { 548 : head_(NULL),
549 block_index_(0) {
498 GetNewBlock(); 550 GetNewBlock();
499 } 551 }
500 552
501 553
502 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js) { 554 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js) {
503 MutexLocker ml(&lock_); 555 MutexLocker ml(&lock_);
504 JSONObject topLevel(js); 556 JSONObject topLevel(js);
505 topLevel.AddProperty("type", "_Timeline"); 557 topLevel.AddProperty("type", "_Timeline");
506 { 558 {
507 JSONArray events(&topLevel, "traceEvents"); 559 JSONArray events(&topLevel, "traceEvents");
(...skipping 14 matching lines...) Expand all
522 // no-op. 574 // no-op.
523 } 575 }
524 576
525 577
526 TimelineEvent* TimelineEventEndlessRecorder::StartEvent(const Object& object) { 578 TimelineEvent* TimelineEventEndlessRecorder::StartEvent(const Object& object) {
527 return StartEvent(); 579 return StartEvent();
528 } 580 }
529 581
530 582
531 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { 583 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() {
532 // Grab the thread's timeline event block. 584 return ThreadBlockStartEvent();
533 Thread* thread = Thread::Current();
534 TimelineEventBlock* thread_block = thread->timeline_block();
535 if (thread_block == NULL) {
536 return NULL;
537 }
538 ASSERT(thread_block != NULL);
539 if (thread_block->IsFull()) {
540 // If it is full, request a new block.
541 thread_block = GetNewBlock();
542 thread->set_timeline_block(thread_block);
543 }
544 ASSERT(!thread_block->IsFull());
545 return thread_block->StartEvent();
546 } 585 }
547 586
548 587
549 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { 588 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) {
550 // no-op. 589 // no-op.
551 } 590 }
552 591
553 592
554 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() { 593 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked() {
555 TimelineEventBlock* block = new TimelineEventBlock(); 594 TimelineEventBlock* block = new TimelineEventBlock(block_index_++);
556 block->set_next(head_); 595 block->set_next(head_);
557 head_ = block; 596 head_ = block;
558 return head_; 597 return head_;
559 } 598 }
560 599
561 600
562 void TimelineEventEndlessRecorder::PrintJSONEvents(JSONArray* events) const { 601 void TimelineEventEndlessRecorder::PrintJSONEvents(JSONArray* events) const {
563 TimelineEventBlock* current = head_; 602 TimelineEventBlock* current = head_;
564 while (current != NULL) { 603 while (current != NULL) {
565 intptr_t length = current->length(); 604 intptr_t length = current->length();
566 for (intptr_t i = 0; i < length; i++) { 605 for (intptr_t i = 0; i < length; i++) {
567 TimelineEvent* event = current->At(i); 606 TimelineEvent* event = current->At(i);
568 if (!event->IsValid()) { 607 if (!event->IsValid()) {
569 continue; 608 continue;
570 } 609 }
571 events->AddValue(event); 610 events->AddValue(event);
572 } 611 }
573 current = current->next(); 612 current = current->next();
574 } 613 }
575 } 614 }
576 615
577 616
578 TimelineEventBlock::TimelineEventBlock() 617 TimelineEventBlock::TimelineEventBlock(intptr_t block_index)
579 : next_(NULL), 618 : next_(NULL),
580 length_(0) { 619 length_(0),
620 block_index_(block_index) {
581 } 621 }
582 622
583 623
624 TimelineEventBlock::~TimelineEventBlock() {
625 Reset();
626 }
627
628
584 TimelineEvent* TimelineEventBlock::StartEvent() { 629 TimelineEvent* TimelineEventBlock::StartEvent() {
585 ASSERT(!IsFull()); 630 ASSERT(!IsFull());
586 return &events_[length_++]; 631 return &events_[length_++];
587 } 632 }
588 633
589 634
590 ThreadId TimelineEventBlock::thread() const { 635 ThreadId TimelineEventBlock::thread() const {
591 ASSERT(length_ > 0); 636 ASSERT(length_ > 0);
592 return events_[0].thread(); 637 return events_[0].thread();
593 } 638 }
(...skipping 24 matching lines...) Expand all
618 if (last_time > At(i)->TimeOrigin()) { 663 if (last_time > At(i)->TimeOrigin()) {
619 return false; 664 return false;
620 } 665 }
621 last_time = At(i)->TimeOrigin(); 666 last_time = At(i)->TimeOrigin();
622 } 667 }
623 668
624 return true; 669 return true;
625 } 670 }
626 671
627 672
673 void TimelineEventBlock::Reset() {
674 for (intptr_t i = 0; i < kBlockSize; i++) {
675 // Clear any extra data.
676 events_[i].Reset();
677 }
678 length_ = 0;
679 }
680
681
628 TimelineEventBlockIterator::TimelineEventBlockIterator( 682 TimelineEventBlockIterator::TimelineEventBlockIterator(
629 TimelineEventEndlessRecorder* recorder) 683 TimelineEventEndlessRecorder* recorder)
630 : current_(NULL), 684 : current_(NULL),
631 recorder_(recorder) { 685 recorder_(recorder) {
632 if (recorder_ == NULL) { 686 if (recorder_ == NULL) {
633 return; 687 return;
634 } 688 }
635 recorder->lock_.Lock(); 689 recorder->lock_.Lock();
636 } 690 }
637 691
(...skipping 17 matching lines...) Expand all
655 } 709 }
656 if (current_ == NULL) { 710 if (current_ == NULL) {
657 current_ = recorder_->head_; 711 current_ = recorder_->head_;
658 } else { 712 } else {
659 current_ = current_->next(); 713 current_ = current_->next();
660 } 714 }
661 return current_ != NULL; 715 return current_ != NULL;
662 } 716 }
663 717
664 } // namespace dart 718 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/timeline.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698