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 |