Chromium Code Reviews| Index: components/metrics/profiler/tracking_synchronizer.cc |
| diff --git a/components/metrics/profiler/tracking_synchronizer.cc b/components/metrics/profiler/tracking_synchronizer.cc |
| index ad3644195f2a9236851b6aa1706f47b420d1ce92..2a272da678dba3a2f0e5895947da78da41c931af 100644 |
| --- a/components/metrics/profiler/tracking_synchronizer.cc |
| +++ b/components/metrics/profiler/tracking_synchronizer.cc |
| @@ -180,11 +180,12 @@ base::LazyInstance |
| // TrackingSynchronizer methods and members. |
| -TrackingSynchronizer::TrackingSynchronizer(base::TimeTicks now) |
| - : last_used_sequence_number_(kNeverUsableSequenceNumber), start_time_(now) { |
| +TrackingSynchronizer::TrackingSynchronizer(scoped_ptr<base::TickClock> clock) |
| + : last_used_sequence_number_(kNeverUsableSequenceNumber), |
| + clock_(clock.Pass()) { |
| DCHECK(!g_tracking_synchronizer); |
| g_tracking_synchronizer = this; |
| - phase_start_times_.push_back(now); |
| + phase_start_times_.push_back(clock_->NowTicks()); |
| #if !defined(OS_IOS) |
| // TODO: This ifdef and other ifdefs for OS_IOS in this file are only |
| @@ -227,6 +228,20 @@ void TrackingSynchronizer::FetchProfilerDataAsynchronously( |
| base::TimeDelta::FromMinutes(1)); |
| } |
| +// static |
| +void TrackingSynchronizer::OnProfilingPhaseCompleted( |
| + ProfilerEventProto::ProfilerEvent profiling_event) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + if (!g_tracking_synchronizer) { |
| + // System teardown is happening. |
| + return; |
| + } |
| + |
| + g_tracking_synchronizer->NotifyAllProcessesOfProfilingPhaseCompletion( |
| + profiling_event); |
| +} |
| + |
| void TrackingSynchronizer::OnPendingProcesses(int sequence_number, |
| int pending_processes, |
| bool end) { |
| @@ -261,24 +276,63 @@ int TrackingSynchronizer::RegisterAndNotifyAllProcesses( |
| // Increment pending process count for sending browser's profiler data. |
| request->IncrementProcessesPending(); |
| + const int current_profiling_phase = phase_completion_events_sequence_.size(); |
| + |
| #if !defined(OS_IOS) |
| // Get profiler data from renderer and browser child processes. |
| - content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); |
| + content::ProfilerController::GetInstance()->GetProfilerData( |
| + sequence_number, current_profiling_phase); |
| #endif |
| // Send process data snapshot from browser process. |
| tracked_objects::ProcessDataSnapshot process_data_snapshot; |
| - tracked_objects::ThreadData::Snapshot(&process_data_snapshot); |
| + tracked_objects::ThreadData::Snapshot(current_profiling_phase, |
| + &process_data_snapshot); |
| + |
| DecrementPendingProcessesAndSendData(sequence_number, process_data_snapshot, |
| content::PROCESS_TYPE_BROWSER); |
| return sequence_number; |
| } |
| +void TrackingSynchronizer::RegisterPhaseCompletion( |
| + ProfilerEventProto::ProfilerEvent profiling_event) { |
| + phase_completion_events_sequence_.push_back(profiling_event); |
| + phase_start_times_.push_back(clock_->NowTicks()); |
| +} |
| + |
| +void TrackingSynchronizer::NotifyAllProcessesOfProfilingPhaseCompletion( |
| + ProfilerEventProto::ProfilerEvent profiling_event) { |
| + DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| + |
| + if (variations::GetVariationParamValue("UMALogPhasedProfiling", |
| + "send_split_profiles") == "false") { |
| + return; |
| + } |
| + |
| + int profiling_phase = phase_completion_events_sequence_.size(); |
| + |
| + // If you hit this check, stop and think. You just added a new profiling |
| + // phase. Each profiling phase takes additional memory in DeathData's list of |
| + // snapshots. We cannot grow it indefinitely. Consider collapsing older phases |
| + // after they were sent to UMA server, or other ways to save memory. |
| + DCHECK(profiling_phase < 1); |
|
Alexei Svitkine (slow)
2015/04/15 19:22:50
DCHECK_LT?
vadimt
2015/04/15 19:52:15
Done.
|
| + |
| + RegisterPhaseCompletion(profiling_event); |
| + |
| +#if !defined(OS_IOS) |
| + // Notify renderer and browser child processes. |
| + content::ProfilerController::GetInstance()->OnProfilingPhaseCompleted( |
| + profiling_phase); |
| +#endif |
| + |
| + // Notify browser process. |
| + tracked_objects::ThreadData::OnProfilingPhaseCompleted(profiling_phase); |
| +} |
| + |
| void TrackingSynchronizer::SendData( |
| const tracked_objects::ProcessDataSnapshot& profiler_data, |
| content::ProcessType process_type, |
| - base::TimeTicks now, |
| TrackingSynchronizerObserver* observer) const { |
| // We are going to loop though past profiling phases and notify the request |
| // about each phase that is contained in profiler_data. past_events |
| @@ -290,20 +344,19 @@ void TrackingSynchronizer::SendData( |
| // comparison. |
| for (size_t phase = 0; phase <= phase_completion_events_sequence_.size(); |
| ++phase) { |
| - auto it = profiler_data.phased_process_data_snapshots.find(phase); |
| + auto it = profiler_data.phased_snapshots.find(phase); |
| - if (it != profiler_data.phased_process_data_snapshots.end()) { |
| + if (it != profiler_data.phased_snapshots.end()) { |
| // If the phase is contained in the received snapshot, notify the |
| // request. |
| - const base::TimeDelta phase_start = |
| - phase_start_times_[phase] - start_time_; |
| - const base::TimeDelta phase_finish = |
| - (phase + 1 < phase_start_times_.size() ? phase_start_times_[phase + 1] |
| - : now) - |
| - start_time_; |
| - observer->ReceivedProfilerData(it->second, profiler_data.process_id, |
| - process_type, phase, phase_start, |
| - phase_finish, past_events); |
| + const base::TimeTicks phase_start = phase_start_times_[phase]; |
| + const base::TimeTicks phase_finish = phase + 1 < phase_start_times_.size() |
| + ? phase_start_times_[phase + 1] |
| + : clock_->NowTicks(); |
| + observer->ReceivedProfilerData( |
| + ProfilerDataAttributes(phase, profiler_data.process_id, process_type, |
| + phase_start, phase_finish), |
| + it->second, past_events); |
| } |
| if (phase < phase_completion_events_sequence_.size()) { |
| @@ -324,7 +377,7 @@ void TrackingSynchronizer::DecrementPendingProcessesAndSendData( |
| TrackingSynchronizerObserver* observer = request->callback_object_.get(); |
| if (observer) |
| - SendData(profiler_data, process_type, base::TimeTicks::Now(), observer); |
| + SendData(profiler_data, process_type, observer); |
| // Delete request if we have heard back from all child processes. |
| request->DecrementProcessesPending(); |