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