| 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object, | 47 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object, |
| 48 int sequence_number) | 48 int sequence_number) |
| 49 : callback_object_(callback_object), | 49 : callback_object_(callback_object), |
| 50 sequence_number_(sequence_number), | 50 sequence_number_(sequence_number), |
| 51 received_process_group_count_(0), | 51 received_process_group_count_(0), |
| 52 processes_pending_(0) { | 52 processes_pending_(0) { |
| 53 } | 53 } |
| 54 ~RequestContext() {} | 54 ~RequestContext() {} |
| 55 | 55 |
| 56 void SetReceivedProcessGroupCount(bool done) { | 56 void SetReceivedProcessGroupCount(bool done) { |
| 57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 57 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 58 received_process_group_count_ = done; | 58 received_process_group_count_ = done; |
| 59 } | 59 } |
| 60 | 60 |
| 61 // Methods for book keeping of processes_pending_. | 61 // Methods for book keeping of processes_pending_. |
| 62 void IncrementProcessesPending() { | 62 void IncrementProcessesPending() { |
| 63 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 63 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 64 ++processes_pending_; | 64 ++processes_pending_; |
| 65 } | 65 } |
| 66 | 66 |
| 67 void AddProcessesPending(int processes_pending) { | 67 void AddProcessesPending(int processes_pending) { |
| 68 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 68 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 69 processes_pending_ += processes_pending; | 69 processes_pending_ += processes_pending; |
| 70 } | 70 } |
| 71 | 71 |
| 72 void DecrementProcessesPending() { | 72 void DecrementProcessesPending() { |
| 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 73 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 74 --processes_pending_; | 74 --processes_pending_; |
| 75 } | 75 } |
| 76 | 76 |
| 77 // Records that we are waiting for one less tracking data from a process for | 77 // Records that we are waiting for one less tracking data from a process for |
| 78 // the given sequence number. If |received_process_group_count_| and | 78 // the given sequence number. If |received_process_group_count_| and |
| 79 // |processes_pending_| are zero, then delete the current object by calling | 79 // |processes_pending_| are zero, then delete the current object by calling |
| 80 // Unregister. | 80 // Unregister. |
| 81 void DeleteIfAllDone() { | 81 void DeleteIfAllDone() { |
| 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 82 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 83 | 83 |
| 84 if (processes_pending_ <= 0 && received_process_group_count_) | 84 if (processes_pending_ <= 0 && received_process_group_count_) |
| 85 RequestContext::Unregister(sequence_number_); | 85 RequestContext::Unregister(sequence_number_); |
| 86 } | 86 } |
| 87 | 87 |
| 88 // Register |callback_object| in |outstanding_requests_| map for the given | 88 // Register |callback_object| in |outstanding_requests_| map for the given |
| 89 // |sequence_number|. | 89 // |sequence_number|. |
| 90 static RequestContext* Register( | 90 static RequestContext* Register( |
| 91 int sequence_number, | 91 int sequence_number, |
| 92 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { | 92 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { |
| 93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 93 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 94 | 94 |
| 95 RequestContext* request = new RequestContext( | 95 RequestContext* request = new RequestContext( |
| 96 callback_object, sequence_number); | 96 callback_object, sequence_number); |
| 97 outstanding_requests_.Get()[sequence_number] = request; | 97 outstanding_requests_.Get()[sequence_number] = request; |
| 98 | 98 |
| 99 return request; | 99 return request; |
| 100 } | 100 } |
| 101 | 101 |
| 102 // Find the |RequestContext| in |outstanding_requests_| map for the given | 102 // Find the |RequestContext| in |outstanding_requests_| map for the given |
| 103 // |sequence_number|. | 103 // |sequence_number|. |
| 104 static RequestContext* GetRequestContext(int sequence_number) { | 104 static RequestContext* GetRequestContext(int sequence_number) { |
| 105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 105 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 106 | 106 |
| 107 RequestContextMap::iterator it = | 107 RequestContextMap::iterator it = |
| 108 outstanding_requests_.Get().find(sequence_number); | 108 outstanding_requests_.Get().find(sequence_number); |
| 109 if (it == outstanding_requests_.Get().end()) | 109 if (it == outstanding_requests_.Get().end()) |
| 110 return NULL; | 110 return NULL; |
| 111 | 111 |
| 112 RequestContext* request = it->second; | 112 RequestContext* request = it->second; |
| 113 DCHECK_EQ(sequence_number, request->sequence_number_); | 113 DCHECK_EQ(sequence_number, request->sequence_number_); |
| 114 return request; | 114 return request; |
| 115 } | 115 } |
| 116 | 116 |
| 117 // Delete the entry for the given |sequence_number| from | 117 // Delete the entry for the given |sequence_number| from |
| 118 // |outstanding_requests_| map. This method is called when all changes have | 118 // |outstanding_requests_| map. This method is called when all changes have |
| 119 // been acquired, or when the wait time expires (whichever is sooner). | 119 // been acquired, or when the wait time expires (whichever is sooner). |
| 120 static void Unregister(int sequence_number) { | 120 static void Unregister(int sequence_number) { |
| 121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 121 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 122 | 122 |
| 123 RequestContextMap::iterator it = | 123 RequestContextMap::iterator it = |
| 124 outstanding_requests_.Get().find(sequence_number); | 124 outstanding_requests_.Get().find(sequence_number); |
| 125 if (it == outstanding_requests_.Get().end()) | 125 if (it == outstanding_requests_.Get().end()) |
| 126 return; | 126 return; |
| 127 | 127 |
| 128 RequestContext* request = it->second; | 128 RequestContext* request = it->second; |
| 129 DCHECK_EQ(sequence_number, request->sequence_number_); | 129 DCHECK_EQ(sequence_number, request->sequence_number_); |
| 130 bool received_process_group_count = request->received_process_group_count_; | 130 bool received_process_group_count = request->received_process_group_count_; |
| 131 int unresponsive_processes = request->processes_pending_; | 131 int unresponsive_processes = request->processes_pending_; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 191 | 191 |
| 192 // Just in case we have any pending tasks, clear them out. | 192 // Just in case we have any pending tasks, clear them out. |
| 193 RequestContext::OnShutdown(); | 193 RequestContext::OnShutdown(); |
| 194 | 194 |
| 195 g_tracking_synchronizer = NULL; | 195 g_tracking_synchronizer = NULL; |
| 196 } | 196 } |
| 197 | 197 |
| 198 // static | 198 // static |
| 199 void TrackingSynchronizer::FetchProfilerDataAsynchronously( | 199 void TrackingSynchronizer::FetchProfilerDataAsynchronously( |
| 200 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { | 200 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { |
| 201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 201 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 202 | 202 |
| 203 if (!g_tracking_synchronizer) { | 203 if (!g_tracking_synchronizer) { |
| 204 // System teardown is happening. | 204 // System teardown is happening. |
| 205 return; | 205 return; |
| 206 } | 206 } |
| 207 | 207 |
| 208 int sequence_number = g_tracking_synchronizer->RegisterAndNotifyAllProcesses( | 208 int sequence_number = g_tracking_synchronizer->RegisterAndNotifyAllProcesses( |
| 209 callback_object); | 209 callback_object); |
| 210 | 210 |
| 211 // Post a task that would be called after waiting for wait_time. This acts | 211 // 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. | 212 // as a watchdog, to cancel the requests for non-responsive processes. |
| 213 BrowserThread::PostDelayedTask( | 213 BrowserThread::PostDelayedTask( |
| 214 BrowserThread::UI, FROM_HERE, | 214 BrowserThread::UI, FROM_HERE, |
| 215 base::Bind(&RequestContext::Unregister, sequence_number), | 215 base::Bind(&RequestContext::Unregister, sequence_number), |
| 216 base::TimeDelta::FromMinutes(1)); | 216 base::TimeDelta::FromMinutes(1)); |
| 217 } | 217 } |
| 218 | 218 |
| 219 void TrackingSynchronizer::OnPendingProcesses(int sequence_number, | 219 void TrackingSynchronizer::OnPendingProcesses(int sequence_number, |
| 220 int pending_processes, | 220 int pending_processes, |
| 221 bool end) { | 221 bool end) { |
| 222 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 222 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 223 | 223 |
| 224 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 224 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
| 225 if (!request) | 225 if (!request) |
| 226 return; | 226 return; |
| 227 request->AddProcessesPending(pending_processes); | 227 request->AddProcessesPending(pending_processes); |
| 228 request->SetReceivedProcessGroupCount(end); | 228 request->SetReceivedProcessGroupCount(end); |
| 229 request->DeleteIfAllDone(); | 229 request->DeleteIfAllDone(); |
| 230 } | 230 } |
| 231 | 231 |
| 232 void TrackingSynchronizer::OnProfilerDataCollected( | 232 void TrackingSynchronizer::OnProfilerDataCollected( |
| 233 int sequence_number, | 233 int sequence_number, |
| 234 const tracked_objects::ProcessDataSnapshot& profiler_data, | 234 const tracked_objects::ProcessDataSnapshot& profiler_data, |
| 235 int process_type) { | 235 int process_type) { |
| 236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 236 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 237 DecrementPendingProcessesAndSendData(sequence_number, profiler_data, | 237 DecrementPendingProcessesAndSendData(sequence_number, profiler_data, |
| 238 process_type); | 238 process_type); |
| 239 } | 239 } |
| 240 | 240 |
| 241 int TrackingSynchronizer::RegisterAndNotifyAllProcesses( | 241 int TrackingSynchronizer::RegisterAndNotifyAllProcesses( |
| 242 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { | 242 const base::WeakPtr<TrackingSynchronizerObserver>& callback_object) { |
| 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 243 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 244 | 244 |
| 245 int sequence_number = GetNextAvailableSequenceNumber(); | 245 int sequence_number = GetNextAvailableSequenceNumber(); |
| 246 | 246 |
| 247 RequestContext* request = | 247 RequestContext* request = |
| 248 RequestContext::Register(sequence_number, callback_object); | 248 RequestContext::Register(sequence_number, callback_object); |
| 249 | 249 |
| 250 // Increment pending process count for sending browser's profiler data. | 250 // Increment pending process count for sending browser's profiler data. |
| 251 request->IncrementProcessesPending(); | 251 request->IncrementProcessesPending(); |
| 252 | 252 |
| 253 // Get profiler data from renderer and browser child processes. | 253 // Get profiler data from renderer and browser child processes. |
| 254 content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); | 254 content::ProfilerController::GetInstance()->GetProfilerData(sequence_number); |
| 255 | 255 |
| 256 // Send profiler_data from browser process. | 256 // Send profiler_data from browser process. |
| 257 tracked_objects::ProcessDataSnapshot process_data; | 257 tracked_objects::ProcessDataSnapshot process_data; |
| 258 tracked_objects::ThreadData::Snapshot(&process_data); | 258 tracked_objects::ThreadData::Snapshot(&process_data); |
| 259 DecrementPendingProcessesAndSendData(sequence_number, process_data, | 259 DecrementPendingProcessesAndSendData(sequence_number, process_data, |
| 260 content::PROCESS_TYPE_BROWSER); | 260 content::PROCESS_TYPE_BROWSER); |
| 261 | 261 |
| 262 return sequence_number; | 262 return sequence_number; |
| 263 } | 263 } |
| 264 | 264 |
| 265 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( | 265 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( |
| 266 int sequence_number, | 266 int sequence_number, |
| 267 const tracked_objects::ProcessDataSnapshot& profiler_data, | 267 const tracked_objects::ProcessDataSnapshot& profiler_data, |
| 268 int process_type) { | 268 int process_type) { |
| 269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 269 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 270 | 270 |
| 271 RequestContext* request = RequestContext::GetRequestContext(sequence_number); | 271 RequestContext* request = RequestContext::GetRequestContext(sequence_number); |
| 272 if (!request) | 272 if (!request) |
| 273 return; | 273 return; |
| 274 | 274 |
| 275 if (request->callback_object_.get()) { | 275 if (request->callback_object_.get()) { |
| 276 request->callback_object_ | 276 request->callback_object_ |
| 277 ->ReceivedProfilerData(profiler_data, process_type); | 277 ->ReceivedProfilerData(profiler_data, process_type); |
| 278 } | 278 } |
| 279 | 279 |
| 280 // Delete request if we have heard back from all child processes. | 280 // Delete request if we have heard back from all child processes. |
| 281 request->DecrementProcessesPending(); | 281 request->DecrementProcessesPending(); |
| 282 request->DeleteIfAllDone(); | 282 request->DeleteIfAllDone(); |
| 283 } | 283 } |
| 284 | 284 |
| 285 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { | 285 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { |
| 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 286 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 287 | 287 |
| 288 ++last_used_sequence_number_; | 288 ++last_used_sequence_number_; |
| 289 | 289 |
| 290 // Watch out for wrapping to a negative number. | 290 // Watch out for wrapping to a negative number. |
| 291 if (last_used_sequence_number_ < 0) | 291 if (last_used_sequence_number_ < 0) |
| 292 last_used_sequence_number_ = 1; | 292 last_used_sequence_number_ = 1; |
| 293 return last_used_sequence_number_; | 293 return last_used_sequence_number_; |
| 294 } | 294 } |
| 295 | 295 |
| 296 } // namespace metrics | 296 } // namespace metrics |
| OLD | NEW |