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

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: Schedule next interval collection if collection never takes place 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
(...skipping 16 matching lines...) Expand all
275 DCHECK(CalledOnValidThread()); 299 DCHECK(CalledOnValidThread());
276 300
277 // Do not collect further data if we've already collected a substantial amount 301 // Do not collect further data if we've already collected a substantial amount
278 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|. 302 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|.
279 size_t cached_perf_data_size = 0; 303 size_t cached_perf_data_size = 0;
280 for (size_t i = 0; i < cached_perf_data_.size(); ++i) { 304 for (size_t i = 0; i < cached_perf_data_.size(); ++i) {
281 cached_perf_data_size += cached_perf_data_[i].ByteSize(); 305 cached_perf_data_size += cached_perf_data_[i].ByteSize();
282 } 306 }
283 if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) { 307 if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) {
284 AddToPerfHistogram(NOT_READY_TO_COLLECT); 308 AddToPerfHistogram(NOT_READY_TO_COLLECT);
309 // Schedule the next interval-based perf collection.
310 ScheduleIntervalCollection();
Ilya Sherman 2014/07/16 22:01:19 Why not just call this at the beginning of Collect
Simon Que 2014/07/16 22:26:54 Done.
285 return; 311 return;
286 } 312 }
287 313
288 // For privacy reasons, Chrome should only collect perf data if there is no 314 // For privacy reasons, Chrome should only collect perf data if there is no
289 // incognito session active (or gets spawned during the collection). 315 // incognito session active (or gets spawned during the collection).
290 if (BrowserList::IsOffTheRecordSessionActive()) { 316 if (BrowserList::IsOffTheRecordSessionActive()) {
291 AddToPerfHistogram(INCOGNITO_ACTIVE); 317 AddToPerfHistogram(INCOGNITO_ACTIVE);
318 // Schedule the next interval-based perf collection.
319 ScheduleIntervalCollection();
292 return; 320 return;
293 } 321 }
294 322
295 scoped_ptr<WindowedIncognitoObserver> incognito_observer( 323 scoped_ptr<WindowedIncognitoObserver> incognito_observer(
296 new WindowedIncognitoObserver); 324 new WindowedIncognitoObserver);
297 325
298 chromeos::DebugDaemonClient* client = 326 chromeos::DebugDaemonClient* client =
299 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); 327 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
300 328
301 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds( 329 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
302 kPerfCommandDurationDefaultSeconds); 330 kPerfCommandDurationDefaultSeconds);
303 331
304 client->GetPerfData(collection_duration.InSeconds(), 332 client->GetPerfData(collection_duration.InSeconds(),
305 base::Bind(&PerfProvider::ParseProtoIfValid, 333 base::Bind(&PerfProvider::ParseProtoIfValid,
306 weak_factory_.GetWeakPtr(), 334 weak_factory_.GetWeakPtr(),
307 base::Passed(&incognito_observer), 335 base::Passed(&incognito_observer),
308 base::Passed(&sampled_profile))); 336 base::Passed(&sampled_profile)));
309 } 337 }
310 338
311 void PerfProvider::DoPeriodicCollection() { 339 void PerfProvider::DoPeriodicCollection() {
312 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 340 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
313 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); 341 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
314 342
315 CollectIfNecessary(sampled_profile.Pass()); 343 CollectIfNecessary(sampled_profile.Pass());
316 ScheduleCollection(); 344 }
345
346 void PerfProvider::CollectPerfDataAfterResume(
347 const base::TimeDelta& sleep_duration,
348 const base::TimeDelta& time_after_resume) {
349 // Fill out a SampledProfile protobuf that will contain the collected data.
350 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
351 sampled_profile->set_trigger_event(SampledProfile::RESUME_FROM_SUSPEND);
352 sampled_profile->set_suspend_duration_ms(sleep_duration.InMilliseconds());
353 sampled_profile->set_ms_after_resume(time_after_resume.InMilliseconds());
354
355 CollectIfNecessary(sampled_profile.Pass());
356 }
357
358 void PerfProvider::CollectPerfDataAfterSessionRestore(
359 const base::TimeDelta& time_after_restore) {
360 // Fill out a SampledProfile protobuf that will contain the collected data.
361 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
362 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
363 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds());
364
365 CollectIfNecessary(sampled_profile.Pass());
366 last_session_restore_collection_time_ = base::TimeTicks::Now();
317 } 367 }
318 368
319 void PerfProvider::ParseProtoIfValid( 369 void PerfProvider::ParseProtoIfValid(
320 scoped_ptr<WindowedIncognitoObserver> incognito_observer, 370 scoped_ptr<WindowedIncognitoObserver> incognito_observer,
321 scoped_ptr<SampledProfile> sampled_profile, 371 scoped_ptr<SampledProfile> sampled_profile,
322 const std::vector<uint8>& data) { 372 const std::vector<uint8>& data) {
323 DCHECK(CalledOnValidThread()); 373 DCHECK(CalledOnValidThread());
324 374
375 // Schedule another interval collection. This call makes sense regardless of
376 // whether or not the current collection was interval-triggered. If it had
377 // been another type of trigger event, the interval timer would have been
378 // halted, so it makes sense to reschedule a new interval collection.
379 ScheduleIntervalCollection();
380
325 if (incognito_observer->incognito_launched()) { 381 if (incognito_observer->incognito_launched()) {
326 AddToPerfHistogram(INCOGNITO_LAUNCHED); 382 AddToPerfHistogram(INCOGNITO_LAUNCHED);
327 return; 383 return;
328 } 384 }
329 385
330 PerfDataProto perf_data_proto; 386 PerfDataProto perf_data_proto;
331 if (!perf_data_proto.ParseFromArray(data.data(), data.size())) { 387 if (!perf_data_proto.ParseFromArray(data.data(), data.size())) {
332 AddToPerfHistogram(PROTOBUF_NOT_PARSED); 388 AddToPerfHistogram(PROTOBUF_NOT_PARSED);
333 return; 389 return;
334 } 390 }
(...skipping 11 matching lines...) Expand all
346 DCHECK(!login_time_.is_null()); 402 DCHECK(!login_time_.is_null());
347 collection_data. 403 collection_data.
348 set_ms_after_login((base::TimeTicks::Now() - login_time_) 404 set_ms_after_login((base::TimeTicks::Now() - login_time_)
349 .InMilliseconds()); 405 .InMilliseconds());
350 406
351 // Finally, store the perf data itself. 407 // Finally, store the perf data itself.
352 collection_data.mutable_perf_data()->Swap(&perf_data_proto); 408 collection_data.mutable_perf_data()->Swap(&perf_data_proto);
353 } 409 }
354 410
355 } // namespace metrics 411 } // 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