Index: base/tracked_objects.cc |
diff --git a/base/tracked_objects.cc b/base/tracked_objects.cc |
index b3f3c7edcb93d065a92da0b6af36c4e8c1eddbf0..6fd68c44d340b2b0632021f5f6b1693b05cd8eb1 100644 |
--- a/base/tracked_objects.cc |
+++ b/base/tracked_objects.cc |
@@ -15,6 +15,7 @@ |
#include "base/logging.h" |
#include "base/process/process_handle.h" |
#include "base/profiler/alternate_timer.h" |
+#include "base/stl_util.h" |
#include "base/strings/stringprintf.h" |
#include "base/third_party/valgrind/memcheck.h" |
#include "base/tracking_info.h" |
@@ -227,6 +228,10 @@ int Births::birth_count() const { return birth_count_; } |
void Births::RecordBirth() { ++birth_count_; } |
+void Births::SubtractBirths(int count) { |
+ birth_count_ -= count; |
+} |
+ |
//------------------------------------------------------------------------------ |
// ThreadData maintains the central data for all births and deaths on a single |
// thread. |
@@ -269,6 +274,10 @@ base::LazyInstance<base::Lock>::Leaky |
// static |
ThreadData::Status ThreadData::status_ = ThreadData::UNINITIALIZED; |
+// static |
+base::LazyInstance<PhasedProcessDataSnapshotMap> |
+ ThreadData::completed_phases_snapshots_ = LAZY_INSTANCE_INITIALIZER; |
+ |
ThreadData::ThreadData(const std::string& suggested_name) |
: next_(NULL), |
next_retired_worker_(NULL), |
@@ -390,9 +399,26 @@ void ThreadData::OnThreadTerminationCleanup() { |
} |
// static |
-void ThreadData::Snapshot(ProcessDataSnapshot* process_data_snapshot) { |
+void ThreadData::Snapshot(int current_profiling_phase, |
+ ProcessDataSnapshot* process_data_snapshot) { |
+ process_data_snapshot->phased_process_data_snapshots = |
+ completed_phases_snapshots_.Get(); |
+ |
+ DCHECK(!ContainsKey(process_data_snapshot->phased_process_data_snapshots, |
+ current_profiling_phase)); |
ThreadData::SnapshotCurrentPhase( |
- &process_data_snapshot->phased_process_data_snapshots[0]); |
+ false, &process_data_snapshot |
+ ->phased_process_data_snapshots[current_profiling_phase]); |
+} |
+ |
+// static |
+void ThreadData::OnProfilingPhaseCompletion(int profiling_phase) { |
+ if (!kTrackAllTaskObjects) |
+ return; // Not compiled in. |
+ |
+ PhasedProcessDataSnapshotMap& snapshots = completed_phases_snapshots_.Get(); |
+ DCHECK(!ContainsKey(snapshots, profiling_phase)); |
+ ThreadData::SnapshotCurrentPhase(true, &snapshots[profiling_phase]); |
} |
Births* ThreadData::TallyABirth(const Location& location) { |
@@ -424,16 +450,16 @@ Births* ThreadData::TallyABirth(const Location& location) { |
return child; |
} |
-void ThreadData::TallyADeath(const Births& birth, |
- int32 queue_duration, |
- const TaskStopwatch& stopwatch) { |
+void ThreadData::TallyADeath(int32 queue_duration, |
+ const TaskStopwatch& stopwatch, |
+ Births* birth) { |
int32 run_duration = stopwatch.RunDurationMs(); |
// Stir in some randomness, plus add constant in case durations are zero. |
const uint32 kSomePrimeNumber = 2147483647; |
random_number_ += queue_duration + run_duration + kSomePrimeNumber; |
// An address is going to have some randomness to it as well ;-). |
- random_number_ ^= static_cast<uint32>(&birth - reinterpret_cast<Births*>(0)); |
+ random_number_ ^= static_cast<uint32>(birth - reinterpret_cast<Births*>(0)); |
// We don't have queue durations without OS timer. OS timer is automatically |
// used for task-post-timing, so the use of an alternate timer implies all |
@@ -445,20 +471,20 @@ void ThreadData::TallyADeath(const Births& birth, |
queue_duration = 0; |
} |
- DeathMap::iterator it = death_map_.find(&birth); |
+ DeathMap::iterator it = death_map_.find(birth); |
DeathData* death_data; |
if (it != death_map_.end()) { |
death_data = &it->second; |
} else { |
base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. |
- death_data = &death_map_[&birth]; |
+ death_data = &death_map_[birth]; |
} // Release lock ASAP. |
death_data->RecordDeath(queue_duration, run_duration, random_number_); |
if (!kTrackParentChildLinks) |
return; |
if (!parent_stack_.empty()) { // We might get turned off. |
- DCHECK_EQ(parent_stack_.top(), &birth); |
+ DCHECK_EQ(parent_stack_.top(), birth); |
parent_stack_.pop(); |
} |
} |
@@ -486,7 +512,7 @@ void ThreadData::TallyRunOnNamedThreadIfTracking( |
// Even if we have been DEACTIVATED, we will process any pending births so |
// that our data structures (which counted the outstanding births) remain |
// consistent. |
- const Births* birth = completed_task.birth_tally; |
+ Births* birth = completed_task.birth_tally; |
if (!birth) |
return; |
ThreadData* current_thread_data = stopwatch.GetThreadData(); |
@@ -504,14 +530,14 @@ void ThreadData::TallyRunOnNamedThreadIfTracking( |
queue_duration = (start_of_run - completed_task.EffectiveTimePosted()) |
.InMilliseconds(); |
} |
- current_thread_data->TallyADeath(*birth, queue_duration, stopwatch); |
+ current_thread_data->TallyADeath(queue_duration, stopwatch, birth); |
} |
// static |
void ThreadData::TallyRunOnWorkerThreadIfTracking( |
- const Births* birth, |
const TrackedTime& time_posted, |
- const TaskStopwatch& stopwatch) { |
+ const TaskStopwatch& stopwatch, |
+ Births* birth) { |
if (!kTrackAllTaskObjects) |
return; // Not compiled in. |
@@ -539,13 +565,13 @@ void ThreadData::TallyRunOnWorkerThreadIfTracking( |
if (!start_of_run.is_null()) { |
queue_duration = (start_of_run - time_posted).InMilliseconds(); |
} |
- current_thread_data->TallyADeath(*birth, queue_duration, stopwatch); |
+ current_thread_data->TallyADeath(queue_duration, stopwatch, birth); |
} |
// static |
void ThreadData::TallyRunInAScopedRegionIfTracking( |
- const Births* birth, |
- const TaskStopwatch& stopwatch) { |
+ const TaskStopwatch& stopwatch, |
+ Births* birth) { |
if (!kTrackAllTaskObjects) |
return; // Not compiled in. |
@@ -560,11 +586,12 @@ void ThreadData::TallyRunInAScopedRegionIfTracking( |
return; |
int32 queue_duration = 0; |
- current_thread_data->TallyADeath(*birth, queue_duration, stopwatch); |
+ current_thread_data->TallyADeath(queue_duration, stopwatch, birth); |
} |
// static |
void ThreadData::SnapshotAllExecutedTasks( |
+ bool reset, |
ProcessDataPhaseSnapshot* process_data_phase, |
BirthCountMap* birth_counts) { |
if (!kTrackAllTaskObjects) |
@@ -582,18 +609,20 @@ void ThreadData::SnapshotAllExecutedTasks( |
for (ThreadData* thread_data = my_list; |
thread_data; |
thread_data = thread_data->next()) { |
- thread_data->SnapshotExecutedTasks(process_data_phase, birth_counts); |
+ thread_data->SnapshotExecutedTasks(reset, process_data_phase, birth_counts); |
} |
} |
// static |
void ThreadData::SnapshotCurrentPhase( |
+ bool reset, |
ProcessDataPhaseSnapshot* process_data_phase) { |
// Add births that have run to completion to |collected_data|. |
// |birth_counts| tracks the total number of births recorded at each location |
// for which we have not seen a death count. |
BirthCountMap birth_counts; |
- ThreadData::SnapshotAllExecutedTasks(process_data_phase, &birth_counts); |
+ ThreadData::SnapshotAllExecutedTasks(reset, process_data_phase, |
+ &birth_counts); |
// Add births that are still active -- i.e. objects that have tallied a birth, |
// but have not yet tallied a matching death, and hence must be either |
@@ -607,6 +636,7 @@ void ThreadData::SnapshotCurrentPhase( |
} |
void ThreadData::SnapshotExecutedTasks( |
+ bool reset, |
ProcessDataPhaseSnapshot* process_data_phase, |
BirthCountMap* birth_counts) { |
// Get copy of data, so that the data will not change during the iterations |
@@ -614,12 +644,14 @@ void ThreadData::SnapshotExecutedTasks( |
ThreadData::BirthMap birth_map; |
ThreadData::DeathMap death_map; |
ThreadData::ParentChildSet parent_child_set; |
- SnapshotMaps(&birth_map, &death_map, &parent_child_set); |
+ SnapshotMaps(reset, &birth_map, &death_map, &parent_child_set); |
for (const auto& death : death_map) { |
process_data_phase->tasks.push_back( |
TaskSnapshot(*death.first, death.second, thread_name())); |
- (*birth_counts)[death.first] -= death.first->birth_count(); |
+ // We don't populate birth_counts if |reset| is true. |
+ if (!reset) |
+ (*birth_counts)[death.first] -= death.first->birth_count(); |
} |
for (const auto& birth : birth_map) { |
@@ -636,14 +668,28 @@ void ThreadData::SnapshotExecutedTasks( |
} |
// This may be called from another thread. |
-void ThreadData::SnapshotMaps(BirthMap* birth_map, |
+void ThreadData::SnapshotMaps(bool reset, |
+ BirthMap* birth_map, |
DeathMap* death_map, |
ParentChildSet* parent_child_set) { |
base::AutoLock lock(map_lock_); |
- for (const auto& birth : birth_map_) |
- (*birth_map)[birth.first] = birth.second; |
- for (auto& death : death_map_) |
+ if (!reset) { |
+ // When reset is not requested, snapshot births. |
+ for (const auto& birth : birth_map_) |
+ (*birth_map)[birth.first] = birth.second; |
+ } |
+ for (auto& death : death_map_) { |
+ // Don't snapshot deaths with 0 count. Deaths with 0 count can result from |
+ // prior calls to SnapshotMaps with reset=true param. |
+ if (death.second.count() <= 0) |
+ continue; |
+ |
(*death_map)[death.first] = death.second; |
+ if (reset) { |
+ death.first->SubtractBirths(death.second.count()); |
+ death.second.Clear(); |
+ } |
+ } |
if (!kTrackParentChildLinks) |
return; |
@@ -833,6 +879,8 @@ void ThreadData::ShutdownSingleThreadedCleanup(bool leak) { |
delete it->second; // Delete the Birth Records. |
delete next_thread_data; // Includes all Death Records. |
} |
+ |
+ completed_phases_snapshots_.Get().clear(); |
} |
//------------------------------------------------------------------------------ |