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

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

Issue 1395803002: Stop holding onto TimelineEvents (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
« 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/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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 int64_t micros) { 271 int64_t micros) {
272 Init(kEnd, label); 272 Init(kEnd, label);
273 timestamp0_ = micros; 273 timestamp0_ = micros;
274 } 274 }
275 275
276 276
277 void TimelineEvent::SetNumArguments(intptr_t length) { 277 void TimelineEvent::SetNumArguments(intptr_t length) {
278 // Cannot call this twice. 278 // Cannot call this twice.
279 ASSERT(arguments_ == NULL); 279 ASSERT(arguments_ == NULL);
280 ASSERT(arguments_length_ == 0); 280 ASSERT(arguments_length_ == 0);
281 if (length == 0) {
282 return;
283 }
281 arguments_length_ = length; 284 arguments_length_ = length;
282 arguments_ = reinterpret_cast<TimelineEventArgument*>( 285 arguments_ = reinterpret_cast<TimelineEventArgument*>(
283 calloc(sizeof(TimelineEventArgument), length)); 286 calloc(sizeof(TimelineEventArgument), length));
284 } 287 }
285 288
286 289
287 void TimelineEvent::SetArgument(intptr_t i, const char* name, char* argument) { 290 void TimelineEvent::SetArgument(intptr_t i, const char* name, char* argument) {
288 ASSERT(i >= 0); 291 ASSERT(i >= 0);
289 ASSERT(i < arguments_length_); 292 ASSERT(i < arguments_length_);
290 arguments_[i].name = name; 293 arguments_[i].name = name;
(...skipping 20 matching lines...) Expand all
311 } 314 }
312 315
313 316
314 void TimelineEvent::CopyArgument(intptr_t i, 317 void TimelineEvent::CopyArgument(intptr_t i,
315 const char* name, 318 const char* name,
316 const char* argument) { 319 const char* argument) {
317 SetArgument(i, name, strdup(argument)); 320 SetArgument(i, name, strdup(argument));
318 } 321 }
319 322
320 323
324 void TimelineEvent::StealArguments(intptr_t arguments_length,
325 TimelineEventArgument* arguments) {
326 arguments_length_ = arguments_length;
327 arguments_ = arguments;
328 }
329
330
321 void TimelineEvent::Complete() { 331 void TimelineEvent::Complete() {
322 TimelineEventRecorder* recorder = Timeline::recorder(); 332 TimelineEventRecorder* recorder = Timeline::recorder();
323 if (recorder != NULL) { 333 if (recorder != NULL) {
324 recorder->CompleteEvent(this); 334 recorder->CompleteEvent(this);
325 } 335 }
326 } 336 }
327 337
328 338
329 void TimelineEvent::FreeArguments() { 339 void TimelineEvent::FreeArguments() {
330 if (arguments_ == NULL) { 340 if (arguments_ == NULL) {
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 } 470 }
461 ASSERT(name_ != NULL); 471 ASSERT(name_ != NULL);
462 TimelineEvent* event = recorder->StartEvent(); 472 TimelineEvent* event = recorder->StartEvent();
463 if (event != NULL) { 473 if (event != NULL) {
464 event->StreamInit(this); 474 event->StreamInit(this);
465 } 475 }
466 return event; 476 return event;
467 } 477 }
468 478
469 479
480 TimelineDurationScope::TimelineDurationScope(TimelineStream* stream,
481 const char* label)
482 : StackResource(reinterpret_cast<Thread*>(NULL)),
483 timestamp_(0),
484 stream_(stream),
485 label_(label),
486 arguments_(NULL),
487 arguments_length_(0),
488 enabled_(false) {
489 Init();
490 }
491
492
493 TimelineDurationScope::TimelineDurationScope(Thread* thread,
494 TimelineStream* stream,
495 const char* label)
496 : StackResource(thread),
497 timestamp_(0),
498 stream_(stream),
499 label_(label),
500 arguments_(NULL),
501 arguments_length_(0),
502 enabled_(false) {
503 ASSERT(thread != NULL);
504 Init();
505 }
506
507
508 TimelineDurationScope::~TimelineDurationScope() {
509 if (!enabled_) {
510 FreeArguments();
511 return;
512 }
513 TimelineEvent* event = stream_->StartEvent();
514 ASSERT(event != NULL);
515 event->Duration(label_, timestamp_, OS::GetCurrentTraceMicros());
516 event->StealArguments(arguments_length_, arguments_);
517 event->Complete();
518 arguments_length_ = 0;
519 arguments_ = NULL;
520 }
521
522
523 void TimelineDurationScope::Init() {
524 ASSERT(enabled_ == false);
525 ASSERT(label_ != NULL);
526 ASSERT(stream_ != NULL);
527 if (!stream_->Enabled()) {
528 // Stream is not enabled, do nothing.
529 return;
530 }
531 timestamp_ = OS::GetCurrentTraceMicros();
532 enabled_ = true;
533 }
534
535
536 void TimelineDurationScope::SetNumArguments(intptr_t length) {
537 if (!enabled()) {
538 return;
539 }
540 ASSERT(arguments_ == NULL);
541 ASSERT(arguments_length_ == 0);
542 arguments_length_ = length;
543 if (arguments_length_ == 0) {
544 return;
545 }
546 arguments_ = reinterpret_cast<TimelineEventArgument*>(
547 calloc(sizeof(TimelineEventArgument), length));
548 }
549
550
551 // |name| must be a compile time constant. Takes ownership of |argumentp|.
552 void TimelineDurationScope::SetArgument(intptr_t i,
553 const char* name,
554 char* argument) {
555 if (!enabled()) {
556 return;
557 }
558 ASSERT(i >= 0);
559 ASSERT(i < arguments_length_);
560 arguments_[i].name = name;
561 arguments_[i].value = argument;
562 }
563
564
565 // |name| must be a compile time constant. Copies |argument|.
566 void TimelineDurationScope::CopyArgument(intptr_t i,
567 const char* name,
568 const char* argument) {
569 if (!enabled()) {
570 return;
571 }
572 SetArgument(i, name, strdup(argument));
573 }
574
575
470 void TimelineDurationScope::FormatArgument(intptr_t i, 576 void TimelineDurationScope::FormatArgument(intptr_t i,
471 const char* name, 577 const char* name,
472 const char* fmt, ...) { 578 const char* fmt, ...) {
473 if (event_ == NULL) { 579 if (!enabled()) {
474 return; 580 return;
475 } 581 }
476 va_list args; 582 va_list args;
477 va_start(args, fmt); 583 va_start(args, fmt);
478 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args); 584 intptr_t len = OS::VSNPrint(NULL, 0, fmt, args);
479 va_end(args); 585 va_end(args);
480 586
481 char* buffer = reinterpret_cast<char*>(malloc(len + 1)); 587 char* buffer = reinterpret_cast<char*>(malloc(len + 1));
482 va_list args2; 588 va_list args2;
483 va_start(args2, fmt); 589 va_start(args2, fmt);
484 OS::VSNPrint(buffer, (len + 1), fmt, args2); 590 OS::VSNPrint(buffer, (len + 1), fmt, args2);
485 va_end(args2); 591 va_end(args2);
486 592
487 event_->SetArgument(i, name, buffer); 593 SetArgument(i, name, buffer);
488 } 594 }
489 595
490 596
597 void TimelineDurationScope::FreeArguments() {
598 if (arguments_ == NULL) {
599 return;
600 }
601 for (intptr_t i = 0; i < arguments_length_; i++) {
602 free(arguments_[i].value);
603 }
604 free(arguments_);
605 arguments_ = NULL;
606 arguments_length_ = 0;
607 }
608
609
491 TimelineEventFilter::TimelineEventFilter() { 610 TimelineEventFilter::TimelineEventFilter() {
492 } 611 }
493 612
494 613
495 TimelineEventFilter::~TimelineEventFilter() { 614 TimelineEventFilter::~TimelineEventFilter() {
496 } 615 }
497 616
498 617
499 IsolateTimelineEventFilter::IsolateTimelineEventFilter(Isolate* isolate) 618 IsolateTimelineEventFilter::IsolateTimelineEventFilter(Isolate* isolate)
500 : isolate_(isolate) { 619 : isolate_(isolate) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 657
539 658
540 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const { 659 void TimelineEventRecorder::PrintJSONMeta(JSONArray* events) const {
541 } 660 }
542 661
543 662
544 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() { 663 TimelineEvent* TimelineEventRecorder::ThreadBlockStartEvent() {
545 // Grab the current thread. 664 // Grab the current thread.
546 Thread* thread = Thread::Current(); 665 Thread* thread = Thread::Current();
547 ASSERT(thread != NULL); 666 ASSERT(thread != NULL);
548 // We are accessing the thread's timeline block- so take the lock. 667 ASSERT(thread->isolate() != NULL);
549 MutexLocker ml(thread->timeline_block_lock()); 668 Mutex* thread_block_lock = thread->timeline_block_lock();
550 669 ASSERT(thread_block_lock != NULL);
551 if (thread->isolate() == NULL) { 670 // We are accessing the thread's timeline block- so take the lock here.
552 // Non-isolate thread case. This should be infrequent. 671 // This lock will be held until the call to |CompleteEvent| is made.
553 return GlobalBlockStartEvent(); 672 thread_block_lock->Lock();
554 }
555 673
556 TimelineEventBlock* thread_block = thread->timeline_block(); 674 TimelineEventBlock* thread_block = thread->timeline_block();
557 675
558 if ((thread_block != NULL) && thread_block->IsFull()) { 676 if ((thread_block != NULL) && thread_block->IsFull()) {
559 MutexLocker ml(&lock_); 677 MutexLocker ml(&lock_);
560 // Thread has a block and it is full: 678 // Thread has a block and it is full:
561 // 1) Mark it as finished. 679 // 1) Mark it as finished.
562 thread_block->Finish(); 680 thread_block->Finish();
563 // 2) Allocate a new block. 681 // 2) Allocate a new block.
564 thread_block = GetNewBlockLocked(thread->isolate()); 682 thread_block = GetNewBlockLocked(thread->isolate());
565 thread->set_timeline_block(thread_block); 683 thread->set_timeline_block(thread_block);
566 } else if (thread_block == NULL) { 684 } else if (thread_block == NULL) {
567 MutexLocker ml(&lock_); 685 MutexLocker ml(&lock_);
568 // Thread has no block. Attempt to allocate one. 686 // Thread has no block. Attempt to allocate one.
569 thread_block = GetNewBlockLocked(thread->isolate()); 687 thread_block = GetNewBlockLocked(thread->isolate());
570 thread->set_timeline_block(thread_block); 688 thread->set_timeline_block(thread_block);
571 } 689 }
572 if (thread_block != NULL) { 690 if (thread_block != NULL) {
691 // NOTE: We are exiting this function with the thread's block lock held.
573 ASSERT(!thread_block->IsFull()); 692 ASSERT(!thread_block->IsFull());
574 return thread_block->StartEvent(); 693 TimelineEvent* event = thread_block->StartEvent();
694 if (event != NULL) {
695 event->set_global_block(false);
696 }
697 return event;
575 } 698 }
699 // Drop lock here as no event is being handed out.
700 thread_block_lock->Unlock();
576 return NULL; 701 return NULL;
577 } 702 }
578 703
579 704
580
581 TimelineEvent* TimelineEventRecorder::GlobalBlockStartEvent() { 705 TimelineEvent* TimelineEventRecorder::GlobalBlockStartEvent() {
582 MutexLocker ml(&lock_); 706 // Take recorder lock. This lock will be held until the call to
707 // |CompleteEvent| is made.
708 lock_.Lock();
583 if (FLAG_trace_timeline) { 709 if (FLAG_trace_timeline) {
584 OS::Print("GlobalBlockStartEvent in block %p for thread %" Px "\n", 710 OS::Print("GlobalBlockStartEvent in block %p for thread %" Px "\n",
585 global_block_, OSThread::CurrentCurrentThreadIdAsIntPtr()); 711 global_block_, OSThread::CurrentCurrentThreadIdAsIntPtr());
586 } 712 }
587 if ((global_block_ != NULL) && global_block_->IsFull()) { 713 if ((global_block_ != NULL) && global_block_->IsFull()) {
588 // Global block is full. 714 // Global block is full.
589 global_block_->Finish(); 715 global_block_->Finish();
590 global_block_ = NULL; 716 global_block_ = NULL;
591 } 717 }
592 if (global_block_ == NULL) { 718 if (global_block_ == NULL) {
593 // Allocate a new block. 719 // Allocate a new block.
594 global_block_ = GetNewBlockLocked(NULL); 720 global_block_ = GetNewBlockLocked(NULL);
595 ASSERT(global_block_ != NULL); 721 ASSERT(global_block_ != NULL);
596 } 722 }
597 if (global_block_ != NULL) { 723 if (global_block_ != NULL) {
724 // NOTE: We are exiting this function with the recorder's lock held.
598 ASSERT(!global_block_->IsFull()); 725 ASSERT(!global_block_->IsFull());
599 return global_block_->StartEvent(); 726 TimelineEvent* event = global_block_->StartEvent();
727 if (event != NULL) {
728 event->set_global_block(true);
729 }
730 return event;
600 } 731 }
732 // Drop lock here as no event is being handed out.
733 lock_.Unlock();
601 return NULL; 734 return NULL;
602 } 735 }
603 736
604 737
738 void TimelineEventRecorder::ThreadBlockCompleteEvent(TimelineEvent* event) {
739 if (event == NULL) {
740 return;
741 }
742 ASSERT(!event->global_block());
743 // Grab the current thread.
744 Thread* thread = Thread::Current();
745 ASSERT(thread != NULL);
746 ASSERT(thread->isolate() != NULL);
747 // This event came from the isolate's thread local block. Unlock the
748 // thread's block lock.
749 Mutex* thread_block_lock = thread->timeline_block_lock();
750 ASSERT(thread_block_lock != NULL);
751 thread_block_lock->Unlock();
752 }
753
754
755 void TimelineEventRecorder::GlobalBlockCompleteEvent(TimelineEvent* event) {
756 if (event == NULL) {
757 return;
758 }
759 ASSERT(event->global_block());
760 // This event came from the global block, unlock the recorder's lock now
761 // that the event is filled.
762 lock_.Unlock();
763 }
764
765
605 // Trims the ']' character. 766 // Trims the ']' character.
606 static void TrimOutput(char* output, 767 static void TrimOutput(char* output,
607 intptr_t* output_length) { 768 intptr_t* output_length) {
608 ASSERT(output != NULL); 769 ASSERT(output != NULL);
609 ASSERT(output_length != NULL); 770 ASSERT(output_length != NULL);
610 ASSERT(*output_length >= 2); 771 ASSERT(*output_length >= 2);
611 // We expect the first character to be the opening of an array. 772 // We expect the first character to be the opening of an array.
612 ASSERT(output[0] == '['); 773 ASSERT(output[0] == '[');
613 // We expect the last character to be the closing of an array. 774 // We expect the last character to be the closing of an array.
614 ASSERT(output[*output_length - 1] == ']'); 775 ASSERT(output[*output_length - 1] == ']');
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 if (block->LowerTimeBound() < earliest_time) { 1023 if (block->LowerTimeBound() < earliest_time) {
863 earliest_time = block->LowerTimeBound(); 1024 earliest_time = block->LowerTimeBound();
864 earliest_index = block_idx; 1025 earliest_index = block_idx;
865 } 1026 }
866 } 1027 }
867 return earliest_index; 1028 return earliest_index;
868 } 1029 }
869 1030
870 1031
871 TimelineEvent* TimelineEventRingRecorder::StartEvent() { 1032 TimelineEvent* TimelineEventRingRecorder::StartEvent() {
1033 // Grab the current thread.
1034 Thread* thread = Thread::Current();
1035 ASSERT(thread != NULL);
1036 if (thread->isolate() == NULL) {
1037 // Non-isolate thread case. This should be infrequent.
1038 return GlobalBlockStartEvent();
1039 }
872 return ThreadBlockStartEvent(); 1040 return ThreadBlockStartEvent();
873 } 1041 }
874 1042
875 1043
876 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) { 1044 void TimelineEventRingRecorder::CompleteEvent(TimelineEvent* event) {
877 // no-op. 1045 if (event == NULL) {
1046 return;
1047 }
1048 if (event->global_block()) {
1049 GlobalBlockCompleteEvent(event);
1050 } else {
1051 ThreadBlockCompleteEvent(event);
1052 }
878 } 1053 }
879 1054
880 1055
881 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() { 1056 TimelineEventStreamingRecorder::TimelineEventStreamingRecorder() {
882 } 1057 }
883 1058
884 1059
885 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() { 1060 TimelineEventStreamingRecorder::~TimelineEventStreamingRecorder() {
886 } 1061 }
887 1062
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
989 dart_events_[dart_events_cursor_++] = dart_event; 1164 dart_events_[dart_events_cursor_++] = dart_event;
990 } 1165 }
991 1166
992 1167
993 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() { 1168 TimelineEventBlock* TimelineEventEndlessRecorder::GetHeadBlockLocked() {
994 return head_; 1169 return head_;
995 } 1170 }
996 1171
997 1172
998 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() { 1173 TimelineEvent* TimelineEventEndlessRecorder::StartEvent() {
1174 // Grab the current thread.
1175 Thread* thread = Thread::Current();
1176 ASSERT(thread != NULL);
1177 if (thread->isolate() == NULL) {
1178 // Non-isolate thread case. This should be infrequent.
1179 return GlobalBlockStartEvent();
1180 }
999 return ThreadBlockStartEvent(); 1181 return ThreadBlockStartEvent();
1000 } 1182 }
1001 1183
1002 1184
1003 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) { 1185 void TimelineEventEndlessRecorder::CompleteEvent(TimelineEvent* event) {
1004 // no-op. 1186 if (event == NULL) {
1187 return;
1188 }
1189 if (event->global_block()) {
1190 GlobalBlockCompleteEvent(event);
1191 } else {
1192 ThreadBlockCompleteEvent(event);
1193 }
1005 } 1194 }
1006 1195
1007 1196
1008 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked( 1197 TimelineEventBlock* TimelineEventEndlessRecorder::GetNewBlockLocked(
1009 Isolate* isolate) { 1198 Isolate* isolate) {
1010 TimelineEventBlock* block = new TimelineEventBlock(block_index_++); 1199 TimelineEventBlock* block = new TimelineEventBlock(block_index_++);
1011 block->set_next(head_); 1200 block->set_next(head_);
1012 block->Open(isolate); 1201 block->Open(isolate);
1013 head_ = block; 1202 head_ = block;
1014 if (FLAG_trace_timeline) { 1203 if (FLAG_trace_timeline) {
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 // If an isolate was specified, skip events from other isolates. 1462 // If an isolate was specified, skip events from other isolates.
1274 continue; 1463 continue;
1275 } 1464 }
1276 ASSERT(event->event_as_json() != NULL); 1465 ASSERT(event->event_as_json() != NULL);
1277 result = zone->ConcatStrings(result, event->event_as_json()); 1466 result = zone->ConcatStrings(result, event->event_as_json());
1278 } 1467 }
1279 return result; 1468 return result;
1280 } 1469 }
1281 1470
1282 } // namespace dart 1471 } // 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