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

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

Issue 10454086: Histograms - Support histograms for Plugins, GPU (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 6 months 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/metrics/histogram_synchronizer.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram.h"
10 #include "base/threading/thread.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "chrome/common/chrome_constants.h"
13 #include "chrome/common/render_messages.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "content/public/browser/render_process_host.h"
16
17 using base::Time;
18 using base::TimeDelta;
19 using base::TimeTicks;
20 using content::BrowserThread;
21
22 // Negative numbers are never used as sequence numbers. We explicitly pick a
23 // negative number that is "so negative" that even when we add one (as is done
24 // when we generated the next sequence number) that it will still be negative.
25 // We have code that handles wrapping around on an overflow into negative
26 // territory.
27 static const int kNeverUsableSequenceNumber = -2;
28
29 HistogramSynchronizer::HistogramSynchronizer()
30 : lock_(),
31 received_all_renderer_histograms_(&lock_),
32 callback_thread_(NULL),
33 last_used_sequence_number_(kNeverUsableSequenceNumber),
34 async_sequence_number_(kNeverUsableSequenceNumber),
35 async_renderers_pending_(0),
36 synchronous_sequence_number_(kNeverUsableSequenceNumber),
37 synchronous_renderers_pending_(0) {
38 DCHECK(histogram_synchronizer_ == NULL);
39 histogram_synchronizer_ = this;
40 }
41
42 HistogramSynchronizer::~HistogramSynchronizer() {
43 // Just in case we have any pending tasks, clear them out.
44 SetCallbackTaskAndThread(NULL, base::Closure());
45 histogram_synchronizer_ = NULL;
46 }
47
48 // static
49 HistogramSynchronizer* HistogramSynchronizer::CurrentSynchronizer() {
50 DCHECK(histogram_synchronizer_ != NULL);
51 return histogram_synchronizer_;
52 }
53
54 void HistogramSynchronizer::FetchRendererHistogramsSynchronously(
55 TimeDelta wait_time) {
56 NotifyAllRenderers(SYNCHRONOUS_HISTOGRAMS);
57
58 TimeTicks start = TimeTicks::Now();
59 TimeTicks end_time = start + wait_time;
60 int unresponsive_renderer_count;
61 {
62 base::AutoLock auto_lock(lock_);
63 while (synchronous_renderers_pending_ > 0 && TimeTicks::Now() < end_time) {
64 wait_time = end_time - TimeTicks::Now();
65 base::ThreadRestrictions::ScopedAllowWait allow_wait;
66 received_all_renderer_histograms_.TimedWait(wait_time);
67 }
68 unresponsive_renderer_count = synchronous_renderers_pending_;
69 synchronous_renderers_pending_ = 0;
70 synchronous_sequence_number_ = kNeverUsableSequenceNumber;
71 }
72 UMA_HISTOGRAM_COUNTS("Histogram.RendersNotRespondingSynchronous",
73 unresponsive_renderer_count);
74 if (!unresponsive_renderer_count)
75 UMA_HISTOGRAM_TIMES("Histogram.FetchRendererHistogramsSynchronously",
76 TimeTicks::Now() - start);
77 }
78
79 // static
80 void HistogramSynchronizer::FetchRendererHistogramsAsynchronously(
81 MessageLoop* callback_thread,
82 const base::Closure& callback,
83 base::TimeDelta wait_time) {
84 DCHECK(callback_thread != NULL);
85 DCHECK(!callback.is_null());
86
87 HistogramSynchronizer* current_synchronizer = CurrentSynchronizer();
88
89 if (current_synchronizer == NULL) {
90 // System teardown is happening.
91 callback_thread->PostTask(FROM_HERE, callback);
92 return;
93 }
94
95 current_synchronizer->SetCallbackTaskAndThread(callback_thread,
96 callback);
97
98 int sequence_number =
99 current_synchronizer->NotifyAllRenderers(ASYNC_HISTOGRAMS);
100
101 // Post a task that would be called after waiting for wait_time. This acts
102 // as a watchdog, to ensure that a non-responsive renderer won't block us from
103 // making the callback.
104 BrowserThread::PostDelayedTask(
105 BrowserThread::UI, FROM_HERE,
106 base::Bind(
107 &HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback,
108 current_synchronizer,
109 sequence_number),
110 wait_time);
111 }
112
113 // static
114 void HistogramSynchronizer::DeserializeHistogramList(
115 int sequence_number,
116 const std::vector<std::string>& histograms) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
118 for (std::vector<std::string>::const_iterator it = histograms.begin();
119 it < histograms.end();
120 ++it) {
121 base::Histogram::DeserializeHistogramInfo(*it);
122 }
123
124 HistogramSynchronizer* current_synchronizer = CurrentSynchronizer();
125 if (current_synchronizer == NULL)
126 return;
127
128 // Record that we have received a histogram from renderer process.
129 current_synchronizer->DecrementPendingRenderers(sequence_number);
130 }
131
132 int HistogramSynchronizer::NotifyAllRenderers(
133 RendererHistogramRequester requester) {
134 // To iterate over RenderProcessHosts, or to send messages to the hosts, we
135 // need to be on the UI thread.
136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
137
138 int notification_count = 0;
139 for (content::RenderProcessHost::iterator it(
140 content::RenderProcessHost::AllHostsIterator());
141 !it.IsAtEnd(); it.Advance())
142 ++notification_count;
143
144 int sequence_number = GetNextAvailableSequenceNumber(requester,
145 notification_count);
146 for (content::RenderProcessHost::iterator it(
147 content::RenderProcessHost::AllHostsIterator());
148 !it.IsAtEnd(); it.Advance()) {
149 if (!it.GetCurrentValue()->Send(
150 new ChromeViewMsg_GetRendererHistograms(sequence_number)))
151 DecrementPendingRenderers(sequence_number);
152 }
153
154 return sequence_number;
155 }
156
157 void HistogramSynchronizer::DecrementPendingRenderers(int sequence_number) {
158 bool synchronous_completed = false;
159 bool asynchronous_completed = false;
160
161 {
162 base::AutoLock auto_lock(lock_);
163 if (sequence_number == async_sequence_number_) {
164 if (--async_renderers_pending_ <= 0)
165 asynchronous_completed = true;
166 } else if (sequence_number == synchronous_sequence_number_) {
167 if (--synchronous_renderers_pending_ <= 0)
168 synchronous_completed = true;
169 }
170 }
171
172 if (asynchronous_completed)
173 ForceHistogramSynchronizationDoneCallback(sequence_number);
174 else if (synchronous_completed)
175 received_all_renderer_histograms_.Signal();
176 }
177
178 void HistogramSynchronizer::SetCallbackTaskAndThread(
179 MessageLoop* callback_thread,
180 const base::Closure& callback) {
181 base::Closure old_callback;
182 MessageLoop* old_thread = NULL;
183 TimeTicks old_start_time;
184 int unresponsive_renderers;
185 const TimeTicks now = TimeTicks::Now();
186 {
187 base::AutoLock auto_lock(lock_);
188 old_callback = callback_;
189 callback_ = callback;
190 old_thread = callback_thread_;
191 callback_thread_ = callback_thread;
192 unresponsive_renderers = async_renderers_pending_;
193 old_start_time = async_callback_start_time_;
194 async_callback_start_time_ = now;
195 // Prevent premature calling of our new callbacks.
196 async_sequence_number_ = kNeverUsableSequenceNumber;
197 }
198 // Just in case there was a task pending....
199 InternalPostTask(old_thread, old_callback, unresponsive_renderers,
200 old_start_time);
201 }
202
203 void HistogramSynchronizer::ForceHistogramSynchronizationDoneCallback(
204 int sequence_number) {
205 base::Closure callback;
206 MessageLoop* thread = NULL;
207 TimeTicks started;
208 int unresponsive_renderers;
209 {
210 base::AutoLock lock(lock_);
211 if (sequence_number != async_sequence_number_)
212 return;
213 callback = callback_;
214 thread = callback_thread_;
215 callback_.Reset();
216 callback_thread_ = NULL;
217 started = async_callback_start_time_;
218 unresponsive_renderers = async_renderers_pending_;
219 }
220 InternalPostTask(thread, callback, unresponsive_renderers, started);
221 }
222
223 void HistogramSynchronizer::InternalPostTask(MessageLoop* thread,
224 const base::Closure& callback,
225 int unresponsive_renderers,
226 const base::TimeTicks& started) {
227 if (callback.is_null() || !thread)
228 return;
229 UMA_HISTOGRAM_COUNTS("Histogram.RendersNotRespondingAsynchronous",
230 unresponsive_renderers);
231 if (!unresponsive_renderers) {
232 UMA_HISTOGRAM_TIMES("Histogram.FetchRendererHistogramsAsynchronously",
233 TimeTicks::Now() - started);
234 }
235
236 thread->PostTask(FROM_HERE, callback);
237 }
238
239 int HistogramSynchronizer::GetNextAvailableSequenceNumber(
240 RendererHistogramRequester requester,
241 int renderer_count) {
242 base::AutoLock auto_lock(lock_);
243 ++last_used_sequence_number_;
244 // Watch out for wrapping to a negative number.
245 if (last_used_sequence_number_ < 0) {
246 // Bypass the reserved number, which is used when a renderer spontaneously
247 // decides to send some histogram data.
248 last_used_sequence_number_ =
249 chrome::kHistogramSynchronizerReservedSequenceNumber + 1;
250 }
251 DCHECK_NE(last_used_sequence_number_,
252 chrome::kHistogramSynchronizerReservedSequenceNumber);
253 if (requester == ASYNC_HISTOGRAMS) {
254 async_sequence_number_ = last_used_sequence_number_;
255 async_renderers_pending_ = renderer_count;
256 } else if (requester == SYNCHRONOUS_HISTOGRAMS) {
257 synchronous_sequence_number_ = last_used_sequence_number_;
258 synchronous_renderers_pending_ = renderer_count;
259 }
260 return last_used_sequence_number_;
261 }
262
263 // static
264 HistogramSynchronizer* HistogramSynchronizer::histogram_synchronizer_ = NULL;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698