Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: chrome/browser/metrics/tracking_synchronizer.cc

Issue 8413009: Changes to upload tracked_objects data from all renderer (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:executable
+ *
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/metrics/tracking_synchronizer.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/json/json_writer.h"
9 #include "base/logging.h"
10 #include "base/metrics/histogram.h"
11 #include "base/threading/thread.h"
12 #include "base/tracked_objects.h"
13 #include "chrome/common/chrome_constants.h"
14 #include "chrome/common/render_messages.h"
15 #include "content/browser/browser_thread.h"
16 #include "content/browser/renderer_host/render_process_host.h"
17
18 using base::Time;
jar (doing other things) 2011/10/30 08:04:19 We probably won't use this. It is "wall clock" ti
ramant (doing other things) 2011/11/01 00:52:15 Done.
19 using base::TimeDelta;
20 using base::TimeTicks;
21
22 namespace chrome_browser_metrics {
23
24 // Negative numbers are never used as sequence numbers. We explicitly pick a
25 // negative number that is "so negative" that even when we add one (as is done
26 // when we generated the next sequence number) that it will still be negative.
27 // We have code that handles wrapping around on an overflow into negative
28 // territory.
29 static const int kNeverUsableSequenceNumber = -2;
30
31 TrackingSynchronizer::TrackingSynchronizer()
32 : lock_(),
33 last_used_sequence_number_(kNeverUsableSequenceNumber),
34 // TODO(rtenneti): delete last_value_from_renderer_.
35 last_value_from_renderer_(NULL) {
36 DCHECK(tracking_synchronizer_ == NULL);
37 tracking_synchronizer_ = this;
38 }
39
40 TrackingSynchronizer::~TrackingSynchronizer() {
41 // Just in case we have any pending tasks, clear them out.
42 while (!outstanding_requests_.empty()) {
43 RequestContextMap::iterator it = outstanding_requests_.begin();
44 delete it->second;
45 outstanding_requests_.erase(it);
46 }
47
48 tracking_synchronizer_ = NULL;
49 }
50
51 // static
52 TrackingSynchronizer* TrackingSynchronizer::CurrentSynchronizer() {
53 DCHECK(tracking_synchronizer_ != NULL);
54 return tracking_synchronizer_;
55 }
56
57 // static
58 // TODO(rtenneti): Delete this method after testing.
59 void TrackingSynchronizer::FetchTrackingDataSynchronously(std::string* output) {
60 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer();
61
62 CallbackObject* callback_object = new CallbackObject;
63 FetchTrackingDataAsynchronously(callback_object);
64
65 // We get tracked data fro browser process immediately.
66 base::JSONWriter::Write(callback_object->value_, false, output);
jar (doing other things) 2011/10/30 08:04:19 To test this equally simply... you could do a Post
ramant (doing other things) 2011/11/01 00:52:15 Done.
67
68 if (!current_synchronizer->last_value_from_renderer_)
69 return;
70
71 base::JSONWriter::Write(
72 current_synchronizer->last_value_from_renderer_, false, output);
73 }
74
75 // static
76 void TrackingSynchronizer::FetchTrackingDataAsynchronously(
77 CallbackObject* callback_object) {
78 DCHECK(callback_object != NULL);
79
80 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer();
81
82 if (current_synchronizer == NULL) {
83 // System teardown is happening.
84 return;
85 }
86
87 // Get the ThreadData for the browser process and send it back.
88 base::Value* value = tracked_objects::ThreadData::ToValue(0);
89 callback_object->SendData(value);
90
91 int sequence_number = current_synchronizer->RegisterAndNotifyAllProcesses(
92 callback_object);
93
94 // Post a task that would be called after waiting for wait_time. This acts
95 // as a watchdog, to cancel the requests for non-responsive processes.
96 BrowserThread::PostDelayedTask(
97 BrowserThread::UI, FROM_HERE,
98 NewRunnableMethod(
99 current_synchronizer,
100 &TrackingSynchronizer::ForceTrackingSynchronizationDoneCallback,
101 sequence_number),
102 10000);
jar (doing other things) 2011/10/30 08:04:19 You may as well make this a bit longer. There is
ramant (doing other things) 2011/11/01 00:52:15 Done.
103 }
104
105 // static
106 void TrackingSynchronizer::DeserializeTrackingList(
107 int sequence_number,
108 const std::string& tracking_data) {
109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
110
111 base::Value* value =
112 base::JSONReader().JsonToValue(tracking_data, false, true);
113
114 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer();
115 if (current_synchronizer == NULL)
116 return;
jar (doing other things) 2011/10/30 08:04:19 This would leak value. Perhaps you should do the
ramant (doing other things) 2011/11/01 00:52:15 Done.
117
118 // Send back the tracking data we have received from a process.
119 current_synchronizer->DecrementPendingProcessesAndSendData(
120 sequence_number, value);
121 }
122
123 int TrackingSynchronizer::RegisterAndNotifyAllProcesses(
124 CallbackObject* callback_object) {
125 // To iterate over all processes, or to send messages to the hosts, we need
126 // to be on the UI thread.
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
128
129 int notification_count = 0;
130 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
131 !it.IsAtEnd(); it.Advance())
132 ++notification_count;
jar (doing other things) 2011/10/30 08:04:19 This number is probably changing underneath us. I'
ramant (doing other things) 2011/11/01 00:52:15 Done.
133
134 int sequence_number = GetNextAvailableSequenceNumber();
135
136 Register(sequence_number, callback_object, notification_count);
jar (doing other things) 2011/10/30 08:04:19 You should probably just set the count to 1 here (
ramant (doing other things) 2011/11/01 00:52:15 Done.
137
138 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
139 !it.IsAtEnd(); it.Advance()) {
140 if (!it.GetCurrentValue()->Send(
141 new ChromeViewMsg_GetRendererTrackedData(sequence_number)))
142 DecrementPendingProcesses(sequence_number);
143 }
144
145 return sequence_number;
146 }
147
148 void TrackingSynchronizer::Register(int sequence_number,
149 CallbackObject* callback_object,
150 int processes_pending) {
151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
152
153 RequestContext* request = new RequestContext(
154 callback_object, sequence_number, processes_pending, TimeTicks::Now());
155 {
156 base::AutoLock auto_lock(lock_);
jar (doing other things) 2011/10/30 08:04:19 So long as we only access this on the UI thread, w
ramant (doing other things) 2011/11/01 00:52:15 Done.
157 outstanding_requests_[sequence_number] = request;
158 }
159 }
160
161 void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
162 int sequence_number, base::Value* value) {
163 RequestContext* request = NULL;
164 bool completed = false;
165
jar (doing other things) 2011/10/30 08:04:19 DCHECK on UI thread.
ramant (doing other things) 2011/11/01 00:52:15 Done.
166 {
167 base::AutoLock auto_lock(lock_);
168 RequestContextMap::iterator it =
169 outstanding_requests_.find(sequence_number);
170 if (it == outstanding_requests_.end())
171 return;
172
173 request = it->second;
174
175 DCHECK(sequence_number == request->sequence_number_);
176 if (--request->processes_pending_ <= 0)
177 completed = true;
178
179 // TODO(rtenneti): Delete last_value_from_renderer_ after testing.
180 if (value)
181 last_value_from_renderer_ = value;
182 }
183
184 if (request) {
185 // TODO(rtenneti): SendData is called on IO thread. Should
186 // |callback_object_| do a PostTask to UI thread??
jar (doing other things) 2011/10/30 08:04:19 yeah... we should have bounced over to the UI thre
ramant (doing other things) 2011/11/01 00:52:15 Done.
187 request->callback_object_->SendData(value);
jar (doing other things) 2011/10/30 08:04:19 You need to do this only if value is non-null. On
ramant (doing other things) 2011/11/01 00:52:15 Done.
188 }
189
190 if (completed)
191 ForceTrackingSynchronizationDoneCallback(sequence_number);
192 }
193
194 void TrackingSynchronizer::DecrementPendingProcesses(int sequence_number) {
195 DecrementPendingProcessesAndSendData(sequence_number, NULL);
196 }
197
198 void TrackingSynchronizer::ForceTrackingSynchronizationDoneCallback(
199 int sequence_number) {
200 TimeTicks started;
201 int unresponsive_processes;
202 {
203 base::AutoLock lock(lock_);
204 RequestContextMap::iterator it =
205 outstanding_requests_.find(sequence_number);
206 if (it == outstanding_requests_.end())
207 return;
208
209 RequestContext* request = it->second;
210
211 DCHECK(sequence_number == request->sequence_number_);
212
213 started = request->request_start_time_;
214 unresponsive_processes = request->processes_pending_;
215
216 delete it->second;
217 outstanding_requests_.erase(it);
218 }
219
220 UMA_HISTOGRAM_COUNTS("Tracking.ProcessNotRespondingAsynchronous",
221 unresponsive_processes);
222 if (!unresponsive_processes) {
223 UMA_HISTOGRAM_TIMES("Tracking.FetchProcessTrackingsAsynchronously",
224 TimeTicks::Now() - started);
jar (doing other things) 2011/10/30 08:04:19 This duration should almost always be your 10secon
ramant (doing other things) 2011/11/01 00:52:15 Deleted this histogram. Done.
225 }
226 }
227
228 int TrackingSynchronizer::GetNextAvailableSequenceNumber() {
229 base::AutoLock auto_lock(lock_);
230 ++last_used_sequence_number_;
231 // Watch out for wrapping to a negative number.
232 if (last_used_sequence_number_ < 0) {
233 // Bypass the reserved number, which is used when a process spontaneously
234 // decides to send some tracking data.
235 last_used_sequence_number_ =
236 chrome::kTrackingSynchronizerReservedSequenceNumber + 1;
237 }
238 DCHECK_NE(last_used_sequence_number_,
239 chrome::kTrackingSynchronizerReservedSequenceNumber);
240 return last_used_sequence_number_;
241 }
242
243 // static
244 TrackingSynchronizer* TrackingSynchronizer::tracking_synchronizer_ = NULL;
245
246 } // namespace chrome_browser_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698