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

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: Use only one timer 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
« no previous file with comments | « chrome/browser/metrics/perf_provider_chromeos.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
188 // Collect a profile only 1/|kResumeSamplingFactor| of the time, to avoid 198 // Collect a profile only 1/|kResumeSamplingFactor| of the time, to avoid
189 // collecting too much data. 199 // collecting too much data.
190 if (base::RandGenerator(kResumeSamplingFactor) != 0) 200 if (base::RandGenerator(kResumeSamplingFactor) != 0)
191 return; 201 return;
192 202
193 // Fill out a SampledProfile protobuf that will contain the collected data. 203 // Override any existing profiling.
194 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 204 if (timer_.IsRunning())
195 sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND); 205 timer_.Stop();
196 sampled_profile->set_suspend_duration_ms(sleep_duration.InMilliseconds()); 206
197 // TODO(sque): Vary the time after resume at which to collect a profile. 207 // Randomly pick a delay before doing the collection.
198 // http://crbug.com/358778. 208 base::TimeDelta collection_delay =
199 sampled_profile->set_ms_after_resume(0); 209 base::TimeDelta::FromMilliseconds(
200 CollectIfNecessary(sampled_profile.Pass()); 210 base::RandGenerator(kMaxResumeCollectionDelayMs));
211 timer_.Start(FROM_HERE,
212 collection_delay,
213 base::Bind(&PerfProvider::CollectPerfDataAfterResume,
214 weak_factory_.GetWeakPtr(),
215 sleep_duration,
216 collection_delay));
201 } 217 }
202 218
203 void PerfProvider::Observe(int type, 219 void PerfProvider::Observe(int type,
204 const content::NotificationSource& source, 220 const content::NotificationSource& source,
205 const content::NotificationDetails& details) { 221 const content::NotificationDetails& details) {
206 // Only handle session restore notifications. 222 // Only handle session restore notifications.
207 DCHECK_EQ(type, chrome::NOTIFICATION_SESSION_RESTORE_DONE); 223 DCHECK_EQ(type, chrome::NOTIFICATION_SESSION_RESTORE_DONE);
208 224
225 // Do not collect a profile unless logged in as a normal user.
226 if (!IsNormalUserLoggedIn())
227 return;
228
209 // Collect a profile only 1/|kRestoreSessionSamplingFactor| of the time, to 229 // Collect a profile only 1/|kRestoreSessionSamplingFactor| of the time, to
210 // avoid collecting too much data and potentially causing UI latency. 230 // avoid collecting too much data and potentially causing UI latency.
211 if (base::RandGenerator(kRestoreSessionSamplingFactor) != 0) 231 if (base::RandGenerator(kRestoreSessionSamplingFactor) != 0)
212 return; 232 return;
213 233
234 // Stop any existing scheduled collection.
235 if (timer_.IsRunning())
236 timer_.Stop();
Ilya Sherman 2014/07/12 03:11:56 It looks like if the early-return below is reached
Simon Que 2014/07/14 21:08:30 Done.
237
214 const base::TimeDelta min_interval = 238 const base::TimeDelta min_interval =
215 base::TimeDelta::FromMilliseconds( 239 base::TimeDelta::FromMilliseconds(
216 kMinIntervalBetweenSessionRestoreCollectionsMs); 240 kMinIntervalBetweenSessionRestoreCollectionsMs);
217 const base::TimeDelta time_since_last_collection = 241 const base::TimeDelta time_since_last_collection =
218 (base::TimeTicks::Now() - last_session_restore_collection_time_); 242 (base::TimeTicks::Now() - last_session_restore_collection_time_);
219 // Do not collect if there hasn't been enough elapsed time since the last 243 // Do not collect if there hasn't been enough elapsed time since the last
220 // collection. 244 // collection.
221 if (!last_session_restore_collection_time_.is_null() && 245 if (!last_session_restore_collection_time_.is_null() &&
222 time_since_last_collection < min_interval) { 246 time_since_last_collection < min_interval) {
223 return; 247 return;
224 } 248 }
225 249
226 // Fill out a SampledProfile protobuf that will contain the collected data. 250 // Randomly pick a delay before doing the collection.
227 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 251 base::TimeDelta collection_delay =
228 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); 252 base::TimeDelta::FromMilliseconds(
229 // TODO(sque): Vary the time after restore at which to collect a profile, 253 base::RandGenerator(kMaxRestoreSessionCollectionDelayMs));
230 // and find a way to determine the number of tabs restored. 254 timer_.Start(
231 // http://crbug.com/358778. 255 FROM_HERE,
232 sampled_profile->set_ms_after_restore(0); 256 collection_delay,
233 257 base::Bind(&PerfProvider::CollectPerfDataAfterSessionRestore,
234 CollectIfNecessary(sampled_profile.Pass()); 258 weak_factory_.GetWeakPtr(),
235 last_session_restore_collection_time_ = base::TimeTicks::Now(); 259 collection_delay));
236 } 260 }
237 261
238 void PerfProvider::OnUserLoggedIn() { 262 void PerfProvider::OnUserLoggedIn() {
239 login_time_ = base::TimeTicks::Now(); 263 login_time_ = base::TimeTicks::Now();
240 ScheduleCollection(); 264 ScheduleIntervalCollection();
241 } 265 }
242 266
243 void PerfProvider::Deactivate() { 267 void PerfProvider::Deactivate() {
244 // Stop the timer, but leave |cached_perf_data_| intact. 268 // Stop the timer, but leave |cached_perf_data_| intact.
245 timer_.Stop(); 269 timer_.Stop();
246 } 270 }
247 271
248 void PerfProvider::ScheduleCollection() { 272 void PerfProvider::ScheduleIntervalCollection() {
249 DCHECK(CalledOnValidThread()); 273 DCHECK(CalledOnValidThread());
250 if (timer_.IsRunning()) 274 if (timer_.IsRunning())
251 return; 275 return;
252 276
253 // Pick a random time in the current interval. 277 // Pick a random time in the current interval.
254 base::TimeTicks scheduled_time = 278 base::TimeTicks scheduled_time =
255 next_profiling_interval_start_ + 279 next_profiling_interval_start_ +
256 base::TimeDelta::FromMilliseconds( 280 base::TimeDelta::FromMilliseconds(
257 base::RandGenerator(kPerfProfilingIntervalMs)); 281 base::RandGenerator(kPerfProfilingIntervalMs));
258 282
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 weak_factory_.GetWeakPtr(), 330 weak_factory_.GetWeakPtr(),
307 base::Passed(&incognito_observer), 331 base::Passed(&incognito_observer),
308 base::Passed(&sampled_profile))); 332 base::Passed(&sampled_profile)));
309 } 333 }
310 334
311 void PerfProvider::DoPeriodicCollection() { 335 void PerfProvider::DoPeriodicCollection() {
312 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 336 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
313 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); 337 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
314 338
315 CollectIfNecessary(sampled_profile.Pass()); 339 CollectIfNecessary(sampled_profile.Pass());
316 ScheduleCollection(); 340 }
341
342 void PerfProvider::CollectPerfDataAfterResume(
343 const base::TimeDelta& sleep_duration,
344 const base::TimeDelta& time_after_resume) {
345 // Fill out a SampledProfile protobuf that will contain the collected data.
346 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
347 sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND);
348 sampled_profile->set_suspend_duration_ms(sleep_duration.InMilliseconds());
349 sampled_profile->set_ms_after_resume(time_after_resume.InMilliseconds());
350
351 CollectIfNecessary(sampled_profile.Pass());
352 }
353
354 void PerfProvider::CollectPerfDataAfterSessionRestore(
355 const base::TimeDelta& time_after_restore) {
356 // Fill out a SampledProfile protobuf that will contain the collected data.
357 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
358 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
359 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds());
360
361 CollectIfNecessary(sampled_profile.Pass());
362 last_session_restore_collection_time_ = base::TimeTicks::Now();
317 } 363 }
318 364
319 void PerfProvider::ParseProtoIfValid( 365 void PerfProvider::ParseProtoIfValid(
320 scoped_ptr<WindowedIncognitoObserver> incognito_observer, 366 scoped_ptr<WindowedIncognitoObserver> incognito_observer,
321 scoped_ptr<SampledProfile> sampled_profile, 367 scoped_ptr<SampledProfile> sampled_profile,
322 const std::vector<uint8>& data) { 368 const std::vector<uint8>& data) {
323 DCHECK(CalledOnValidThread()); 369 DCHECK(CalledOnValidThread());
324 370
325 if (incognito_observer->incognito_launched()) { 371 if (incognito_observer->incognito_launched()) {
326 AddToPerfHistogram(INCOGNITO_LAUNCHED); 372 AddToPerfHistogram(INCOGNITO_LAUNCHED);
(...skipping 16 matching lines...) Expand all
343 collection_data.set_ms_after_boot( 389 collection_data.set_ms_after_boot(
344 perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond); 390 perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond);
345 391
346 DCHECK(!login_time_.is_null()); 392 DCHECK(!login_time_.is_null());
347 collection_data. 393 collection_data.
348 set_ms_after_login((base::TimeTicks::Now() - login_time_) 394 set_ms_after_login((base::TimeTicks::Now() - login_time_)
349 .InMilliseconds()); 395 .InMilliseconds());
350 396
351 // Finally, store the perf data itself. 397 // Finally, store the perf data itself.
352 collection_data.mutable_perf_data()->Swap(&perf_data_proto); 398 collection_data.mutable_perf_data()->Swap(&perf_data_proto);
399
400 // Schedule another interval collection. This call makes sense regardless of
401 // whether or not the current collection was interval-triggered. If it had
402 // been another type of trigger event, the interval timer would have been
403 // halted, so it makes sense to reschedule a new interval collection.
404 ScheduleIntervalCollection();
Ilya Sherman 2014/07/12 03:11:56 What if there was an early return from CollectIfNe
Simon Que 2014/07/14 21:08:30 Done.
353 } 405 }
354 406
355 } // namespace metrics 407 } // namespace metrics
OLDNEW
« no previous file with comments | « chrome/browser/metrics/perf_provider_chromeos.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698