| 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 | 
|---|