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

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

Issue 1377663002: Add Timeline to dart:developer (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 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
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/atomic.h" 7 #include "vm/atomic.h"
8 #include "vm/isolate.h" 8 #include "vm/isolate.h"
9 #include "vm/json_stream.h" 9 #include "vm/json_stream.h"
10 #include "vm/lockers.h" 10 #include "vm/lockers.h"
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 472
473 TimelineEventFilter::~TimelineEventFilter() { 473 TimelineEventFilter::~TimelineEventFilter() {
474 } 474 }
475 475
476 476
477 IsolateTimelineEventFilter::IsolateTimelineEventFilter(Isolate* isolate) 477 IsolateTimelineEventFilter::IsolateTimelineEventFilter(Isolate* isolate)
478 : isolate_(isolate) { 478 : isolate_(isolate) {
479 } 479 }
480 480
481 481
482 DartTimelineEvent::DartTimelineEvent()
483 : isolate_(NULL),
484 event_as_json_(NULL) {
485 }
486
487
488 DartTimelineEvent::~DartTimelineEvent() {
489 Clear();
490 }
491
492
493 void DartTimelineEvent::Clear() {
494 if (isolate_ != NULL) {
495 isolate_ = NULL;
496 }
497 if (event_as_json_ != NULL) {
498 free(event_as_json_);
499 event_as_json_ = NULL;
500 }
501 }
502
503
504 void DartTimelineEvent::Init(Isolate* isolate, const char* event) {
505 ASSERT(isolate_ == NULL);
506 ASSERT(event != NULL);
507 isolate_ = isolate;
508 event_as_json_ = strdup(event);
509 }
510
511
482 TimelineEventRecorder::TimelineEventRecorder() 512 TimelineEventRecorder::TimelineEventRecorder()
483 : global_block_(NULL), 513 : global_block_(NULL),
484 async_id_(0) { 514 async_id_(0) {
485 } 515 }
486 516
487 517
488 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { 518 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const {
489 } 519 }
490 520
491 521
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 ASSERT(global_block_ != NULL); 573 ASSERT(global_block_ != NULL);
544 } 574 }
545 if (global_block_ != NULL) { 575 if (global_block_ != NULL) {
546 ASSERT(!global_block_->IsFull()); 576 ASSERT(!global_block_->IsFull());
547 return global_block_->StartEvent(); 577 return global_block_->StartEvent();
548 } 578 }
549 return NULL; 579 return NULL;
550 } 580 }
551 581
552 582
583 // Trims the ']' character.
584 static void TrimOutput(char* output,
585 intptr_t* output_length) {
586 ASSERT(output != NULL);
587 ASSERT(output_length != NULL);
588 ASSERT(*output_length >= 2);
589 // We expect the first character to be the opening of an array.
590 ASSERT(output[0] == '[');
591 // We expect the last character to be the closing of an array.
592 ASSERT(output[*output_length - 1] == ']');
593 // Skip the ].
594 *output_length -= 1;
595 }
596
597
553 void TimelineEventRecorder::WriteTo(const char* directory) { 598 void TimelineEventRecorder::WriteTo(const char* directory) {
554 Dart_FileOpenCallback file_open = Isolate::file_open_callback(); 599 Dart_FileOpenCallback file_open = Isolate::file_open_callback();
555 Dart_FileWriteCallback file_write = Isolate::file_write_callback(); 600 Dart_FileWriteCallback file_write = Isolate::file_write_callback();
556 Dart_FileCloseCallback file_close = Isolate::file_close_callback(); 601 Dart_FileCloseCallback file_close = Isolate::file_close_callback();
557 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) { 602 if ((file_open == NULL) || (file_write == NULL) || (file_close == NULL)) {
558 return; 603 return;
559 } 604 }
605 Thread* T = Thread::Current();
606 StackZone zone(T);
560 607
561 Timeline::ReclaimAllBlocks(); 608 Timeline::ReclaimAllBlocks();
562 609
563 JSONStream js;
564 TimelineEventFilter filter;
565 PrintJSON(&js, &filter);
566
567 intptr_t pid = OS::ProcessId(); 610 intptr_t pid = OS::ProcessId();
568 char* filename = OS::SCreate(NULL, 611 char* filename = OS::SCreate(NULL,
569 "%s/dart-timeline-%" Pd ".json", directory, pid); 612 "%s/dart-timeline-%" Pd ".json", directory, pid);
570 void* file = (*file_open)(filename, true); 613 void* file = (*file_open)(filename, true);
571 if (file == NULL) { 614 if (file == NULL) {
572 OS::Print("Failed to write timeline file: %s\n", filename); 615 OS::Print("Failed to write timeline file: %s\n", filename);
573 free(filename); 616 free(filename);
574 return; 617 return;
575 } 618 }
576 free(filename); 619 free(filename);
577 (*file_write)(js.buffer()->buf(), js.buffer()->length(), file); 620
621 JSONStream js;
622 TimelineEventFilter filter;
623 PrintTraceEvent(&js, &filter);
624 // Steal output from JSONStream.
625 char* output = NULL;
626 intptr_t output_length = 0;
627 js.Steal(const_cast<const char**>(&output), &output_length);
628 TrimOutput(output, &output_length);
629 ASSERT(output_length >= 1);
630 (*file_write)(output, output_length, file);
631 // Free the stolen output.
632 free(output);
633
634 const char* dart_events =
635 DartTimelineEventIterator::PrintTraceEvents(this,
636 zone.GetZone(),
637 NULL);
638
639 // If we wrote out vm events and have dart events, write out the comma.
640 if ((output_length > 1) && (dart_events != NULL)) {
641 // Write out the ']' character.
642 const char* comma = ",";
643 (*file_write)(comma, 1, file);
644 }
645
646 // Write out the Dart events.
647 if (dart_events != NULL) {
648 (*file_write)(dart_events, strlen(dart_events), file);
649 }
650
651 // Write out the ']' character.
652 const char* array_close = "]";
653 (*file_write)(array_close, 1, file);
578 (*file_close)(file); 654 (*file_close)(file);
655
656 return;
579 } 657 }
580 658
581 659
582 void TimelineEventRecorder::ReclaimGlobalBlock() { 660 void TimelineEventRecorder::ReclaimGlobalBlock() {
583 MutexLocker ml(&lock_); 661 MutexLocker ml(&lock_);
584 if (global_block_ != NULL) { 662 if (global_block_ != NULL) {
585 global_block_->Finish(); 663 global_block_->Finish();
586 global_block_ = NULL; 664 global_block_ = NULL;
587 } 665 }
588 } 666 }
(...skipping 19 matching lines...) Expand all
608 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() { 686 TimelineEventBlock* TimelineEventRecorder::GetNewBlock() {
609 MutexLocker ml(&lock_); 687 MutexLocker ml(&lock_);
610 return GetNewBlockLocked(Isolate::Current()); 688 return GetNewBlockLocked(Isolate::Current());
611 } 689 }
612 690
613 691
614 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity) 692 TimelineEventRingRecorder::TimelineEventRingRecorder(intptr_t capacity)
615 : blocks_(NULL), 693 : blocks_(NULL),
616 capacity_(capacity), 694 capacity_(capacity),
617 num_blocks_(0), 695 num_blocks_(0),
618 block_cursor_(0) { 696 block_cursor_(0),
697 dart_events_(NULL),
698 dart_events_capacity_(capacity),
699 dart_events_cursor_(0) {
619 // Capacity must be a multiple of TimelineEventBlock::kBlockSize 700 // Capacity must be a multiple of TimelineEventBlock::kBlockSize
620 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0); 701 ASSERT((capacity % TimelineEventBlock::kBlockSize) == 0);
621 // Allocate blocks array. 702 // Allocate blocks array.
622 num_blocks_ = capacity / TimelineEventBlock::kBlockSize; 703 num_blocks_ = capacity / TimelineEventBlock::kBlockSize;
623 blocks_ = 704 blocks_ =
624 reinterpret_cast<TimelineEventBlock**>( 705 reinterpret_cast<TimelineEventBlock**>(
625 calloc(num_blocks_, sizeof(TimelineEventBlock*))); 706 calloc(num_blocks_, sizeof(TimelineEventBlock*)));
626 // Allocate each block. 707 // Allocate each block.
627 for (intptr_t i = 0; i < num_blocks_; i++) { 708 for (intptr_t i = 0; i < num_blocks_; i++) {
628 blocks_[i] = new TimelineEventBlock(i); 709 blocks_[i] = new TimelineEventBlock(i);
629 } 710 }
630 // Chain blocks together. 711 // Chain blocks together.
631 for (intptr_t i = 0; i < num_blocks_ - 1; i++) { 712 for (intptr_t i = 0; i < num_blocks_ - 1; i++) {
632 blocks_[i]->set_next(blocks_[i + 1]); 713 blocks_[i]->set_next(blocks_[i + 1]);
633 } 714 }
715 // Pre-allocate DartTimelineEvents.
716 dart_events_ =
717 reinterpret_cast<DartTimelineEvent**>(
718 calloc(dart_events_capacity_, sizeof(DartTimelineEvent*)));
719 for (intptr_t i = 0; i < dart_events_capacity_; i++) {
720 dart_events_[i] = new DartTimelineEvent();
721 }
634 } 722 }
635 723
636 724
637 TimelineEventRingRecorder::~TimelineEventRingRecorder() { 725 TimelineEventRingRecorder::~TimelineEventRingRecorder() {
638 // Delete all blocks. 726 // Delete all blocks.
639 for (intptr_t i = 0; i < num_blocks_; i++) { 727 for (intptr_t i = 0; i < num_blocks_; i++) {
640 TimelineEventBlock* block = blocks_[i]; 728 TimelineEventBlock* block = blocks_[i];
641 delete block; 729 delete block;
642 } 730 }
643 free(blocks_); 731 free(blocks_);
732 // Delete all DartTimelineEvents.
733 for (intptr_t i = 0; i < dart_events_capacity_; i++) {
734 DartTimelineEvent* event = dart_events_[i];
735 delete event;
736 }
737 free(dart_events_);
644 } 738 }
645 739
646 740
647 void TimelineEventRingRecorder::PrintJSONEvents( 741 void TimelineEventRingRecorder::PrintJSONEvents(
648 JSONArray* events, 742 JSONArray* events,
649 TimelineEventFilter* filter) const { 743 TimelineEventFilter* filter) const {
650 intptr_t block_offset = FindOldestBlockIndex(); 744 intptr_t block_offset = FindOldestBlockIndex();
651 if (block_offset == -1) { 745 if (block_offset == -1) {
652 // All blocks are empty. 746 // All blocks are empty.
653 return; 747 return;
(...skipping 20 matching lines...) Expand all
674 JSONObject topLevel(js); 768 JSONObject topLevel(js);
675 topLevel.AddProperty("type", "_Timeline"); 769 topLevel.AddProperty("type", "_Timeline");
676 { 770 {
677 JSONArray events(&topLevel, "traceEvents"); 771 JSONArray events(&topLevel, "traceEvents");
678 PrintJSONMeta(&events); 772 PrintJSONMeta(&events);
679 PrintJSONEvents(&events, filter); 773 PrintJSONEvents(&events, filter);
680 } 774 }
681 } 775 }
682 776
683 777
778 void TimelineEventRingRecorder::AppendDartEvent(Isolate* isolate,
779 const char* event) {
780 MutexLocker ml(&lock_);
781 // TODO(johnmccutchan): If locking becomes an issue, use the Isolate to store
782 // the events.
783 if (dart_events_cursor_ == dart_events_capacity_) {
784 dart_events_cursor_ = 0;
785 }
786 ASSERT(dart_events_[dart_events_cursor_] != NULL);
787 dart_events_[dart_events_cursor_]->Clear();
788 dart_events_[dart_events_cursor_]->Init(isolate, event);
789 dart_events_cursor_++;
790 }
791
792
793 intptr_t TimelineEventRingRecorder::NumDartEventsLocked() {
794 return dart_events_capacity_;
795 }
796
797
798 DartTimelineEvent* TimelineEventRingRecorder::DartEventAtLocked(intptr_t i) {
799 ASSERT(i >= 0);
800 ASSERT(i < dart_events_capacity_);
801 return dart_events_[i];
802 }
803
804
684 void TimelineEventRingRecorder::PrintTraceEvent(JSONStream* js, 805 void TimelineEventRingRecorder::PrintTraceEvent(JSONStream* js,
685 TimelineEventFilter* filter) { 806 TimelineEventFilter* filter) {
686 JSONArray events(js); 807 JSONArray events(js);
687 PrintJSONEvents(&events, filter); 808 PrintJSONEvents(&events, filter);
688 } 809 }
689 810
690 811
691 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() { 812 TimelineEventBlock* TimelineEventRingRecorder::GetHeadBlockLocked() {
692 return blocks_[0]; 813 return blocks_[0];
693 } 814 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 } 875 }
755 876
756 877
757 void TimelineEventStreamingRecorder::PrintTraceEvent( 878 void TimelineEventStreamingRecorder::PrintTraceEvent(
758 JSONStream* js, 879 JSONStream* js,
759 TimelineEventFilter* filter) { 880 TimelineEventFilter* filter) {
760 JSONArray events(js); 881 JSONArray events(js);
761 } 882 }
762 883
763 884
885 void TimelineEventStreamingRecorder::AppendDartEvent(Isolate* isolate,
886 const char* event) {
887 if (event != NULL) {
888 StreamDartEvent(event);
889 }
890 }
891
892
893 intptr_t TimelineEventStreamingRecorder::NumDartEventsLocked() {
894 return 0;
895 }
896
897
898 DartTimelineEvent* TimelineEventStreamingRecorder::DartEventAtLocked(
899 intptr_t i) {
900 return NULL;
901 }
902
903
764 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() { 904 TimelineEvent* TimelineEventStreamingRecorder::StartEvent() {
765 TimelineEvent* event = new TimelineEvent(); 905 TimelineEvent* event = new TimelineEvent();
766 return event; 906 return event;
767 } 907 }
768 908
769 909
770 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) { 910 void TimelineEventStreamingRecorder::CompleteEvent(TimelineEvent* event) {
771 StreamEvent(event); 911 StreamEvent(event);
772 delete event; 912 delete event;
773 } 913 }
774 914
775 915
776 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder() 916 TimelineEventEndlessRecorder::TimelineEventEndlessRecorder()
777 : head_(NULL), 917 : head_(NULL),
778 block_index_(0) { 918 block_index_(0),
919 dart_events_(NULL),
920 dart_events_capacity_(0),
921 dart_events_cursor_(0) {
779 } 922 }
780 923
781 924
782 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js, 925 void TimelineEventEndlessRecorder::PrintJSON(JSONStream* js,
783 TimelineEventFilter* filter) { 926 TimelineEventFilter* filter) {
784 MutexLocker ml(&lock_); 927 MutexLocker ml(&lock_);
785 JSONObject topLevel(js); 928 JSONObject topLevel(js);
786 topLevel.AddProperty("type", "_Timeline"); 929 topLevel.AddProperty("type", "_Timeline");
787 { 930 {
788 JSONArray events(&topLevel, "traceEvents"); 931 JSONArray events(&topLevel, "traceEvents");
789 PrintJSONMeta(&events); 932 PrintJSONMeta(&events);
790 PrintJSONEvents(&events, filter); 933 PrintJSONEvents(&events, filter);
791 } 934 }
792 } 935 }
793 936
794 937
795 void TimelineEventEndlessRecorder::PrintTraceEvent( 938 void TimelineEventEndlessRecorder::PrintTraceEvent(
796 JSONStream* js, 939 JSONStream* js,
797 TimelineEventFilter* filter) { 940 TimelineEventFilter* filter) {
798 JSONArray events(js); 941 JSONArray events(js);
799 PrintJSONEvents(&events, filter); 942 PrintJSONEvents(&events, filter);
800 } 943 }
801 944
802 945
946 void TimelineEventEndlessRecorder::AppendDartEvent(Isolate* isolate,
947 const char* event) {
948 MutexLocker ml(&lock_);
949 // TODO(johnmccutchan): If locking becomes an issue, use the Isolate to store
950 // the events.
951 if (dart_events_cursor_ == dart_events_capacity_) {
952 // Grow.
953 intptr_t new_capacity =
954 (dart_events_capacity_ == 0) ? 16 : dart_events_capacity_ * 2;
955 dart_events_ = reinterpret_cast<DartTimelineEvent**>(
956 realloc(dart_events_, new_capacity * sizeof(DartTimelineEvent*)));
957 for (intptr_t i = dart_events_capacity_; i < new_capacity; i++) {
958 // Fill with NULLs.
959 dart_events_[i] = NULL;
960 }
961 dart_events_capacity_ = new_capacity;
962 }
963 ASSERT(dart_events_cursor_ < dart_events_capacity_);
964 DartTimelineEvent* dart_event = new DartTimelineEvent();
965 dart_event->Init(isolate, event);
966 ASSERT(dart_events_[dart_events_cursor_] == NULL);
967 dart_events_[dart_events_cursor_++] = dart_event;
968 }
969
970
803 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { 971 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() {
804 return head_; 972 return head_;
805 } 973 }
806 974
807 975
808 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { 976 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() {
809 return ThreadBlockStartEvent(); 977 return ThreadBlockStartEvent();
810 } 978 }
811 979
812 980
(...skipping 13 matching lines...) Expand all
826 OS::Print("Created new isolate block %p for %s\n", 994 OS::Print("Created new isolate block %p for %s\n",
827 block, isolate->name()); 995 block, isolate->name());
828 } else { 996 } else {
829 OS::Print("Created new global block %p\n", block); 997 OS::Print("Created new global block %p\n", block);
830 } 998 }
831 } 999 }
832 return head_; 1000 return head_;
833 } 1001 }
834 1002
835 1003
1004 intptr_t TimelineEventEndlessRecorder::NumDartEventsLocked() {
1005 return dart_events_cursor_;
1006 }
1007
1008
1009 DartTimelineEvent* TimelineEventEndlessRecorder::DartEventAtLocked(
1010 intptr_t i) {
1011 ASSERT(i >= 0);
1012 ASSERT(i < dart_events_cursor_);
1013 return dart_events_[i];
1014 }
1015
1016
836 void TimelineEventEndlessRecorder::PrintJSONEvents( 1017 void TimelineEventEndlessRecorder::PrintJSONEvents(
837 JSONArray* events, 1018 JSONArray* events,
838 TimelineEventFilter* filter) const { 1019 TimelineEventFilter* filter) const {
839 TimelineEventBlock* current = head_; 1020 TimelineEventBlock* current = head_;
840 1021
841 while (current != NULL) { 1022 while (current != NULL) {
842 if (!filter->IncludeBlock(current)) { 1023 if (!filter->IncludeBlock(current)) {
843 current = current->next(); 1024 current = current->next();
844 continue; 1025 continue;
845 } 1026 }
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 } 1174 }
994 1175
995 1176
996 TimelineEventBlock* TimelineEventBlockIterator::Next() { 1177 TimelineEventBlock* TimelineEventBlockIterator::Next() {
997 ASSERT(current_ != NULL); 1178 ASSERT(current_ != NULL);
998 TimelineEventBlock* r = current_; 1179 TimelineEventBlock* r = current_;
999 current_ = current_->next(); 1180 current_ = current_->next();
1000 return r; 1181 return r;
1001 } 1182 }
1002 1183
1184
1185 DartTimelineEventIterator::DartTimelineEventIterator(
1186 TimelineEventRecorder* recorder)
1187 : cursor_(0),
1188 num_events_(0),
1189 recorder_(NULL) {
1190 Reset(recorder);
1191 }
1192
1193
1194 DartTimelineEventIterator::~DartTimelineEventIterator() {
1195 Reset(NULL);
1196 }
1197
1198
1199 void DartTimelineEventIterator::Reset(TimelineEventRecorder* recorder) {
1200 // Clear state.
1201 cursor_ = 0;
1202 num_events_ = 0;
1203 if (recorder_ != NULL) {
1204 // Unlock old recorder.
1205 recorder_->lock_.Unlock();
1206 }
1207 recorder_ = recorder;
1208 if (recorder_ == NULL) {
1209 return;
1210 }
1211 // Lock new recorder.
1212 recorder_->lock_.Lock();
1213 cursor_ = 0;
1214 num_events_ = recorder_->NumDartEventsLocked();
1215 }
1216
1217
1218 bool DartTimelineEventIterator::HasNext() const {
1219 return cursor_ < num_events_;
1220 }
1221
1222
1223 DartTimelineEvent* DartTimelineEventIterator::Next() {
1224 ASSERT(cursor_ < num_events_);
1225 DartTimelineEvent* r = recorder_->DartEventAtLocked(cursor_);
1226 cursor_++;
1227 return r;
1228 }
1229
1230 const char* DartTimelineEventIterator::PrintTraceEvents(
1231 TimelineEventRecorder* recorder,
1232 Zone* zone,
1233 Isolate* isolate) {
1234 if (recorder == NULL) {
1235 return NULL;
1236 }
1237
1238 if (zone == NULL) {
1239 return NULL;
1240 }
1241
1242 char* result = NULL;
1243 DartTimelineEventIterator iterator(recorder);
1244 while (iterator.HasNext()) {
1245 DartTimelineEvent* event = iterator.Next();
1246 if (!event->IsValid()) {
1247 // Skip invalid
1248 continue;
1249 }
1250 if ((isolate != NULL) && (isolate != event->isolate())) {
1251 // If an isolate was specified, skip events from other isolates.
1252 continue;
1253 }
1254 ASSERT(event->event_as_json() != NULL);
1255 result = zone->ConcatStrings(result, event->event_as_json());
1256 }
1257 return result;
1258 }
1259
1003 } // namespace dart 1260 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698