| Index: components/metrics/profiler/tracking_synchronizer.cc
|
| diff --git a/components/metrics/profiler/tracking_synchronizer.cc b/components/metrics/profiler/tracking_synchronizer.cc
|
| index 8d53bd2a7ec19f42df2336cd968f5dcf49eb89b2..18533cd53ccddf11ee0243a74acfbe4f18b5a303 100644
|
| --- a/components/metrics/profiler/tracking_synchronizer.cc
|
| +++ b/components/metrics/profiler/tracking_synchronizer.cc
|
| @@ -9,6 +9,7 @@
|
| #include "base/threading/thread.h"
|
| #include "base/tracked_objects.h"
|
| #include "components/metrics/profiler/tracking_synchronizer_observer.h"
|
| +#include "components/variations/variations_associated_data.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/profiler_controller.h"
|
| #include "content/public/common/process_type.h"
|
| @@ -180,9 +181,11 @@ base::LazyInstance
|
| // TrackingSynchronizer methods and members.
|
|
|
| TrackingSynchronizer::TrackingSynchronizer()
|
| - : last_used_sequence_number_(kNeverUsableSequenceNumber) {
|
| + : last_used_sequence_number_(kNeverUsableSequenceNumber),
|
| + start_time_(base::TimeTicks::Now()) {
|
| DCHECK(!g_tracking_synchronizer);
|
| g_tracking_synchronizer = this;
|
| + phase_start_times_.push_back(base::TimeTicks::Now());
|
| content::ProfilerController::GetInstance()->Register(this);
|
| }
|
|
|
| @@ -216,6 +219,20 @@ void TrackingSynchronizer::FetchProfilerDataAsynchronously(
|
| base::TimeDelta::FromMinutes(1));
|
| }
|
|
|
| +// static
|
| +void TrackingSynchronizer::OnProfilingPhaseCompletion(
|
| + ProfilerEventProto::ProfilerEvent profiling_event) {
|
| + DCHECK(BrowserThread::CurrentlyOn(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) {
|
| @@ -250,18 +267,44 @@ int TrackingSynchronizer::RegisterAndNotifyAllProcesses(
|
| // Increment pending process count for sending browser's profiler data.
|
| request->IncrementProcessesPending();
|
|
|
| - // Get profiler data from renderer and browser child processes.
|
| - content::ProfilerController::GetInstance()->GetProfilerData(sequence_number);
|
| + const int current_profiling_phase = phase_completion_events_sequence_.size();
|
|
|
| - // Send profiler_data from browser process.
|
| - tracked_objects::ProcessDataSnapshot process_data;
|
| - tracked_objects::ThreadData::Snapshot(&process_data);
|
| - DecrementPendingProcessesAndSendData(sequence_number, process_data,
|
| + // Get profiler data from renderer and browser child processes.
|
| + content::ProfilerController::GetInstance()->GetProfilerData(
|
| + sequence_number, current_profiling_phase);
|
| +
|
| + // Send process_data_snapshot from browser process.
|
| + tracked_objects::ProcessDataSnapshot process_data_snapshot;
|
| + tracked_objects::ThreadData::GetProcessDataSnapshot(current_profiling_phase,
|
| + &process_data_snapshot);
|
| + DecrementPendingProcessesAndSendData(sequence_number, process_data_snapshot,
|
| content::PROCESS_TYPE_BROWSER);
|
|
|
| return sequence_number;
|
| }
|
|
|
| +void TrackingSynchronizer::NotifyAllProcessesOfProfilingPhaseCompletion(
|
| + ProfilerEventProto::ProfilerEvent profiling_event) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + if (variations::GetVariationParamValue("UMALogUploadInterval",
|
| + "send_split_profiles") != "true") {
|
| + return;
|
| + }
|
| +
|
| + const int profiling_phase = phase_completion_events_sequence_.size();
|
| +
|
| + phase_completion_events_sequence_.push_back(profiling_event);
|
| + phase_start_times_.push_back(base::TimeTicks::Now());
|
| +
|
| + // Notify renderer and browser child processes.
|
| + content::ProfilerController::GetInstance()->OnProfilingPhaseCompletion(
|
| + profiling_phase);
|
| +
|
| + // Notify browser process.
|
| + tracked_objects::ThreadData::OnProfilingPhaseCompletion(profiling_phase);
|
| +}
|
| +
|
| void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
|
| int sequence_number,
|
| const tracked_objects::ProcessDataSnapshot& profiler_data,
|
| @@ -273,8 +316,39 @@ void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
|
| return;
|
|
|
| if (request->callback_object_.get()) {
|
| - request->callback_object_
|
| - ->ReceivedProfilerData(profiler_data, process_type);
|
| + // We are going to loop though past profiling phases and notify the request
|
| + // about each phase that is contained in profiler_data. past_profiler_events
|
| + // will track the set of past profiling events as we go.
|
| + ProfilerEventsSet past_profiler_events;
|
| +
|
| + // Go though all completed phases, and though the current one. The current
|
| + // one is not in phase_completion_events_sequence_, but note the <=
|
| + // comparison.
|
| + for (size_t phase = 0; phase <= phase_completion_events_sequence_.size();
|
| + ++phase) {
|
| + tracked_objects::PhasedProcessDataSnapshots::const_iterator it =
|
| + profiler_data.phased_process_data_snapshots.find(phase);
|
| +
|
| + if (it != profiler_data.phased_process_data_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]
|
| + : base::TimeTicks::Now()) -
|
| + start_time_;
|
| + request->callback_object_->ReceivedProfilerData(
|
| + it->second, profiler_data.process_id, process_type, phase,
|
| + phase_start, phase_finish, past_profiler_events);
|
| + }
|
| +
|
| + if (phase != phase_completion_events_sequence_.size()) {
|
| + past_profiler_events.push_back(
|
| + phase_completion_events_sequence_[phase]);
|
| + }
|
| + }
|
| }
|
|
|
| // Delete request if we have heard back from all child processes.
|
|
|