| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/tracked_objects.h" | 5 #include "base/tracked_objects.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 | 21 |
| 22 using base::TimeDelta; | 22 using base::TimeDelta; |
| 23 | 23 |
| 24 namespace base { | 24 namespace base { |
| 25 class TimeDelta; | 25 class TimeDelta; |
| 26 } | 26 } |
| 27 | 27 |
| 28 namespace tracked_objects { | 28 namespace tracked_objects { |
| 29 | 29 |
| 30 namespace { | 30 namespace { |
| 31 // TODO(jar): Evaluate the perf impact of enabling this. If the perf impact is | |
| 32 // negligible, enable by default. | |
| 33 // Flag to compile out parent-child link recording. | |
| 34 const bool kTrackParentChildLinks = false; | |
| 35 | |
| 36 // When ThreadData is first initialized, should we start in an ACTIVE state to | 31 // When ThreadData is first initialized, should we start in an ACTIVE state to |
| 37 // record all of the startup-time tasks, or should we start up DEACTIVATED, so | 32 // record all of the startup-time tasks, or should we start up DEACTIVATED, so |
| 38 // that we only record after parsing the command line flag --enable-tracking. | 33 // that we only record after parsing the command line flag --enable-tracking. |
| 39 // Note that the flag may force either state, so this really controls only the | 34 // Note that the flag may force either state, so this really controls only the |
| 40 // period of time up until that flag is parsed. If there is no flag seen, then | 35 // period of time up until that flag is parsed. If there is no flag seen, then |
| 41 // this state may prevail for much or all of the process lifetime. | 36 // this state may prevail for much or all of the process lifetime. |
| 42 const ThreadData::Status kInitialStartupState = | 37 const ThreadData::Status kInitialStartupState = ThreadData::PROFILING_ACTIVE; |
| 43 ThreadData::PROFILING_CHILDREN_ACTIVE; | |
| 44 | 38 |
| 45 // Control whether an alternate time source (Now() function) is supported by | 39 // Control whether an alternate time source (Now() function) is supported by |
| 46 // the ThreadData class. This compile time flag should be set to true if we | 40 // the ThreadData class. This compile time flag should be set to true if we |
| 47 // want other modules (such as a memory allocator, or a thread-specific CPU time | 41 // want other modules (such as a memory allocator, or a thread-specific CPU time |
| 48 // clock) to be able to provide a thread-specific Now() function. Without this | 42 // clock) to be able to provide a thread-specific Now() function. Without this |
| 49 // compile-time flag, the code will only support the wall-clock time. This flag | 43 // compile-time flag, the code will only support the wall-clock time. This flag |
| 50 // can be flipped to efficiently disable this path (if there is a performance | 44 // can be flipped to efficiently disable this path (if there is a performance |
| 51 // problem with its presence). | 45 // problem with its presence). |
| 52 static const bool kAllowAlternateTimeSourceHandling = true; | 46 static const bool kAllowAlternateTimeSourceHandling = true; |
| 53 | 47 |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 child = it->second; | 515 child = it->second; |
| 522 child->RecordBirth(); | 516 child->RecordBirth(); |
| 523 } else { | 517 } else { |
| 524 child = new Births(location, *this); // Leak this. | 518 child = new Births(location, *this); // Leak this. |
| 525 // Lock since the map may get relocated now, and other threads sometimes | 519 // Lock since the map may get relocated now, and other threads sometimes |
| 526 // snapshot it (but they lock before copying it). | 520 // snapshot it (but they lock before copying it). |
| 527 base::AutoLock lock(map_lock_); | 521 base::AutoLock lock(map_lock_); |
| 528 birth_map_[location] = child; | 522 birth_map_[location] = child; |
| 529 } | 523 } |
| 530 | 524 |
| 531 if (kTrackParentChildLinks && status_ > PROFILING_ACTIVE && | |
| 532 !parent_stack_.empty()) { | |
| 533 const Births* parent = parent_stack_.top(); | |
| 534 ParentChildPair pair(parent, child); | |
| 535 if (parent_child_set_.find(pair) == parent_child_set_.end()) { | |
| 536 // Lock since the map may get relocated now, and other threads sometimes | |
| 537 // snapshot it (but they lock before copying it). | |
| 538 base::AutoLock lock(map_lock_); | |
| 539 parent_child_set_.insert(pair); | |
| 540 } | |
| 541 } | |
| 542 | |
| 543 return child; | 525 return child; |
| 544 } | 526 } |
| 545 | 527 |
| 546 void ThreadData::TallyADeath(const Births& births, | 528 void ThreadData::TallyADeath(const Births& births, |
| 547 int32 queue_duration, | 529 int32 queue_duration, |
| 548 const TaskStopwatch& stopwatch) { | 530 const TaskStopwatch& stopwatch) { |
| 549 int32 run_duration = stopwatch.RunDurationMs(); | 531 int32 run_duration = stopwatch.RunDurationMs(); |
| 550 | 532 |
| 551 // Stir in some randomness, plus add constant in case durations are zero. | 533 // Stir in some randomness, plus add constant in case durations are zero. |
| 552 const uint32 kSomePrimeNumber = 2147483647; | 534 const uint32 kSomePrimeNumber = 2147483647; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 566 | 548 |
| 567 DeathMap::iterator it = death_map_.find(&births); | 549 DeathMap::iterator it = death_map_.find(&births); |
| 568 DeathData* death_data; | 550 DeathData* death_data; |
| 569 if (it != death_map_.end()) { | 551 if (it != death_map_.end()) { |
| 570 death_data = &it->second; | 552 death_data = &it->second; |
| 571 } else { | 553 } else { |
| 572 base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. | 554 base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. |
| 573 death_data = &death_map_[&births]; | 555 death_data = &death_map_[&births]; |
| 574 } // Release lock ASAP. | 556 } // Release lock ASAP. |
| 575 death_data->RecordDeath(queue_duration, run_duration, random_number_); | 557 death_data->RecordDeath(queue_duration, run_duration, random_number_); |
| 576 | |
| 577 if (!kTrackParentChildLinks) | |
| 578 return; | |
| 579 if (!parent_stack_.empty()) { // We might get turned off. | |
| 580 DCHECK_EQ(parent_stack_.top(), &births); | |
| 581 parent_stack_.pop(); | |
| 582 } | |
| 583 } | 558 } |
| 584 | 559 |
| 585 // static | 560 // static |
| 586 Births* ThreadData::TallyABirthIfActive(const Location& location) { | 561 Births* ThreadData::TallyABirthIfActive(const Location& location) { |
| 587 if (!TrackingStatus()) | 562 if (!TrackingStatus()) |
| 588 return NULL; | 563 return NULL; |
| 589 ThreadData* current_thread_data = Get(); | 564 ThreadData* current_thread_data = Get(); |
| 590 if (!current_thread_data) | 565 if (!current_thread_data) |
| 591 return NULL; | 566 return NULL; |
| 592 return current_thread_data->TallyABirth(location); | 567 return current_thread_data->TallyABirth(location); |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 } | 646 } |
| 672 | 647 |
| 673 void ThreadData::SnapshotExecutedTasks( | 648 void ThreadData::SnapshotExecutedTasks( |
| 674 int current_profiling_phase, | 649 int current_profiling_phase, |
| 675 PhasedProcessDataSnapshotMap* phased_snapshots, | 650 PhasedProcessDataSnapshotMap* phased_snapshots, |
| 676 BirthCountMap* birth_counts) { | 651 BirthCountMap* birth_counts) { |
| 677 // Get copy of data, so that the data will not change during the iterations | 652 // Get copy of data, so that the data will not change during the iterations |
| 678 // and processing. | 653 // and processing. |
| 679 BirthMap birth_map; | 654 BirthMap birth_map; |
| 680 DeathsSnapshot deaths; | 655 DeathsSnapshot deaths; |
| 681 ParentChildSet parent_child_set; | 656 SnapshotMaps(current_profiling_phase, &birth_map, &deaths); |
| 682 SnapshotMaps(current_profiling_phase, &birth_map, &deaths, &parent_child_set); | |
| 683 | 657 |
| 684 for (const auto& birth : birth_map) { | 658 for (const auto& birth : birth_map) { |
| 685 (*birth_counts)[birth.second] += birth.second->birth_count(); | 659 (*birth_counts)[birth.second] += birth.second->birth_count(); |
| 686 } | 660 } |
| 687 | 661 |
| 688 for (const auto& death : deaths) { | 662 for (const auto& death : deaths) { |
| 689 (*birth_counts)[death.first] -= death.first->birth_count(); | 663 (*birth_counts)[death.first] -= death.first->birth_count(); |
| 690 | 664 |
| 691 // For the current death data, walk through all its snapshots, starting from | 665 // For the current death data, walk through all its snapshots, starting from |
| 692 // the current one, then from the previous profiling phase etc., and for | 666 // the current one, then from the previous profiling phase etc., and for |
| (...skipping 10 matching lines...) Expand all Loading... |
| 703 TaskSnapshot(BirthOnThreadSnapshot(*death.first), death_data, | 677 TaskSnapshot(BirthOnThreadSnapshot(*death.first), death_data, |
| 704 thread_name())); | 678 thread_name())); |
| 705 } | 679 } |
| 706 } | 680 } |
| 707 } | 681 } |
| 708 } | 682 } |
| 709 | 683 |
| 710 // This may be called from another thread. | 684 // This may be called from another thread. |
| 711 void ThreadData::SnapshotMaps(int profiling_phase, | 685 void ThreadData::SnapshotMaps(int profiling_phase, |
| 712 BirthMap* birth_map, | 686 BirthMap* birth_map, |
| 713 DeathsSnapshot* deaths, | 687 DeathsSnapshot* deaths) { |
| 714 ParentChildSet* parent_child_set) { | |
| 715 base::AutoLock lock(map_lock_); | 688 base::AutoLock lock(map_lock_); |
| 716 | 689 |
| 717 for (const auto& birth : birth_map_) | 690 for (const auto& birth : birth_map_) |
| 718 (*birth_map)[birth.first] = birth.second; | 691 (*birth_map)[birth.first] = birth.second; |
| 719 | 692 |
| 720 for (const auto& death : death_map_) { | 693 for (const auto& death : death_map_) { |
| 721 deaths->push_back(std::make_pair( | 694 deaths->push_back(std::make_pair( |
| 722 death.first, | 695 death.first, |
| 723 DeathDataPhaseSnapshot(profiling_phase, death.second.count(), | 696 DeathDataPhaseSnapshot(profiling_phase, death.second.count(), |
| 724 death.second.run_duration_sum(), | 697 death.second.run_duration_sum(), |
| 725 death.second.run_duration_max(), | 698 death.second.run_duration_max(), |
| 726 death.second.run_duration_sample(), | 699 death.second.run_duration_sample(), |
| 727 death.second.queue_duration_sum(), | 700 death.second.queue_duration_sum(), |
| 728 death.second.queue_duration_max(), | 701 death.second.queue_duration_max(), |
| 729 death.second.queue_duration_sample(), | 702 death.second.queue_duration_sample(), |
| 730 death.second.last_phase_snapshot()))); | 703 death.second.last_phase_snapshot()))); |
| 731 } | 704 } |
| 732 | |
| 733 if (!kTrackParentChildLinks) | |
| 734 return; | |
| 735 | |
| 736 for (const auto& parent_child : parent_child_set_) | |
| 737 parent_child_set->insert(parent_child); | |
| 738 } | 705 } |
| 739 | 706 |
| 740 void ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { | 707 void ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { |
| 741 base::AutoLock lock(map_lock_); | 708 base::AutoLock lock(map_lock_); |
| 742 | 709 |
| 743 for (auto& death : death_map_) { | 710 for (auto& death : death_map_) { |
| 744 death.second.OnProfilingPhaseCompleted(profiling_phase); | 711 death.second.OnProfilingPhaseCompleted(profiling_phase); |
| 745 } | 712 } |
| 746 } | 713 } |
| 747 | 714 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 784 } | 751 } |
| 785 | 752 |
| 786 // Incarnation counter is only significant to testing, as it otherwise will | 753 // Incarnation counter is only significant to testing, as it otherwise will |
| 787 // never again change in this process. | 754 // never again change in this process. |
| 788 ++incarnation_counter_; | 755 ++incarnation_counter_; |
| 789 | 756 |
| 790 // The lock is not critical for setting status_, but it doesn't hurt. It also | 757 // The lock is not critical for setting status_, but it doesn't hurt. It also |
| 791 // ensures that if we have a racy initialization, that we'll bail as soon as | 758 // ensures that if we have a racy initialization, that we'll bail as soon as |
| 792 // we get the lock earlier in this method. | 759 // we get the lock earlier in this method. |
| 793 status_ = kInitialStartupState; | 760 status_ = kInitialStartupState; |
| 794 if (!kTrackParentChildLinks && | |
| 795 kInitialStartupState == PROFILING_CHILDREN_ACTIVE) | |
| 796 status_ = PROFILING_ACTIVE; | |
| 797 DCHECK(status_ != UNINITIALIZED); | 761 DCHECK(status_ != UNINITIALIZED); |
| 798 return true; | 762 return true; |
| 799 } | 763 } |
| 800 | 764 |
| 801 // static | 765 // static |
| 802 bool ThreadData::InitializeAndSetTrackingStatus(Status status) { | 766 bool ThreadData::InitializeAndSetTrackingStatus(Status status) { |
| 803 DCHECK_GE(status, DEACTIVATED); | 767 DCHECK_GE(status, DEACTIVATED); |
| 804 DCHECK_LE(status, PROFILING_CHILDREN_ACTIVE); | 768 DCHECK_LE(status, PROFILING_ACTIVE); |
| 805 | 769 |
| 806 if (!Initialize()) // No-op if already initialized. | 770 if (!Initialize()) // No-op if already initialized. |
| 807 return false; // Not compiled in. | 771 return false; // Not compiled in. |
| 808 | 772 |
| 809 if (!kTrackParentChildLinks && status > DEACTIVATED) | 773 if (status > DEACTIVATED) |
| 810 status = PROFILING_ACTIVE; | 774 status = PROFILING_ACTIVE; |
| 811 status_ = status; | 775 status_ = status; |
| 812 return true; | 776 return true; |
| 813 } | 777 } |
| 814 | 778 |
| 815 // static | 779 // static |
| 816 ThreadData::Status ThreadData::status() { | 780 ThreadData::Status ThreadData::status() { |
| 817 return status_; | 781 return status_; |
| 818 } | 782 } |
| 819 | 783 |
| 820 // static | 784 // static |
| 821 bool ThreadData::TrackingStatus() { | 785 bool ThreadData::TrackingStatus() { |
| 822 return status_ > DEACTIVATED; | 786 return status_ > DEACTIVATED; |
| 823 } | 787 } |
| 824 | 788 |
| 825 // static | 789 // static |
| 826 bool ThreadData::TrackingParentChildStatus() { | |
| 827 return status_ >= PROFILING_CHILDREN_ACTIVE; | |
| 828 } | |
| 829 | |
| 830 // static | |
| 831 void ThreadData::PrepareForStartOfRun(const Births* parent) { | |
| 832 if (kTrackParentChildLinks && parent && status_ > PROFILING_ACTIVE) { | |
| 833 ThreadData* current_thread_data = Get(); | |
| 834 if (current_thread_data) | |
| 835 current_thread_data->parent_stack_.push(parent); | |
| 836 } | |
| 837 } | |
| 838 | |
| 839 // static | |
| 840 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { | 790 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { |
| 841 DCHECK(now_function); | 791 DCHECK(now_function); |
| 842 if (kAllowAlternateTimeSourceHandling) | 792 if (kAllowAlternateTimeSourceHandling) |
| 843 now_function_ = now_function; | 793 now_function_ = now_function; |
| 844 } | 794 } |
| 845 | 795 |
| 846 // static | 796 // static |
| 847 void ThreadData::EnableProfilerTiming() { | 797 void ThreadData::EnableProfilerTiming() { |
| 848 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING); | 798 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING); |
| 849 } | 799 } |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1056 const std::string& death_thread_name) | 1006 const std::string& death_thread_name) |
| 1057 : birth(birth), | 1007 : birth(birth), |
| 1058 death_data(death_data), | 1008 death_data(death_data), |
| 1059 death_thread_name(death_thread_name) { | 1009 death_thread_name(death_thread_name) { |
| 1060 } | 1010 } |
| 1061 | 1011 |
| 1062 TaskSnapshot::~TaskSnapshot() { | 1012 TaskSnapshot::~TaskSnapshot() { |
| 1063 } | 1013 } |
| 1064 | 1014 |
| 1065 //------------------------------------------------------------------------------ | 1015 //------------------------------------------------------------------------------ |
| 1066 // ParentChildPairSnapshot | |
| 1067 | |
| 1068 ParentChildPairSnapshot::ParentChildPairSnapshot() { | |
| 1069 } | |
| 1070 | |
| 1071 ParentChildPairSnapshot::ParentChildPairSnapshot( | |
| 1072 const ThreadData::ParentChildPair& parent_child) | |
| 1073 : parent(*parent_child.first), | |
| 1074 child(*parent_child.second) { | |
| 1075 } | |
| 1076 | |
| 1077 ParentChildPairSnapshot::~ParentChildPairSnapshot() { | |
| 1078 } | |
| 1079 | |
| 1080 //------------------------------------------------------------------------------ | |
| 1081 // ProcessDataPhaseSnapshot | 1016 // ProcessDataPhaseSnapshot |
| 1082 | 1017 |
| 1083 ProcessDataPhaseSnapshot::ProcessDataPhaseSnapshot() { | 1018 ProcessDataPhaseSnapshot::ProcessDataPhaseSnapshot() { |
| 1084 } | 1019 } |
| 1085 | 1020 |
| 1086 ProcessDataPhaseSnapshot::~ProcessDataPhaseSnapshot() { | 1021 ProcessDataPhaseSnapshot::~ProcessDataPhaseSnapshot() { |
| 1087 } | 1022 } |
| 1088 | 1023 |
| 1089 //------------------------------------------------------------------------------ | 1024 //------------------------------------------------------------------------------ |
| 1090 // ProcessDataPhaseSnapshot | 1025 // ProcessDataPhaseSnapshot |
| 1091 | 1026 |
| 1092 ProcessDataSnapshot::ProcessDataSnapshot() | 1027 ProcessDataSnapshot::ProcessDataSnapshot() |
| 1093 #if !defined(OS_NACL) | 1028 #if !defined(OS_NACL) |
| 1094 : process_id(base::GetCurrentProcId()) { | 1029 : process_id(base::GetCurrentProcId()) { |
| 1095 #else | 1030 #else |
| 1096 : process_id(base::kNullProcessId) { | 1031 : process_id(base::kNullProcessId) { |
| 1097 #endif | 1032 #endif |
| 1098 } | 1033 } |
| 1099 | 1034 |
| 1100 ProcessDataSnapshot::~ProcessDataSnapshot() { | 1035 ProcessDataSnapshot::~ProcessDataSnapshot() { |
| 1101 } | 1036 } |
| 1102 | 1037 |
| 1103 } // namespace tracked_objects | 1038 } // namespace tracked_objects |
| OLD | NEW |