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 "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" |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 }; | 173 }; |
174 | 174 |
175 // static | 175 // static |
176 base::LazyInstance | 176 base::LazyInstance |
177 <TrackingSynchronizer::RequestContext::RequestContextMap>::Leaky | 177 <TrackingSynchronizer::RequestContext::RequestContextMap>::Leaky |
178 TrackingSynchronizer::RequestContext::outstanding_requests_ = | 178 TrackingSynchronizer::RequestContext::outstanding_requests_ = |
179 LAZY_INSTANCE_INITIALIZER; | 179 LAZY_INSTANCE_INITIALIZER; |
180 | 180 |
181 // TrackingSynchronizer methods and members. | 181 // TrackingSynchronizer methods and members. |
182 | 182 |
183 TrackingSynchronizer::TrackingSynchronizer(base::TimeTicks now) | 183 TrackingSynchronizer::TrackingSynchronizer(base::TickClock* clock) |
184 : last_used_sequence_number_(kNeverUsableSequenceNumber), start_time_(now) { | 184 : last_used_sequence_number_(kNeverUsableSequenceNumber), |
| 185 clock_(clock), |
| 186 start_time_(clock->NowTicks()) { |
185 DCHECK(!g_tracking_synchronizer); | 187 DCHECK(!g_tracking_synchronizer); |
186 g_tracking_synchronizer = this; | 188 g_tracking_synchronizer = this; |
187 phase_start_times_.push_back(now); | 189 phase_start_times_.push_back(start_time_); |
188 | 190 |
189 #if !defined(OS_IOS) | 191 #if !defined(OS_IOS) |
190 // TODO: This ifdef and other ifdefs for OS_IOS in this file are only | 192 // TODO: This ifdef and other ifdefs for OS_IOS in this file are only |
191 // short-term hacks to make this compile on iOS, and the proper solution is to | 193 // short-term hacks to make this compile on iOS, and the proper solution is to |
192 // refactor to remove content dependencies from shared code. | 194 // refactor to remove content dependencies from shared code. |
193 // See crbug/472210. | 195 // See crbug/472210. |
194 content::ProfilerController::GetInstance()->Register(this); | 196 content::ProfilerController::GetInstance()->Register(this); |
195 #endif | 197 #endif |
196 } | 198 } |
197 | 199 |
(...skipping 22 matching lines...) Expand all Loading... |
220 callback_object); | 222 callback_object); |
221 | 223 |
222 // Post a task that would be called after waiting for wait_time. This acts | 224 // Post a task that would be called after waiting for wait_time. This acts |
223 // as a watchdog, to cancel the requests for non-responsive processes. | 225 // as a watchdog, to cancel the requests for non-responsive processes. |
224 BrowserThread::PostDelayedTask( | 226 BrowserThread::PostDelayedTask( |
225 BrowserThread::UI, FROM_HERE, | 227 BrowserThread::UI, FROM_HERE, |
226 base::Bind(&RequestContext::Unregister, sequence_number), | 228 base::Bind(&RequestContext::Unregister, sequence_number), |
227 base::TimeDelta::FromMinutes(1)); | 229 base::TimeDelta::FromMinutes(1)); |
228 } | 230 } |
229 | 231 |
| 232 // static |
| 233 void TrackingSynchronizer::OnProfilingPhaseCompleted( |
| 234 ProfilerEventProto::ProfilerEvent profiling_event) { |
| 235 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 236 |
| 237 if (!g_tracking_synchronizer) { |
| 238 // System teardown is happening. |
| 239 return; |
| 240 } |
| 241 |
| 242 g_tracking_synchronizer->NotifyAllProcessesOfProfilingPhaseCompletion( |
| 243 profiling_event); |
| 244 } |
| 245 |
230 void TrackingSynchronizer::OnPendingProcesses(int sequence_number, | 246 void TrackingSynchronizer::OnPendingProcesses(int sequence_number, |
231 int pending_processes, | 247 int pending_processes, |
232 bool end) { | 248 bool end) { |
233 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 249 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
234 | 250 |
235 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 251 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
236 if (!request) | 252 if (!request) |
237 return; | 253 return; |
238 request->AddProcessesPending(pending_processes); | 254 request->AddProcessesPending(pending_processes); |
239 request->SetReceivedProcessGroupCount(end); | 255 request->SetReceivedProcessGroupCount(end); |
(...skipping 14 matching lines...) Expand all Loading... |
254 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 270 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
255 | 271 |
256 int sequence_number = GetNextAvailableSequenceNumber(); | 272 int sequence_number = GetNextAvailableSequenceNumber(); |
257 | 273 |
258 RequestContext* request = | 274 RequestContext* request = |
259 RequestContext::Register(sequence_number, callback_object); | 275 RequestContext::Register(sequence_number, callback_object); |
260 | 276 |
261 // Increment pending process count for sending browser's profiler data. | 277 // Increment pending process count for sending browser's profiler data. |
262 request->IncrementProcessesPending(); | 278 request->IncrementProcessesPending(); |
263 | 279 |
| 280 int current_profiling_phase = phase_completion_events_sequence_.size(); |
| 281 |
264 #if !defined(OS_IOS) | 282 #if !defined(OS_IOS) |
265 // Get profiler data from renderer and browser child processes. | 283 // Get profiler data from renderer and browser child processes. |
266 content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); | 284 content::ProfilerController::GetInstance()->GetProfilerData( |
| 285 sequence_number, current_profiling_phase); |
267 #endif | 286 #endif |
268 | 287 |
269 // Send process data snapshot from browser process. | 288 // Send process data snapshot from browser process. |
270 tracked_objects::ProcessDataSnapshot process_data_snapshot; | 289 tracked_objects::ProcessDataSnapshot process_data_snapshot; |
271 tracked_objects::ThreadData::Snapshot(&process_data_snapshot); | 290 tracked_objects::ThreadData::Snapshot(current_profiling_phase, |
| 291 &process_data_snapshot); |
| 292 |
272 DecrementPendingProcessesAndSendData(sequence_number, process_data_snapshot, | 293 DecrementPendingProcessesAndSendData(sequence_number, process_data_snapshot, |
273 content::PROCESS_TYPE_BROWSER); | 294 content::PROCESS_TYPE_BROWSER); |
274 | 295 |
275 return sequence_number; | 296 return sequence_number; |
276 } | 297 } |
277 | 298 |
| 299 void TrackingSynchronizer::RegisterPhaseCompletion( |
| 300 ProfilerEventProto::ProfilerEvent profiling_event) { |
| 301 phase_completion_events_sequence_.push_back(profiling_event); |
| 302 phase_start_times_.push_back(clock_->NowTicks()); |
| 303 } |
| 304 |
| 305 void TrackingSynchronizer::NotifyAllProcessesOfProfilingPhaseCompletion( |
| 306 ProfilerEventProto::ProfilerEvent profiling_event) { |
| 307 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 308 |
| 309 if (variations::GetVariationParamValue("UMALogUploadInterval", |
| 310 "send_split_profiles") != "true") { |
| 311 return; |
| 312 } |
| 313 |
| 314 int profiling_phase = phase_completion_events_sequence_.size(); |
| 315 |
| 316 RegisterPhaseCompletion(profiling_event); |
| 317 |
| 318 #if !defined(OS_IOS) |
| 319 // Notify renderer and browser child processes. |
| 320 content::ProfilerController::GetInstance()->OnProfilingPhaseCompleted( |
| 321 profiling_phase); |
| 322 #endif |
| 323 |
| 324 // Notify browser process. |
| 325 tracked_objects::ThreadData::OnProfilingPhaseCompleted(profiling_phase); |
| 326 } |
| 327 |
278 void TrackingSynchronizer::SendData( | 328 void TrackingSynchronizer::SendData( |
279 const tracked_objects::ProcessDataSnapshot& profiler_data, | 329 const tracked_objects::ProcessDataSnapshot& profiler_data, |
280 content::ProcessType process_type, | 330 content::ProcessType process_type, |
281 base::TimeTicks now, | |
282 TrackingSynchronizerObserver* observer) const { | 331 TrackingSynchronizerObserver* observer) const { |
283 // We are going to loop though past profiling phases and notify the request | 332 // We are going to loop though past profiling phases and notify the request |
284 // about each phase that is contained in profiler_data. past_events | 333 // about each phase that is contained in profiler_data. past_events |
285 // will track the set of past profiling events as we go. | 334 // will track the set of past profiling events as we go. |
286 ProfilerEvents past_events; | 335 ProfilerEvents past_events; |
287 | 336 |
288 // Go through all completed phases, and through the current one. The current | 337 // Go through all completed phases, and through the current one. The current |
289 // one is not in phase_completion_events_sequence_, but note the <= | 338 // one is not in phase_completion_events_sequence_, but note the <= |
290 // comparison. | 339 // comparison. |
291 for (size_t phase = 0; phase <= phase_completion_events_sequence_.size(); | 340 for (size_t phase = 0; phase <= phase_completion_events_sequence_.size(); |
292 ++phase) { | 341 ++phase) { |
293 auto it = profiler_data.phased_process_data_snapshots.find(phase); | 342 auto it = profiler_data.phased_process_data_snapshots.find(phase); |
294 | 343 |
295 if (it != profiler_data.phased_process_data_snapshots.end()) { | 344 if (it != profiler_data.phased_process_data_snapshots.end()) { |
296 // If the phase is contained in the received snapshot, notify the | 345 // If the phase is contained in the received snapshot, notify the |
297 // request. | 346 // request. |
298 const base::TimeDelta phase_start = | 347 const base::TimeDelta phase_start = |
299 phase_start_times_[phase] - start_time_; | 348 phase_start_times_[phase] - start_time_; |
300 const base::TimeDelta phase_finish = | 349 const base::TimeDelta phase_finish = |
301 (phase + 1 < phase_start_times_.size() ? phase_start_times_[phase + 1] | 350 (phase + 1 < phase_start_times_.size() ? phase_start_times_[phase + 1] |
302 : now) - | 351 : clock_->NowTicks()) - |
303 start_time_; | 352 start_time_; |
304 observer->ReceivedProfilerData(it->second, profiler_data.process_id, | 353 observer->ReceivedProfilerData(it->second, profiler_data.process_id, |
305 process_type, phase, phase_start, | 354 process_type, phase, phase_start, |
306 phase_finish, past_events); | 355 phase_finish, past_events); |
307 } | 356 } |
308 | 357 |
309 if (phase < phase_completion_events_sequence_.size()) { | 358 if (phase < phase_completion_events_sequence_.size()) { |
310 past_events.push_back(phase_completion_events_sequence_[phase]); | 359 past_events.push_back(phase_completion_events_sequence_[phase]); |
311 } | 360 } |
312 } | 361 } |
313 } | 362 } |
314 | 363 |
315 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( | 364 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( |
316 int sequence_number, | 365 int sequence_number, |
317 const tracked_objects::ProcessDataSnapshot& profiler_data, | 366 const tracked_objects::ProcessDataSnapshot& profiler_data, |
318 content::ProcessType process_type) { | 367 content::ProcessType process_type) { |
319 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 368 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
320 | 369 |
321 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 370 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
322 if (!request) | 371 if (!request) |
323 return; | 372 return; |
324 | 373 |
325 TrackingSynchronizerObserver* observer = request->callback_object_.get(); | 374 TrackingSynchronizerObserver* observer = request->callback_object_.get(); |
326 if (observer) | 375 if (observer) |
327 SendData(profiler_data, process_type, base::TimeTicks::Now(), observer); | 376 SendData(profiler_data, process_type, observer); |
328 | 377 |
329 // Delete request if we have heard back from all child processes. | 378 // Delete request if we have heard back from all child processes. |
330 request->DecrementProcessesPending(); | 379 request->DecrementProcessesPending(); |
331 request->DeleteIfAllDone(); | 380 request->DeleteIfAllDone(); |
332 } | 381 } |
333 | 382 |
334 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { | 383 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { |
335 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 384 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
336 | 385 |
337 ++last_used_sequence_number_; | 386 ++last_used_sequence_number_; |
338 | 387 |
339 // Watch out for wrapping to a negative number. | 388 // Watch out for wrapping to a negative number. |
340 if (last_used_sequence_number_ < 0) | 389 if (last_used_sequence_number_ < 0) |
341 last_used_sequence_number_ = 1; | 390 last_used_sequence_number_ = 1; |
342 return last_used_sequence_number_; | 391 return last_used_sequence_number_; |
343 } | 392 } |
344 | 393 |
345 } // namespace metrics | 394 } // namespace metrics |
OLD | NEW |