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

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

Issue 1399703002: PerfProvider: Restructure collection parameters into a struct (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Address comments on PS1 Created 5 years, 2 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
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 "chrome/browser/metrics/perf/perf_provider_chromeos.h" 5 #include "chrome/browser/metrics/perf/perf_provider_chromeos.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/rand_util.h" 13 #include "base/rand_util.h"
14 #include "base/threading/sequenced_worker_pool.h" 14 #include "base/threading/sequenced_worker_pool.h"
15 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h" 15 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
16 #include "chrome/browser/ui/browser_list.h" 16 #include "chrome/browser/ui/browser_list.h"
17 #include "chromeos/dbus/dbus_thread_manager.h" 17 #include "chromeos/dbus/dbus_thread_manager.h"
18 #include "chromeos/dbus/debug_daemon_client.h" 18 #include "chromeos/dbus/debug_daemon_client.h"
19 19
20 namespace metrics {
21
20 namespace { 22 namespace {
21 23
22 // Partition time since login into successive intervals of this size. In each
23 // interval, pick a random time to collect a profile.
24 const size_t kPerfProfilingIntervalMs = 3 * 60 * 60 * 1000;
25
26 // Default time in seconds perf is run for.
27 const size_t kPerfCommandDurationDefaultSeconds = 2;
28
29 // Limit the total size of protobufs that can be cached, so they don't take up 24 // Limit the total size of protobufs that can be cached, so they don't take up
30 // too much memory. If the size of cached protobufs exceeds this value, stop 25 // too much memory. If the size of cached protobufs exceeds this value, stop
31 // collecting further perf data. The current value is 4 MB. 26 // collecting further perf data. The current value is 4 MB.
32 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024; 27 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024;
33 28
34 // There may be too many suspends to collect a profile each time there is a
35 // resume. To limit the number of profiles, collect one for 1 in 10 resumes.
36 // Adjust this number as needed.
37 const int kResumeSamplingFactor = 10;
38
39 // There may be too many session restores to collect a profile each time. Limit
40 // the collection rate by collecting one per 10 restores. Adjust this number as
41 // needed.
42 const int kRestoreSessionSamplingFactor = 10;
43
44 // This is used to space out session restore collections in the face of several 29 // This is used to space out session restore collections in the face of several
45 // notifications in a short period of time. There should be no less than this 30 // notifications in a short period of time. There should be no less than this
46 // much time between collections. The current value is 30 seconds. 31 // much time between collections.
47 const int kMinIntervalBetweenSessionRestoreCollectionsMs = 30 * 1000; 32 const base::TimeDelta kMinIntervalBetweenSessionRestoreCollections =
Alexei Svitkine (slow) 2015/10/09 19:24:32 I'm not sure this is ok to do - I think this gener
dhsharp 2015/10/09 21:18:34 You're right. This is left over from when I though
48 33 base::TimeDelta::FromSeconds(30);
49 // If collecting after a resume, add a random delay before collecting. The delay
50 // should be randomly selected between 0 and this value. Currently the value is
51 // equal to 5 seconds.
52 const int kMaxResumeCollectionDelayMs = 5 * 1000;
53
54 // If collecting after a session restore, add a random delay before collecting.
55 // The delay should be randomly selected between 0 and this value. Currently the
56 // value is equal to 10 seconds.
57 const int kMaxRestoreSessionCollectionDelayMs = 10 * 1000;
58 34
59 // Enumeration representing success and various failure modes for collecting and 35 // Enumeration representing success and various failure modes for collecting and
60 // sending perf data. 36 // sending perf data.
61 enum GetPerfDataOutcome { 37 enum GetPerfDataOutcome {
62 SUCCESS, 38 SUCCESS,
63 NOT_READY_TO_UPLOAD, 39 NOT_READY_TO_UPLOAD,
64 NOT_READY_TO_COLLECT, 40 NOT_READY_TO_COLLECT,
65 INCOGNITO_ACTIVE, 41 INCOGNITO_ACTIVE,
66 INCOGNITO_LAUNCHED, 42 INCOGNITO_LAUNCHED,
67 PROTOBUF_NOT_PARSED, 43 PROTOBUF_NOT_PARSED,
(...skipping 10 matching lines...) Expand all
78 outcome, 54 outcome,
79 NUM_OUTCOMES); 55 NUM_OUTCOMES);
80 } 56 }
81 57
82 // Returns true if a normal user is logged in. Returns false otherwise (e.g. if 58 // Returns true if a normal user is logged in. Returns false otherwise (e.g. if
83 // logged in as a guest or as a kiosk app). 59 // logged in as a guest or as a kiosk app).
84 bool IsNormalUserLoggedIn() { 60 bool IsNormalUserLoggedIn() {
85 return chromeos::LoginState::Get()->IsUserAuthenticated(); 61 return chromeos::LoginState::Get()->IsUserAuthenticated();
86 } 62 }
87 63
64 // Returns a random TimeDelta between zero and |max|.
65 base::TimeDelta RandomTimeDelta(base::TimeDelta max) {
66 return base::TimeDelta::FromMicroseconds(
67 base::RandGenerator(max.InMicroseconds()));
68 }
69
88 } // namespace 70 } // namespace
89 71
90 namespace metrics { 72 PerfProvider::CollectionParams::CollectionParams(
73 base::TimeDelta collection_duration,
74 base::TimeDelta periodic_interval,
75 TriggerParams resume_from_suspend,
76 TriggerParams restore_session)
77 : collection_duration_(collection_duration.ToInternalValue()),
78 periodic_interval_(periodic_interval.ToInternalValue()),
79 resume_from_suspend_(resume_from_suspend),
80 restore_session_(restore_session) {
81 }
82
83 PerfProvider::CollectionParams::TriggerParams::TriggerParams(
84 int64 sampling_factor,
85 base::TimeDelta max_collection_delay)
86 : sampling_factor_(sampling_factor),
87 max_collection_delay_(max_collection_delay.ToInternalValue()) {
88 }
89
90 const PerfProvider::CollectionParams kDefaultParameters(
Alexei Svitkine (slow) 2015/10/09 19:24:32 This should be in the anon namespace above.
dhsharp 2015/10/09 21:18:34 This actually doesn't compile (did I forget to try
91 /* collection_duration = */ base::TimeDelta::FromSeconds(2),
92 /* periodic_interval = */ base::TimeDelta::FromHours(3),
93 /* resume_from_suspend = */ PerfProvider::CollectionParams::TriggerParams(
94 /* sampling_factor = */ 10,
95 /* max_collection_delay = */ base::TimeDelta::FromSeconds(5)),
96 /* restore_session = */ PerfProvider::CollectionParams::TriggerParams(
97 /* sampling_factor = */ 10,
98 /* max_collection_delay = */ base::TimeDelta::FromSeconds(10)));
91 99
92 PerfProvider::PerfProvider() 100 PerfProvider::PerfProvider()
93 : login_observer_(this), 101 : collection_params_(kDefaultParameters),
94 next_profiling_interval_start_(base::TimeTicks::Now()), 102 login_observer_(this),
95 weak_factory_(this) { 103 next_profiling_interval_start_(base::TimeTicks::Now()),
104 weak_factory_(this) {
96 // Register the login observer with LoginState. 105 // Register the login observer with LoginState.
97 chromeos::LoginState::Get()->AddObserver(&login_observer_); 106 chromeos::LoginState::Get()->AddObserver(&login_observer_);
98 107
99 // Register as an observer of power manager events. 108 // Register as an observer of power manager events.
100 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 109 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
101 AddObserver(this); 110 AddObserver(this);
102 111
103 // Register as an observer of session restore. 112 // Register as an observer of session restore.
104 on_session_restored_callback_subscription_ = 113 on_session_restored_callback_subscription_ =
105 SessionRestore::RegisterOnSessionRestoredCallback( 114 SessionRestore::RegisterOnSessionRestoredCallback(
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 // canceled. Do not collect anything if that's the case. 208 // canceled. Do not collect anything if that's the case.
200 if (sleep_duration == base::TimeDelta()) 209 if (sleep_duration == base::TimeDelta())
201 return; 210 return;
202 211
203 // Do not collect a profile unless logged in. The system behavior when closing 212 // Do not collect a profile unless logged in. The system behavior when closing
204 // the lid or idling when not logged in is currently to shut down instead of 213 // the lid or idling when not logged in is currently to shut down instead of
205 // suspending. But it's good to enforce the rule here in case that changes. 214 // suspending. But it's good to enforce the rule here in case that changes.
206 if (!IsNormalUserLoggedIn()) 215 if (!IsNormalUserLoggedIn())
207 return; 216 return;
208 217
209 // Collect a profile only 1/|kResumeSamplingFactor| of the time, to avoid 218 // Collect a profile only 1/|sampling_factor| of the time, to avoid
210 // collecting too much data. 219 // collecting too much data.
211 if (base::RandGenerator(kResumeSamplingFactor) != 0) 220 const auto& resume_params = collection_params_.resume_from_suspend();
221 if (base::RandGenerator(resume_params.sampling_factor()) != 0)
212 return; 222 return;
213 223
214 // Override any existing profiling. 224 // Override any existing profiling.
215 if (timer_.IsRunning()) 225 if (timer_.IsRunning())
216 timer_.Stop(); 226 timer_.Stop();
217 227
218 // Randomly pick a delay before doing the collection. 228 // Randomly pick a delay before doing the collection.
219 base::TimeDelta collection_delay = 229 base::TimeDelta collection_delay = RandomTimeDelta(
220 base::TimeDelta::FromMilliseconds( 230 resume_params.max_collection_delay());
221 base::RandGenerator(kMaxResumeCollectionDelayMs));
222 timer_.Start(FROM_HERE, 231 timer_.Start(FROM_HERE,
223 collection_delay, 232 collection_delay,
224 base::Bind(&PerfProvider::CollectPerfDataAfterResume, 233 base::Bind(&PerfProvider::CollectPerfDataAfterResume,
225 weak_factory_.GetWeakPtr(), 234 weak_factory_.GetWeakPtr(),
226 sleep_duration, 235 sleep_duration,
227 collection_delay)); 236 collection_delay));
228 } 237 }
229 238
230 void PerfProvider::OnSessionRestoreDone(int num_tabs_restored) { 239 void PerfProvider::OnSessionRestoreDone(int num_tabs_restored) {
231 // Do not collect a profile unless logged in as a normal user. 240 // Do not collect a profile unless logged in as a normal user.
232 if (!IsNormalUserLoggedIn()) 241 if (!IsNormalUserLoggedIn())
233 return; 242 return;
234 243
235 // Collect a profile only 1/|kRestoreSessionSamplingFactor| of the time, to 244 // Collect a profile only 1/|sampling_factor| of the time, to
236 // avoid collecting too much data and potentially causing UI latency. 245 // avoid collecting too much data and potentially causing UI latency.
237 if (base::RandGenerator(kRestoreSessionSamplingFactor) != 0) 246 const auto& restore_params = collection_params_.restore_session();
247 if (base::RandGenerator(restore_params.sampling_factor()) != 0)
238 return; 248 return;
239 249
240 const base::TimeDelta min_interval = 250 const auto min_interval = kMinIntervalBetweenSessionRestoreCollections;
241 base::TimeDelta::FromMilliseconds(
242 kMinIntervalBetweenSessionRestoreCollectionsMs);
243 const base::TimeDelta time_since_last_collection = 251 const base::TimeDelta time_since_last_collection =
244 (base::TimeTicks::Now() - last_session_restore_collection_time_); 252 (base::TimeTicks::Now() - last_session_restore_collection_time_);
245 // Do not collect if there hasn't been enough elapsed time since the last 253 // Do not collect if there hasn't been enough elapsed time since the last
246 // collection. 254 // collection.
247 if (!last_session_restore_collection_time_.is_null() && 255 if (!last_session_restore_collection_time_.is_null() &&
248 time_since_last_collection < min_interval) { 256 time_since_last_collection < min_interval) {
249 return; 257 return;
250 } 258 }
251 259
252 // Stop any existing scheduled collection. 260 // Stop any existing scheduled collection.
253 if (timer_.IsRunning()) 261 if (timer_.IsRunning())
254 timer_.Stop(); 262 timer_.Stop();
255 263
256 // Randomly pick a delay before doing the collection. 264 // Randomly pick a delay before doing the collection.
257 base::TimeDelta collection_delay = 265 base::TimeDelta collection_delay = RandomTimeDelta(
258 base::TimeDelta::FromMilliseconds( 266 restore_params.max_collection_delay());
259 base::RandGenerator(kMaxRestoreSessionCollectionDelayMs));
260 timer_.Start( 267 timer_.Start(
261 FROM_HERE, 268 FROM_HERE,
262 collection_delay, 269 collection_delay,
263 base::Bind(&PerfProvider::CollectPerfDataAfterSessionRestore, 270 base::Bind(&PerfProvider::CollectPerfDataAfterSessionRestore,
264 weak_factory_.GetWeakPtr(), 271 weak_factory_.GetWeakPtr(),
265 collection_delay, 272 collection_delay,
266 num_tabs_restored)); 273 num_tabs_restored));
267 } 274 }
268 275
269 void PerfProvider::OnUserLoggedIn() { 276 void PerfProvider::OnUserLoggedIn() {
270 login_time_ = base::TimeTicks::Now(); 277 login_time_ = base::TimeTicks::Now();
271 ScheduleIntervalCollection(); 278 ScheduleIntervalCollection();
272 } 279 }
273 280
274 void PerfProvider::Deactivate() { 281 void PerfProvider::Deactivate() {
275 // Stop the timer, but leave |cached_perf_data_| intact. 282 // Stop the timer, but leave |cached_perf_data_| intact.
276 timer_.Stop(); 283 timer_.Stop();
277 } 284 }
278 285
279 void PerfProvider::ScheduleIntervalCollection() { 286 void PerfProvider::ScheduleIntervalCollection() {
280 DCHECK(CalledOnValidThread()); 287 DCHECK(CalledOnValidThread());
281 if (timer_.IsRunning()) 288 if (timer_.IsRunning())
282 return; 289 return;
283 290
284 // Pick a random time in the current interval. 291 // Pick a random time in the current interval.
285 base::TimeTicks scheduled_time = 292 base::TimeTicks scheduled_time =
286 next_profiling_interval_start_ + 293 next_profiling_interval_start_ +
287 base::TimeDelta::FromMilliseconds( 294 RandomTimeDelta(collection_params_.periodic_interval());
288 base::RandGenerator(kPerfProfilingIntervalMs));
289 295
290 // If the scheduled time has already passed in the time it took to make the 296 // If the scheduled time has already passed in the time it took to make the
291 // above calculations, trigger the collection event immediately. 297 // above calculations, trigger the collection event immediately.
292 base::TimeTicks now = base::TimeTicks::Now(); 298 base::TimeTicks now = base::TimeTicks::Now();
293 if (scheduled_time < now) 299 if (scheduled_time < now)
294 scheduled_time = now; 300 scheduled_time = now;
295 301
296 timer_.Start(FROM_HERE, scheduled_time - now, this, 302 timer_.Start(FROM_HERE, scheduled_time - now, this,
297 &PerfProvider::DoPeriodicCollection); 303 &PerfProvider::DoPeriodicCollection);
298 304
299 // Update the profiling interval tracker to the start of the next interval. 305 // Update the profiling interval tracker to the start of the next interval.
300 next_profiling_interval_start_ += 306 next_profiling_interval_start_ += collection_params_.periodic_interval();
301 base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs);
302 } 307 }
303 308
304 void PerfProvider::CollectIfNecessary( 309 void PerfProvider::CollectIfNecessary(
305 scoped_ptr<SampledProfile> sampled_profile) { 310 scoped_ptr<SampledProfile> sampled_profile) {
306 DCHECK(CalledOnValidThread()); 311 DCHECK(CalledOnValidThread());
307 312
308 // Schedule another interval collection. This call makes sense regardless of 313 // Schedule another interval collection. This call makes sense regardless of
309 // whether or not the current collection was interval-triggered. If it had 314 // whether or not the current collection was interval-triggered. If it had
310 // been another type of trigger event, the interval timer would have been 315 // been another type of trigger event, the interval timer would have been
311 // halted, so it makes sense to reschedule a new interval collection. 316 // halted, so it makes sense to reschedule a new interval collection.
(...skipping 16 matching lines...) Expand all
328 AddToPerfHistogram(INCOGNITO_ACTIVE); 333 AddToPerfHistogram(INCOGNITO_ACTIVE);
329 return; 334 return;
330 } 335 }
331 336
332 scoped_ptr<WindowedIncognitoObserver> incognito_observer( 337 scoped_ptr<WindowedIncognitoObserver> incognito_observer(
333 new WindowedIncognitoObserver); 338 new WindowedIncognitoObserver);
334 339
335 chromeos::DebugDaemonClient* client = 340 chromeos::DebugDaemonClient* client =
336 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); 341 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
337 342
338 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
339 kPerfCommandDurationDefaultSeconds);
340
341 client->GetPerfOutput( 343 client->GetPerfOutput(
342 collection_duration.InSeconds(), 344 collection_params_.collection_duration().InSeconds(),
343 base::Bind(&PerfProvider::ParseOutputProtoIfValid, 345 base::Bind(&PerfProvider::ParseOutputProtoIfValid,
344 weak_factory_.GetWeakPtr(), base::Passed(&incognito_observer), 346 weak_factory_.GetWeakPtr(), base::Passed(&incognito_observer),
345 base::Passed(&sampled_profile))); 347 base::Passed(&sampled_profile)));
346 } 348 }
347 349
348 void PerfProvider::DoPeriodicCollection() { 350 void PerfProvider::DoPeriodicCollection() {
349 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 351 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
350 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); 352 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
351 353
352 CollectIfNecessary(sampled_profile.Pass()); 354 CollectIfNecessary(sampled_profile.Pass());
(...skipping 18 matching lines...) Expand all
371 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 373 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
372 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); 374 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
373 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds()); 375 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds());
374 sampled_profile->set_num_tabs_restored(num_tabs_restored); 376 sampled_profile->set_num_tabs_restored(num_tabs_restored);
375 377
376 CollectIfNecessary(sampled_profile.Pass()); 378 CollectIfNecessary(sampled_profile.Pass());
377 last_session_restore_collection_time_ = base::TimeTicks::Now(); 379 last_session_restore_collection_time_ = base::TimeTicks::Now();
378 } 380 }
379 381
380 } // namespace metrics 382 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698