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

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: Call ScheduleIntervalCollection at the beginning 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
214 const base::TimeDelta min_interval = 234 const base::TimeDelta min_interval =
215 base::TimeDelta::FromMilliseconds( 235 base::TimeDelta::FromMilliseconds(
216 kMinIntervalBetweenSessionRestoreCollectionsMs); 236 kMinIntervalBetweenSessionRestoreCollectionsMs);
217 const base::TimeDelta time_since_last_collection = 237 const base::TimeDelta time_since_last_collection =
218 (base::TimeTicks::Now() - last_session_restore_collection_time_); 238 (base::TimeTicks::Now() - last_session_restore_collection_time_);
219 // Do not collect if there hasn't been enough elapsed time since the last 239 // Do not collect if there hasn't been enough elapsed time since the last
220 // collection. 240 // collection.
221 if (!last_session_restore_collection_time_.is_null() && 241 if (!last_session_restore_collection_time_.is_null() &&
222 time_since_last_collection < min_interval) { 242 time_since_last_collection < min_interval) {
223 return; 243 return;
224 } 244 }
225 245
226 // Fill out a SampledProfile protobuf that will contain the collected data. 246 // Stop any existing scheduled collection.
227 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 247 if (timer_.IsRunning())
228 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); 248 timer_.Stop();
229 // TODO(sque): Vary the time after restore at which to collect a profile,
230 // and find a way to determine the number of tabs restored.
231 // http://crbug.com/358778.
232 sampled_profile->set_ms_after_restore(0);
233 249
234 CollectIfNecessary(sampled_profile.Pass()); 250 // Randomly pick a delay before doing the collection.
235 last_session_restore_collection_time_ = base::TimeTicks::Now(); 251 base::TimeDelta collection_delay =
252 base::TimeDelta::FromMilliseconds(
253 base::RandGenerator(kMaxRestoreSessionCollectionDelayMs));
254 timer_.Start(
255 FROM_HERE,
256 collection_delay,
257 base::Bind(&PerfProvider::CollectPerfDataAfterSessionRestore,
258 weak_factory_.GetWeakPtr(),
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
259 // If the scheduled time has already passed in the time it took to make the 283 // If the scheduled time has already passed in the time it took to make the
260 // above calculations, trigger the collection event immediately. 284 // above calculations, trigger the collection event immediately.
261 base::TimeTicks now = base::TimeTicks::Now(); 285 base::TimeTicks now = base::TimeTicks::Now();
262 if (scheduled_time < now) 286 if (scheduled_time < now)
263 scheduled_time = now; 287 scheduled_time = now;
264 288
265 timer_.Start(FROM_HERE, scheduled_time - now, this, 289 timer_.Start(FROM_HERE, scheduled_time - now, this,
266 &PerfProvider::DoPeriodicCollection); 290 &PerfProvider::DoPeriodicCollection);
267 291
268 // Update the profiling interval tracker to the start of the next interval. 292 // Update the profiling interval tracker to the start of the next interval.
269 next_profiling_interval_start_ += 293 next_profiling_interval_start_ +=
270 base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs); 294 base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs);
271 } 295 }
272 296
273 void PerfProvider::CollectIfNecessary( 297 void PerfProvider::CollectIfNecessary(
274 scoped_ptr<SampledProfile> sampled_profile) { 298 scoped_ptr<SampledProfile> sampled_profile) {
275 DCHECK(CalledOnValidThread()); 299 DCHECK(CalledOnValidThread());
276 300
301 // Schedule another interval collection. This call makes sense regardless of
302 // whether or not the current collection was interval-triggered. If it had
303 // been another type of trigger event, the interval timer would have been
304 // halted, so it makes sense to reschedule a new interval collection.
305 ScheduleIntervalCollection();
306
277 // Do not collect further data if we've already collected a substantial amount 307 // Do not collect further data if we've already collected a substantial amount
278 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|. 308 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|.
279 size_t cached_perf_data_size = 0; 309 size_t cached_perf_data_size = 0;
280 for (size_t i = 0; i < cached_perf_data_.size(); ++i) { 310 for (size_t i = 0; i < cached_perf_data_.size(); ++i) {
281 cached_perf_data_size += cached_perf_data_[i].ByteSize(); 311 cached_perf_data_size += cached_perf_data_[i].ByteSize();
282 } 312 }
283 if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) { 313 if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) {
284 AddToPerfHistogram(NOT_READY_TO_COLLECT); 314 AddToPerfHistogram(NOT_READY_TO_COLLECT);
285 return; 315 return;
286 } 316 }
(...skipping 19 matching lines...) Expand all
306 weak_factory_.GetWeakPtr(), 336 weak_factory_.GetWeakPtr(),
307 base::Passed(&incognito_observer), 337 base::Passed(&incognito_observer),
308 base::Passed(&sampled_profile))); 338 base::Passed(&sampled_profile)));
309 } 339 }
310 340
311 void PerfProvider::DoPeriodicCollection() { 341 void PerfProvider::DoPeriodicCollection() {
312 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 342 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
313 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); 343 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
314 344
315 CollectIfNecessary(sampled_profile.Pass()); 345 CollectIfNecessary(sampled_profile.Pass());
316 ScheduleCollection(); 346 }
347
348 void PerfProvider::CollectPerfDataAfterResume(
349 const base::TimeDelta& sleep_duration,
350 const base::TimeDelta& time_after_resume) {
351 // Fill out a SampledProfile protobuf that will contain the collected data.
352 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
353 sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND);
354 sampled_profile->set_suspend_duration_ms(sleep_duration.InMilliseconds());
355 sampled_profile->set_ms_after_resume(time_after_resume.InMilliseconds());
356
357 CollectIfNecessary(sampled_profile.Pass());
358 }
359
360 void PerfProvider::CollectPerfDataAfterSessionRestore(
361 const base::TimeDelta& time_after_restore) {
362 // Fill out a SampledProfile protobuf that will contain the collected data.
363 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
364 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
365 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds());
366
367 CollectIfNecessary(sampled_profile.Pass());
368 last_session_restore_collection_time_ = base::TimeTicks::Now();
317 } 369 }
318 370
319 void PerfProvider::ParseProtoIfValid( 371 void PerfProvider::ParseProtoIfValid(
320 scoped_ptr<WindowedIncognitoObserver> incognito_observer, 372 scoped_ptr<WindowedIncognitoObserver> incognito_observer,
321 scoped_ptr<SampledProfile> sampled_profile, 373 scoped_ptr<SampledProfile> sampled_profile,
322 const std::vector<uint8>& data) { 374 const std::vector<uint8>& data) {
323 DCHECK(CalledOnValidThread()); 375 DCHECK(CalledOnValidThread());
324 376
325 if (incognito_observer->incognito_launched()) { 377 if (incognito_observer->incognito_launched()) {
326 AddToPerfHistogram(INCOGNITO_LAUNCHED); 378 AddToPerfHistogram(INCOGNITO_LAUNCHED);
(...skipping 19 matching lines...) Expand all
346 DCHECK(!login_time_.is_null()); 398 DCHECK(!login_time_.is_null());
347 collection_data. 399 collection_data.
348 set_ms_after_login((base::TimeTicks::Now() - login_time_) 400 set_ms_after_login((base::TimeTicks::Now() - login_time_)
349 .InMilliseconds()); 401 .InMilliseconds());
350 402
351 // Finally, store the perf data itself. 403 // Finally, store the perf data itself.
352 collection_data.mutable_perf_data()->Swap(&perf_data_proto); 404 collection_data.mutable_perf_data()->Swap(&perf_data_proto);
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