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

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: 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
22 PerfProvider::CollectionParams::CollectionParams(
Alexei Svitkine (slow) 2015/10/09 17:27:21 Nit: Move this below the anon namespace decl.
dhsharp 2015/10/09 18:29:48 Done.
23 base::TimeDelta collection_duration,
24 base::TimeDelta periodic_interval,
25 TriggerParams resume_from_suspend,
26 TriggerParams restore_session)
27 : collection_duration_(collection_duration.ToInternalValue()),
28 periodic_interval_(periodic_interval.ToInternalValue()),
29 resume_from_suspend_(resume_from_suspend),
30 restore_session_(restore_session) {
31 }
Alexei Svitkine (slow) 2015/10/09 17:27:21 Nit: Add an empty line below.
dhsharp 2015/10/09 18:29:48 Oops. Done.
32 PerfProvider::CollectionParams::TriggerParams::TriggerParams(
33 int64 sampling_factor,
34 base::TimeDelta max_collection_delay)
35 : sampling_factor_(sampling_factor),
36 max_collection_delay_(max_collection_delay.ToInternalValue()) {
37 }
38
39 const PerfProvider::CollectionParams PerfProvider::kDefaultParameters(
Alexei Svitkine (slow) 2015/10/09 17:27:21 I'd not make this a static member but instead just
dhsharp 2015/10/09 18:29:48 I had been thinking I needed access to it from tes
40 /*collection_duration*/ base::TimeDelta::FromSeconds(2),
41 /*periodic_interval*/ base::TimeDelta::FromHours(3),
42 /*resume_from_suspend*/ PerfProvider::CollectionParams::TriggerParams(
Alexei Svitkine (slow) 2015/10/09 17:27:21 Nit: I'd prefer the comments to be: /* resume_fro
dhsharp 2015/10/09 18:29:48 Done.
43 /*sampling_factor*/ 10,
44 /*max_collection_delay*/ base::TimeDelta::FromSeconds(5)),
45 /*restore_session*/ PerfProvider::CollectionParams::TriggerParams(
46 /*sampling_factor*/ 10,
47 /*max_collection_delay*/ base::TimeDelta::FromSeconds(10)));
48
20 namespace { 49 namespace {
21 50
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 51 // 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 52 // too much memory. If the size of cached protobufs exceeds this value, stop
31 // collecting further perf data. The current value is 4 MB. 53 // collecting further perf data. The current value is 4 MB.
32 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024; 54 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024;
33 55
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 56 // 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 57 // 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. 58 // much time between collections.
47 const int kMinIntervalBetweenSessionRestoreCollectionsMs = 30 * 1000; 59 const base::TimeDelta kMinIntervalBetweenSessionRestoreCollections =
48 60 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 61
59 // Enumeration representing success and various failure modes for collecting and 62 // Enumeration representing success and various failure modes for collecting and
60 // sending perf data. 63 // sending perf data.
61 enum GetPerfDataOutcome { 64 enum GetPerfDataOutcome {
62 SUCCESS, 65 SUCCESS,
63 NOT_READY_TO_UPLOAD, 66 NOT_READY_TO_UPLOAD,
64 NOT_READY_TO_COLLECT, 67 NOT_READY_TO_COLLECT,
65 INCOGNITO_ACTIVE, 68 INCOGNITO_ACTIVE,
66 INCOGNITO_LAUNCHED, 69 INCOGNITO_LAUNCHED,
67 PROTOBUF_NOT_PARSED, 70 PROTOBUF_NOT_PARSED,
(...skipping 10 matching lines...) Expand all
78 outcome, 81 outcome,
79 NUM_OUTCOMES); 82 NUM_OUTCOMES);
80 } 83 }
81 84
82 // Returns true if a normal user is logged in. Returns false otherwise (e.g. if 85 // 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). 86 // logged in as a guest or as a kiosk app).
84 bool IsNormalUserLoggedIn() { 87 bool IsNormalUserLoggedIn() {
85 return chromeos::LoginState::Get()->IsUserAuthenticated(); 88 return chromeos::LoginState::Get()->IsUserAuthenticated();
86 } 89 }
87 90
91 // Returns a random TimeDelta between zero and |max|.
92 base::TimeDelta RandomTimeDelta(base::TimeDelta max) {
93 return base::TimeDelta::FromMicroseconds(
94 base::RandGenerator(max.InMicroseconds()));
95 }
96
88 } // namespace 97 } // namespace
89 98
90 namespace metrics {
91
92 PerfProvider::PerfProvider() 99 PerfProvider::PerfProvider()
93 : login_observer_(this), 100 : collection_params_(kDefaultParameters),
94 next_profiling_interval_start_(base::TimeTicks::Now()), 101 login_observer_(this),
95 weak_factory_(this) { 102 next_profiling_interval_start_(base::TimeTicks::Now()),
103 weak_factory_(this) {
96 // Register the login observer with LoginState. 104 // Register the login observer with LoginState.
97 chromeos::LoginState::Get()->AddObserver(&login_observer_); 105 chromeos::LoginState::Get()->AddObserver(&login_observer_);
98 106
99 // Register as an observer of power manager events. 107 // Register as an observer of power manager events.
100 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 108 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
101 AddObserver(this); 109 AddObserver(this);
102 110
103 // Register as an observer of session restore. 111 // Register as an observer of session restore.
104 on_session_restored_callback_subscription_ = 112 on_session_restored_callback_subscription_ =
105 SessionRestore::RegisterOnSessionRestoredCallback( 113 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. 207 // canceled. Do not collect anything if that's the case.
200 if (sleep_duration == base::TimeDelta()) 208 if (sleep_duration == base::TimeDelta())
201 return; 209 return;
202 210
203 // Do not collect a profile unless logged in. The system behavior when closing 211 // 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 212 // 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. 213 // suspending. But it's good to enforce the rule here in case that changes.
206 if (!IsNormalUserLoggedIn()) 214 if (!IsNormalUserLoggedIn())
207 return; 215 return;
208 216
209 // Collect a profile only 1/|kResumeSamplingFactor| of the time, to avoid 217 // Collect a profile only 1/|sampling_factor| of the time, to avoid
210 // collecting too much data. 218 // collecting too much data.
211 if (base::RandGenerator(kResumeSamplingFactor) != 0) 219 const auto& resume_params = collection_params_.resume_from_suspend();
220 if (base::RandGenerator(resume_params.sampling_factor()) != 0)
212 return; 221 return;
213 222
214 // Override any existing profiling. 223 // Override any existing profiling.
215 if (timer_.IsRunning()) 224 if (timer_.IsRunning())
216 timer_.Stop(); 225 timer_.Stop();
217 226
218 // Randomly pick a delay before doing the collection. 227 // Randomly pick a delay before doing the collection.
219 base::TimeDelta collection_delay = 228 base::TimeDelta collection_delay = RandomTimeDelta(
220 base::TimeDelta::FromMilliseconds( 229 resume_params.max_collection_delay());
221 base::RandGenerator(kMaxResumeCollectionDelayMs));
222 timer_.Start(FROM_HERE, 230 timer_.Start(FROM_HERE,
223 collection_delay, 231 collection_delay,
224 base::Bind(&PerfProvider::CollectPerfDataAfterResume, 232 base::Bind(&PerfProvider::CollectPerfDataAfterResume,
225 weak_factory_.GetWeakPtr(), 233 weak_factory_.GetWeakPtr(),
226 sleep_duration, 234 sleep_duration,
227 collection_delay)); 235 collection_delay));
228 } 236 }
229 237
230 void PerfProvider::OnSessionRestoreDone(int num_tabs_restored) { 238 void PerfProvider::OnSessionRestoreDone(int num_tabs_restored) {
231 // Do not collect a profile unless logged in as a normal user. 239 // Do not collect a profile unless logged in as a normal user.
232 if (!IsNormalUserLoggedIn()) 240 if (!IsNormalUserLoggedIn())
233 return; 241 return;
234 242
235 // Collect a profile only 1/|kRestoreSessionSamplingFactor| of the time, to 243 // Collect a profile only 1/|sampling_factor| of the time, to
236 // avoid collecting too much data and potentially causing UI latency. 244 // avoid collecting too much data and potentially causing UI latency.
237 if (base::RandGenerator(kRestoreSessionSamplingFactor) != 0) 245 const auto& restore_params = collection_params_.restore_session();
246 if (base::RandGenerator(restore_params.sampling_factor()) != 0)
238 return; 247 return;
239 248
240 const base::TimeDelta min_interval = 249 const auto min_interval = kMinIntervalBetweenSessionRestoreCollections;
241 base::TimeDelta::FromMilliseconds(
242 kMinIntervalBetweenSessionRestoreCollectionsMs);
243 const base::TimeDelta time_since_last_collection = 250 const base::TimeDelta time_since_last_collection =
244 (base::TimeTicks::Now() - last_session_restore_collection_time_); 251 (base::TimeTicks::Now() - last_session_restore_collection_time_);
245 // Do not collect if there hasn't been enough elapsed time since the last 252 // Do not collect if there hasn't been enough elapsed time since the last
246 // collection. 253 // collection.
247 if (!last_session_restore_collection_time_.is_null() && 254 if (!last_session_restore_collection_time_.is_null() &&
248 time_since_last_collection < min_interval) { 255 time_since_last_collection < min_interval) {
249 return; 256 return;
250 } 257 }
251 258
252 // Stop any existing scheduled collection. 259 // Stop any existing scheduled collection.
253 if (timer_.IsRunning()) 260 if (timer_.IsRunning())
254 timer_.Stop(); 261 timer_.Stop();
255 262
256 // Randomly pick a delay before doing the collection. 263 // Randomly pick a delay before doing the collection.
257 base::TimeDelta collection_delay = 264 base::TimeDelta collection_delay = RandomTimeDelta(
258 base::TimeDelta::FromMilliseconds( 265 restore_params.max_collection_delay());
259 base::RandGenerator(kMaxRestoreSessionCollectionDelayMs));
260 timer_.Start( 266 timer_.Start(
261 FROM_HERE, 267 FROM_HERE,
262 collection_delay, 268 collection_delay,
263 base::Bind(&PerfProvider::CollectPerfDataAfterSessionRestore, 269 base::Bind(&PerfProvider::CollectPerfDataAfterSessionRestore,
264 weak_factory_.GetWeakPtr(), 270 weak_factory_.GetWeakPtr(),
265 collection_delay, 271 collection_delay,
266 num_tabs_restored)); 272 num_tabs_restored));
267 } 273 }
268 274
269 void PerfProvider::OnUserLoggedIn() { 275 void PerfProvider::OnUserLoggedIn() {
270 login_time_ = base::TimeTicks::Now(); 276 login_time_ = base::TimeTicks::Now();
271 ScheduleIntervalCollection(); 277 ScheduleIntervalCollection();
272 } 278 }
273 279
274 void PerfProvider::Deactivate() { 280 void PerfProvider::Deactivate() {
275 // Stop the timer, but leave |cached_perf_data_| intact. 281 // Stop the timer, but leave |cached_perf_data_| intact.
276 timer_.Stop(); 282 timer_.Stop();
277 } 283 }
278 284
279 void PerfProvider::ScheduleIntervalCollection() { 285 void PerfProvider::ScheduleIntervalCollection() {
280 DCHECK(CalledOnValidThread()); 286 DCHECK(CalledOnValidThread());
281 if (timer_.IsRunning()) 287 if (timer_.IsRunning())
282 return; 288 return;
283 289
284 // Pick a random time in the current interval. 290 // Pick a random time in the current interval.
285 base::TimeTicks scheduled_time = 291 base::TimeTicks scheduled_time =
286 next_profiling_interval_start_ + 292 next_profiling_interval_start_ +
287 base::TimeDelta::FromMilliseconds( 293 RandomTimeDelta(collection_params_.periodic_interval());
288 base::RandGenerator(kPerfProfilingIntervalMs));
289 294
290 // If the scheduled time has already passed in the time it took to make the 295 // If the scheduled time has already passed in the time it took to make the
291 // above calculations, trigger the collection event immediately. 296 // above calculations, trigger the collection event immediately.
292 base::TimeTicks now = base::TimeTicks::Now(); 297 base::TimeTicks now = base::TimeTicks::Now();
293 if (scheduled_time < now) 298 if (scheduled_time < now)
294 scheduled_time = now; 299 scheduled_time = now;
295 300
296 timer_.Start(FROM_HERE, scheduled_time - now, this, 301 timer_.Start(FROM_HERE, scheduled_time - now, this,
297 &PerfProvider::DoPeriodicCollection); 302 &PerfProvider::DoPeriodicCollection);
298 303
299 // Update the profiling interval tracker to the start of the next interval. 304 // Update the profiling interval tracker to the start of the next interval.
300 next_profiling_interval_start_ += 305 next_profiling_interval_start_ += collection_params_.periodic_interval();
301 base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs);
302 } 306 }
303 307
304 void PerfProvider::CollectIfNecessary( 308 void PerfProvider::CollectIfNecessary(
305 scoped_ptr<SampledProfile> sampled_profile) { 309 scoped_ptr<SampledProfile> sampled_profile) {
306 DCHECK(CalledOnValidThread()); 310 DCHECK(CalledOnValidThread());
307 311
308 // Schedule another interval collection. This call makes sense regardless of 312 // Schedule another interval collection. This call makes sense regardless of
309 // whether or not the current collection was interval-triggered. If it had 313 // 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 314 // been another type of trigger event, the interval timer would have been
311 // halted, so it makes sense to reschedule a new interval collection. 315 // halted, so it makes sense to reschedule a new interval collection.
(...skipping 16 matching lines...) Expand all
328 AddToPerfHistogram(INCOGNITO_ACTIVE); 332 AddToPerfHistogram(INCOGNITO_ACTIVE);
329 return; 333 return;
330 } 334 }
331 335
332 scoped_ptr<WindowedIncognitoObserver> incognito_observer( 336 scoped_ptr<WindowedIncognitoObserver> incognito_observer(
333 new WindowedIncognitoObserver); 337 new WindowedIncognitoObserver);
334 338
335 chromeos::DebugDaemonClient* client = 339 chromeos::DebugDaemonClient* client =
336 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); 340 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
337 341
338 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
339 kPerfCommandDurationDefaultSeconds);
340
341 client->GetPerfOutput( 342 client->GetPerfOutput(
342 collection_duration.InSeconds(), 343 collection_params_.collection_duration().InSeconds(),
343 base::Bind(&PerfProvider::ParseOutputProtoIfValid, 344 base::Bind(&PerfProvider::ParseOutputProtoIfValid,
344 weak_factory_.GetWeakPtr(), base::Passed(&incognito_observer), 345 weak_factory_.GetWeakPtr(), base::Passed(&incognito_observer),
345 base::Passed(&sampled_profile))); 346 base::Passed(&sampled_profile)));
346 } 347 }
347 348
348 void PerfProvider::DoPeriodicCollection() { 349 void PerfProvider::DoPeriodicCollection() {
349 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 350 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
350 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); 351 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
351 352
352 CollectIfNecessary(sampled_profile.Pass()); 353 CollectIfNecessary(sampled_profile.Pass());
(...skipping 18 matching lines...) Expand all
371 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 372 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
372 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); 373 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
373 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds()); 374 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds());
374 sampled_profile->set_num_tabs_restored(num_tabs_restored); 375 sampled_profile->set_num_tabs_restored(num_tabs_restored);
375 376
376 CollectIfNecessary(sampled_profile.Pass()); 377 CollectIfNecessary(sampled_profile.Pass());
377 last_session_restore_collection_time_ = base::TimeTicks::Now(); 378 last_session_restore_collection_time_ = base::TimeTicks::Now();
378 } 379 }
379 380
380 } // namespace metrics 381 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698