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

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

Issue 364913007: metrics: Add random delays to perf collection (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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
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 <string> 5 #include <string>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 // There may be too many session restores to collect a profile each time. Limit 47 // There may be too many session restores to collect a profile each time. Limit
48 // the collection rate by collecting one per 10 restores. Adjust this number as 48 // the collection rate by collecting one per 10 restores. Adjust this number as
49 // needed. 49 // needed.
50 const int kRestoreSessionSamplingFactor = 10; 50 const int kRestoreSessionSamplingFactor = 10;
51 51
52 // This is used to space out session restore collections in the face of several 52 // This is used to space out session restore collections in the face of several
53 // notifications in a short period of time. There should be no less than this 53 // notifications in a short period of time. There should be no less than this
54 // much time between collections. The current value is 30 seconds. 54 // much time between collections. The current value is 30 seconds.
55 const int kMinIntervalBetweenSessionRestoreCollectionsMs = 30 * 1000; 55 const int kMinIntervalBetweenSessionRestoreCollectionsMs = 30 * 1000;
56 56
57 // If collecting after a resume, add a random delay before collecting. The delay
58 // should be randomly selected between 0 and this value. Currently the value is
59 // equal to 5 seconds.
60 const int kMaxResumeCollectionDelayMs = 5 * 1000;
61
62 // If collecting after a session restore, add a random delay before collecting.
63 // The delay should be randomly selected between 0 and this value. Currently the
64 // value is equal to 10 seconds.
65 const int kMaxRestoreSessionCollectionDelayMs = 10 * 1000;
66
57 // Enumeration representing success and various failure modes for collecting and 67 // Enumeration representing success and various failure modes for collecting and
58 // sending perf data. 68 // sending perf data.
59 enum GetPerfDataOutcome { 69 enum GetPerfDataOutcome {
60 SUCCESS, 70 SUCCESS,
61 NOT_READY_TO_UPLOAD, 71 NOT_READY_TO_UPLOAD,
62 NOT_READY_TO_COLLECT, 72 NOT_READY_TO_COLLECT,
63 INCOGNITO_ACTIVE, 73 INCOGNITO_ACTIVE,
64 INCOGNITO_LAUNCHED, 74 INCOGNITO_LAUNCHED,
65 PROTOBUF_NOT_PARSED, 75 PROTOBUF_NOT_PARSED,
66 NUM_OUTCOMES 76 NUM_OUTCOMES
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 // canceled. Do not collect anything if that's the case. 188 // canceled. Do not collect anything if that's the case.
179 if (sleep_duration == base::TimeDelta()) 189 if (sleep_duration == base::TimeDelta())
180 return; 190 return;
181 191
182 // Do not collect a profile unless logged in. The system behavior when closing 192 // Do not collect a profile unless logged in. The system behavior when closing
183 // the lid or idling when not logged in is currently to shut down instead of 193 // the lid or idling when not logged in is currently to shut down instead of
184 // suspending. But it's good to enforce the rule here in case that changes. 194 // suspending. But it's good to enforce the rule here in case that changes.
185 if (!IsNormalUserLoggedIn()) 195 if (!IsNormalUserLoggedIn())
186 return; 196 return;
187 197
198 // Do not collect if there is an existing collection scheduled.
199 if (resume_timer_.IsRunning())
200 return;
201
188 // Collect a profile only 1/|kResumeSamplingFactor| of the time, to avoid 202 // Collect a profile only 1/|kResumeSamplingFactor| of the time, to avoid
189 // collecting too much data. 203 // collecting too much data.
190 if (base::RandGenerator(kResumeSamplingFactor) != 0) 204 if (base::RandGenerator(kResumeSamplingFactor) != 0)
191 return; 205 return;
192 206
193 // Fill out a SampledProfile protobuf that will contain the collected data. 207 // Randomly pick a delay before doing the collection.
194 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 208 uint64 collection_delay_ms = base::RandGenerator(kMaxResumeCollectionDelayMs);
195 sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND); 209 resume_timer_.Start(FROM_HERE,
196 sampled_profile->set_suspend_duration_ms(sleep_duration.InMilliseconds()); 210 base::TimeDelta::FromMilliseconds(collection_delay_ms),
197 // TODO(sque): Vary the time after resume at which to collect a profile. 211 base::Bind(&PerfProvider::DoResumeCollection,
198 // http://crbug.com/358778. 212 weak_factory_.GetWeakPtr(),
199 sampled_profile->set_ms_after_resume(0); 213 sleep_duration.InMilliseconds(),
200 CollectIfNecessary(sampled_profile.Pass()); 214 collection_delay_ms));
201 } 215 }
202 216
203 void PerfProvider::Observe(int type, 217 void PerfProvider::Observe(int type,
204 const content::NotificationSource& source, 218 const content::NotificationSource& source,
205 const content::NotificationDetails& details) { 219 const content::NotificationDetails& details) {
206 // Only handle session restore notifications. 220 // Only handle session restore notifications.
207 DCHECK_EQ(type, chrome::NOTIFICATION_SESSION_RESTORE_DONE); 221 DCHECK_EQ(type, chrome::NOTIFICATION_SESSION_RESTORE_DONE);
208 222
223 // Do not collect if there is an existing collection scheduled.
224 if (restore_session_timer_.IsRunning())
225 return;
226
209 // Collect a profile only 1/|kRestoreSessionSamplingFactor| of the time, to 227 // Collect a profile only 1/|kRestoreSessionSamplingFactor| of the time, to
210 // avoid collecting too much data and potentially causing UI latency. 228 // avoid collecting too much data and potentially causing UI latency.
211 if (base::RandGenerator(kRestoreSessionSamplingFactor) != 0) 229 if (base::RandGenerator(kRestoreSessionSamplingFactor) != 0)
212 return; 230 return;
213 231
214 const base::TimeDelta min_interval = 232 const base::TimeDelta min_interval =
215 base::TimeDelta::FromMilliseconds( 233 base::TimeDelta::FromMilliseconds(
216 kMinIntervalBetweenSessionRestoreCollectionsMs); 234 kMinIntervalBetweenSessionRestoreCollectionsMs);
217 const base::TimeDelta time_since_last_collection = 235 const base::TimeDelta time_since_last_collection =
218 (base::TimeTicks::Now() - last_session_restore_collection_time_); 236 (base::TimeTicks::Now() - last_session_restore_collection_time_);
219 // Do not collect if there hasn't been enough elapsed time since the last 237 // Do not collect if there hasn't been enough elapsed time since the last
220 // collection. 238 // collection.
221 if (!last_session_restore_collection_time_.is_null() && 239 if (!last_session_restore_collection_time_.is_null() &&
222 time_since_last_collection < min_interval) { 240 time_since_last_collection < min_interval) {
223 return; 241 return;
224 } 242 }
225 243
226 // Fill out a SampledProfile protobuf that will contain the collected data. 244 // Randomly pick a delay before doing the collection.
227 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 245 uint64 collection_delay_ms =
228 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); 246 base::RandGenerator(kMaxRestoreSessionCollectionDelayMs);
229 // TODO(sque): Vary the time after restore at which to collect a profile, 247 restore_session_timer_.Start(
230 // and find a way to determine the number of tabs restored. 248 FROM_HERE,
231 // http://crbug.com/358778. 249 base::TimeDelta::FromMilliseconds(collection_delay_ms),
232 sampled_profile->set_ms_after_restore(0); 250 base::Bind(&PerfProvider::DoRestoreSessionCollection,
233 251 weak_factory_.GetWeakPtr(),
234 CollectIfNecessary(sampled_profile.Pass()); 252 collection_delay_ms));
235 last_session_restore_collection_time_ = base::TimeTicks::Now();
236 } 253 }
237 254
238 void PerfProvider::OnUserLoggedIn() { 255 void PerfProvider::OnUserLoggedIn() {
239 login_time_ = base::TimeTicks::Now(); 256 login_time_ = base::TimeTicks::Now();
240 ScheduleCollection(); 257 ScheduleCollection();
241 } 258 }
242 259
243 void PerfProvider::Deactivate() { 260 void PerfProvider::Deactivate() {
244 // Stop the timer, but leave |cached_perf_data_| intact. 261 // Stop the timer, but leave |cached_perf_data_| intact.
245 timer_.Stop(); 262 interval_timer_.Stop();
Ilya Sherman 2014/07/03 00:12:47 Should this stop the other timers as well? In fac
Simon Que 2014/07/07 19:45:26 Done. I think the three timers are needed so that
Ilya Sherman 2014/07/08 00:06:40 Why do the timers need to run independently?
246 } 263 }
247 264
248 void PerfProvider::ScheduleCollection() { 265 void PerfProvider::ScheduleCollection() {
249 DCHECK(CalledOnValidThread()); 266 DCHECK(CalledOnValidThread());
250 if (timer_.IsRunning()) 267 if (interval_timer_.IsRunning())
251 return; 268 return;
252 269
253 // Pick a random time in the current interval. 270 // Pick a random time in the current interval.
254 base::TimeTicks scheduled_time = 271 base::TimeTicks scheduled_time =
255 next_profiling_interval_start_ + 272 next_profiling_interval_start_ +
256 base::TimeDelta::FromMilliseconds( 273 base::TimeDelta::FromMilliseconds(
257 base::RandGenerator(kPerfProfilingIntervalMs)); 274 base::RandGenerator(kPerfProfilingIntervalMs));
258 275
259 // If the scheduled time has already passed in the time it took to make the 276 // If the scheduled time has already passed in the time it took to make the
260 // above calculations, trigger the collection event immediately. 277 // above calculations, trigger the collection event immediately.
261 base::TimeTicks now = base::TimeTicks::Now(); 278 base::TimeTicks now = base::TimeTicks::Now();
262 if (scheduled_time < now) 279 if (scheduled_time < now)
263 scheduled_time = now; 280 scheduled_time = now;
264 281
265 timer_.Start(FROM_HERE, scheduled_time - now, this, 282 interval_timer_.Start(FROM_HERE, scheduled_time - now, this,
266 &PerfProvider::DoPeriodicCollection); 283 &PerfProvider::DoPeriodicCollection);
267 284
268 // Update the profiling interval tracker to the start of the next interval. 285 // Update the profiling interval tracker to the start of the next interval.
269 next_profiling_interval_start_ += 286 next_profiling_interval_start_ +=
270 base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs); 287 base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs);
271 } 288 }
272 289
273 void PerfProvider::CollectIfNecessary( 290 void PerfProvider::CollectIfNecessary(
274 scoped_ptr<SampledProfile> sampled_profile) { 291 scoped_ptr<SampledProfile> sampled_profile) {
275 DCHECK(CalledOnValidThread()); 292 DCHECK(CalledOnValidThread());
276 293
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 } 326 }
310 327
311 void PerfProvider::DoPeriodicCollection() { 328 void PerfProvider::DoPeriodicCollection() {
312 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 329 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
313 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); 330 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
314 331
315 CollectIfNecessary(sampled_profile.Pass()); 332 CollectIfNecessary(sampled_profile.Pass());
316 ScheduleCollection(); 333 ScheduleCollection();
317 } 334 }
318 335
336 void PerfProvider::DoResumeCollection(uint64 sleep_duration_ms,
337 uint64 time_after_resume_ms) {
338 // Fill out a SampledProfile protobuf that will contain the collected data.
339 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
340 sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND);
341 sampled_profile->set_suspend_duration_ms(sleep_duration_ms);
342 sampled_profile->set_ms_after_resume(time_after_resume_ms);
343
344 CollectIfNecessary(sampled_profile.Pass());
345 }
346
347 void PerfProvider::DoRestoreSessionCollection(uint64 time_after_restore_ms) {
348 // Fill out a SampledProfile protobuf that will contain the collected data.
349 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
350 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
351 sampled_profile->set_ms_after_restore(time_after_restore_ms);
352
353 CollectIfNecessary(sampled_profile.Pass());
354 last_session_restore_collection_time_ = base::TimeTicks::Now();
355 }
356
319 void PerfProvider::ParseProtoIfValid( 357 void PerfProvider::ParseProtoIfValid(
320 scoped_ptr<WindowedIncognitoObserver> incognito_observer, 358 scoped_ptr<WindowedIncognitoObserver> incognito_observer,
321 scoped_ptr<SampledProfile> sampled_profile, 359 scoped_ptr<SampledProfile> sampled_profile,
322 const std::vector<uint8>& data) { 360 const std::vector<uint8>& data) {
323 DCHECK(CalledOnValidThread()); 361 DCHECK(CalledOnValidThread());
324 362
325 if (incognito_observer->incognito_launched()) { 363 if (incognito_observer->incognito_launched()) {
326 AddToPerfHistogram(INCOGNITO_LAUNCHED); 364 AddToPerfHistogram(INCOGNITO_LAUNCHED);
327 return; 365 return;
328 } 366 }
(...skipping 17 matching lines...) Expand all
346 DCHECK(!login_time_.is_null()); 384 DCHECK(!login_time_.is_null());
347 collection_data. 385 collection_data.
348 set_ms_after_login((base::TimeTicks::Now() - login_time_) 386 set_ms_after_login((base::TimeTicks::Now() - login_time_)
349 .InMilliseconds()); 387 .InMilliseconds());
350 388
351 // Finally, store the perf data itself. 389 // Finally, store the perf data itself.
352 collection_data.mutable_perf_data()->Swap(&perf_data_proto); 390 collection_data.mutable_perf_data()->Swap(&perf_data_proto);
353 } 391 }
354 392
355 } // namespace metrics 393 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698