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

Side by Side Diff: components/metrics/profiler/tracking_synchronizer.cc

Issue 985773002: Introducing phased profiling framework (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@write_to_file
Patch Set: Created 5 years, 9 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
OLDNEW
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 "components/metrics/profiler/tracking_synchronizer.h" 5 #include "components/metrics/profiler/tracking_synchronizer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/threading/thread.h" 9 #include "base/threading/thread.h"
10 #include "base/tracked_objects.h" 10 #include "base/tracked_objects.h"
11 #include "components/metrics/profiler/tracking_synchronizer_observer.h" 11 #include "components/metrics/profiler/tracking_synchronizer_observer.h"
12 #include "components/variations/variations_associated_data.h"
12 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/profiler_controller.h" 14 #include "content/public/browser/profiler_controller.h"
14 #include "content/public/common/process_type.h" 15 #include "content/public/common/process_type.h"
15 16
16 using base::TimeTicks; 17 using base::TimeTicks;
17 using content::BrowserThread; 18 using content::BrowserThread;
18 19
19 namespace metrics { 20 namespace metrics {
20 21
21 namespace { 22 namespace {
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 174
174 // static 175 // static
175 base::LazyInstance 176 base::LazyInstance
176 <TrackingSynchronizer::RequestContext::RequestContextMap>::Leaky 177 <TrackingSynchronizer::RequestContext::RequestContextMap>::Leaky
177 TrackingSynchronizer::RequestContext::outstanding_requests_ = 178 TrackingSynchronizer::RequestContext::outstanding_requests_ =
178 LAZY_INSTANCE_INITIALIZER; 179 LAZY_INSTANCE_INITIALIZER;
179 180
180 // TrackingSynchronizer methods and members. 181 // TrackingSynchronizer methods and members.
181 182
182 TrackingSynchronizer::TrackingSynchronizer() 183 TrackingSynchronizer::TrackingSynchronizer()
183 : last_used_sequence_number_(kNeverUsableSequenceNumber) { 184 : last_used_sequence_number_(kNeverUsableSequenceNumber),
185 start_time_(base::TimeTicks::Now()) {
184 DCHECK(!g_tracking_synchronizer); 186 DCHECK(!g_tracking_synchronizer);
185 g_tracking_synchronizer = this; 187 g_tracking_synchronizer = this;
188 phase_start_times_.push_back(base::TimeTicks::Now());
186 content::ProfilerController::GetInstance()->Register(this); 189 content::ProfilerController::GetInstance()->Register(this);
187 } 190 }
188 191
189 TrackingSynchronizer::~TrackingSynchronizer() { 192 TrackingSynchronizer::~TrackingSynchronizer() {
190 content::ProfilerController::GetInstance()->Unregister(this); 193 content::ProfilerController::GetInstance()->Unregister(this);
191 194
192 // Just in case we have any pending tasks, clear them out. 195 // Just in case we have any pending tasks, clear them out.
193 RequestContext::OnShutdown(); 196 RequestContext::OnShutdown();
194 197
195 g_tracking_synchronizer = NULL; 198 g_tracking_synchronizer = NULL;
(...skipping 13 matching lines...) Expand all
209 callback_object); 212 callback_object);
210 213
211 // Post a task that would be called after waiting for wait_time. This acts 214 // Post a task that would be called after waiting for wait_time. This acts
212 // as a watchdog, to cancel the requests for non-responsive processes. 215 // as a watchdog, to cancel the requests for non-responsive processes.
213 BrowserThread::PostDelayedTask( 216 BrowserThread::PostDelayedTask(
214 BrowserThread::UI, FROM_HERE, 217 BrowserThread::UI, FROM_HERE,
215 base::Bind(&RequestContext::Unregister, sequence_number), 218 base::Bind(&RequestContext::Unregister, sequence_number),
216 base::TimeDelta::FromMinutes(1)); 219 base::TimeDelta::FromMinutes(1));
217 } 220 }
218 221
222 // static
223 void TrackingSynchronizer::OnProfilingPhaseCompletion(
224 ProfilerEventProto::ProfilerEvent profiling_event) {
225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
226
227 if (!g_tracking_synchronizer) {
228 // System teardown is happening.
229 return;
230 }
231
232 g_tracking_synchronizer->NotifyAllProcessesOfProfilingPhaseCompletion(
233 profiling_event);
234 }
235
219 void TrackingSynchronizer::OnPendingProcesses(int sequence_number, 236 void TrackingSynchronizer::OnPendingProcesses(int sequence_number,
220 int pending_processes, 237 int pending_processes,
221 bool end) { 238 bool end) {
222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
223 240
224 RequestContext* request = RequestContext::GetRequestContext(sequence_number); 241 RequestContext* request = RequestContext::GetRequestContext(sequence_number);
225 if (!request) 242 if (!request)
226 return; 243 return;
227 request->AddProcessesPending(pending_processes); 244 request->AddProcessesPending(pending_processes);
228 request->SetReceivedProcessGroupCount(end); 245 request->SetReceivedProcessGroupCount(end);
(...skipping 14 matching lines...) Expand all
243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
244 261
245 int sequence_number = GetNextAvailableSequenceNumber(); 262 int sequence_number = GetNextAvailableSequenceNumber();
246 263
247 RequestContext* request = 264 RequestContext* request =
248 RequestContext::Register(sequence_number, callback_object); 265 RequestContext::Register(sequence_number, callback_object);
249 266
250 // Increment pending process count for sending browser's profiler data. 267 // Increment pending process count for sending browser's profiler data.
251 request->IncrementProcessesPending(); 268 request->IncrementProcessesPending();
252 269
270 const int current_profiling_phase = phase_completion_events_sequence_.size();
271
253 // Get profiler data from renderer and browser child processes. 272 // Get profiler data from renderer and browser child processes.
254 content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); 273 content::ProfilerController::GetInstance()->GetProfilerData(
274 sequence_number, current_profiling_phase);
255 275
256 // Send profiler_data from browser process. 276 // Send process_data_snapshot from browser process.
257 tracked_objects::ProcessDataSnapshot process_data; 277 tracked_objects::ProcessDataSnapshot process_data_snapshot;
258 tracked_objects::ThreadData::Snapshot(&process_data); 278 tracked_objects::ThreadData::GetProcessDataSnapshot(current_profiling_phase,
259 DecrementPendingProcessesAndSendData(sequence_number, process_data, 279 &process_data_snapshot);
280 DecrementPendingProcessesAndSendData(sequence_number, process_data_snapshot,
260 content::PROCESS_TYPE_BROWSER); 281 content::PROCESS_TYPE_BROWSER);
261 282
262 return sequence_number; 283 return sequence_number;
263 } 284 }
264 285
286 void TrackingSynchronizer::NotifyAllProcessesOfProfilingPhaseCompletion(
287 ProfilerEventProto::ProfilerEvent profiling_event) {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
289
290 if (variations::GetVariationParamValue("UMALogUploadInterval",
291 "send_split_profiles") != "true") {
292 return;
293 }
294
295 const int profiling_phase = phase_completion_events_sequence_.size();
296
297 phase_completion_events_sequence_.push_back(profiling_event);
298 phase_start_times_.push_back(base::TimeTicks::Now());
299
300 // Notify renderer and browser child processes.
301 content::ProfilerController::GetInstance()->OnProfilingPhaseCompletion(
302 profiling_phase);
303
304 // Notify browser process.
305 tracked_objects::ThreadData::OnProfilingPhaseCompletion(profiling_phase);
306 }
307
265 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( 308 void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
266 int sequence_number, 309 int sequence_number,
267 const tracked_objects::ProcessDataSnapshot& profiler_data, 310 const tracked_objects::ProcessDataSnapshot& profiler_data,
268 int process_type) { 311 int process_type) {
269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
270 313
271 RequestContext* request = RequestContext::GetRequestContext(sequence_number); 314 RequestContext* request = RequestContext::GetRequestContext(sequence_number);
272 if (!request) 315 if (!request)
273 return; 316 return;
274 317
275 if (request->callback_object_.get()) { 318 if (request->callback_object_.get()) {
276 request->callback_object_ 319 // We are going to loop though past profiling phases and notify the request
277 ->ReceivedProfilerData(profiler_data, process_type); 320 // about each phase that is contained in profiler_data. past_profiler_events
321 // will track the set of past profiling events as we go.
322 ProfilerEventsSet past_profiler_events;
323
324 // Go though all completed phases, and though the current one. The current
325 // one is not in phase_completion_events_sequence_, but note the <=
326 // comparison.
327 for (size_t phase = 0; phase <= phase_completion_events_sequence_.size();
328 ++phase) {
329 tracked_objects::PhasedProcessDataSnapshots::const_iterator it =
330 profiler_data.phased_process_data_snapshots.find(phase);
331
332 if (it != profiler_data.phased_process_data_snapshots.end()) {
333 // If the phase is contained in the received snapshot, notify the
334 // request.
335 const base::TimeDelta phase_start =
336 phase_start_times_[phase] - start_time_;
337 const base::TimeDelta phase_finish =
338 (phase + 1 < phase_start_times_.size()
339 ? phase_start_times_[phase + 1]
340 : base::TimeTicks::Now()) -
341 start_time_;
342 request->callback_object_->ReceivedProfilerData(
343 it->second, profiler_data.process_id, process_type, phase,
344 phase_start, phase_finish, past_profiler_events);
345 }
346
347 if (phase != phase_completion_events_sequence_.size()) {
348 past_profiler_events.push_back(
349 phase_completion_events_sequence_[phase]);
350 }
351 }
278 } 352 }
279 353
280 // Delete request if we have heard back from all child processes. 354 // Delete request if we have heard back from all child processes.
281 request->DecrementProcessesPending(); 355 request->DecrementProcessesPending();
282 request->DeleteIfAllDone(); 356 request->DeleteIfAllDone();
283 } 357 }
284 358
285 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { 359 int TrackingSynchronizer::GetNextAvailableSequenceNumber() {
286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
287 361
288 ++last_used_sequence_number_; 362 ++last_used_sequence_number_;
289 363
290 // Watch out for wrapping to a negative number. 364 // Watch out for wrapping to a negative number.
291 if (last_used_sequence_number_ < 0) 365 if (last_used_sequence_number_ < 0)
292 last_used_sequence_number_ = 1; 366 last_used_sequence_number_ = 1;
293 return last_used_sequence_number_; 367 return last_used_sequence_number_;
294 } 368 }
295 369
296 } // namespace metrics 370 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698