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

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

Issue 282093011: metrics: Use absolute interval-based perf collection (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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
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"
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/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/threading/sequenced_worker_pool.h" 15 #include "base/threading/sequenced_worker_pool.h"
16 #include "chrome/browser/metrics/perf_provider_chromeos.h" 16 #include "chrome/browser/metrics/perf_provider_chromeos.h"
17 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/browser.h" 18 #include "chrome/browser/ui/browser.h"
19 #include "chrome/browser/ui/browser_list.h" 19 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/browser/ui/browser_list_observer.h" 20 #include "chrome/browser/ui/browser_list_observer.h"
21 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/chrome_switches.h"
22 #include "chromeos/dbus/dbus_thread_manager.h" 22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "chromeos/dbus/debug_daemon_client.h" 23 #include "chromeos/dbus/debug_daemon_client.h"
24 24
25 namespace { 25 namespace {
26 26
27 // Default time in seconds between invocations of perf. 27 // Partition time since the epoch into successive intervals of this size. In
28 // This period is roughly 6.5 hours. 28 // each interval that hasn't passed, pick a random time to collect a profile.
29 // This is chosen to be relatively prime with the number of seconds in: 29 // This interval is four hours.
30 // - one minute (60) 30 const size_t kPerfProfilingIntervalSeconds = 14400;
tipp 2014/05/16 22:17:26 How'd you pick four hours? You should make some e
tipp 2014/05/16 22:17:26 It's clearer to write 4 * 60 * 60.
Simon Que 2014/05/20 20:47:35 Done.
Simon Que 2014/05/20 20:47:35 I'm not sure we have enough information to make th
31 // - one hour (3600)
32 // - one day (86400)
33 const size_t kPerfCommandIntervalDefaultSeconds = 23093;
34
35 // The first collection interval is different from the interval above. This is
36 // because we want to collect the first profile quickly after Chrome is started.
37 // If this period is too long, the user will log off and Chrome will be killed
38 // before it is triggered. The following 2 variables determine the upper and
39 // lower bound on the interval.
40 // The reason we do not always want to collect the initial profile after a fixed
41 // period is to not over-represent task X in the profile where task X always
42 // runs at a fixed period after start-up. By selecting a period randomly between
43 // a lower and upper bound, we will hopefully collect a more fair profile.
44 const size_t kPerfCommandStartIntervalLowerBoundMinutes = 10;
45
46 const size_t kPerfCommandStartIntervalUpperBoundMinutes = 20;
47 31
48 // Default time in seconds perf is run for. 32 // Default time in seconds perf is run for.
49 const size_t kPerfCommandDurationDefaultSeconds = 2; 33 const size_t kPerfCommandDurationDefaultSeconds = 2;
50 34
51 // Limit the total size of protobufs that can be cached, so they don't take up 35 // Limit the total size of protobufs that can be cached, so they don't take up
52 // too much memory. If the size of cached protobufs exceeds this value, stop 36 // too much memory. If the size of cached protobufs exceeds this value, stop
53 // collecting further perf data. The current value is 4 MB. 37 // collecting further perf data. The current value is 4 MB.
54 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024; 38 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024;
55 39
56 // Enumeration representing success and various failure modes for collecting and 40 // Enumeration representing success and various failure modes for collecting and
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 // chrome::BrowserListObserver implementation. 87 // chrome::BrowserListObserver implementation.
104 virtual void OnBrowserAdded(Browser* browser) OVERRIDE { 88 virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
105 if (browser->profile()->IsOffTheRecord()) 89 if (browser->profile()->IsOffTheRecord())
106 incognito_launched_ = true; 90 incognito_launched_ = true;
107 } 91 }
108 92
109 bool incognito_launched_; 93 bool incognito_launched_;
110 }; 94 };
111 95
112 PerfProvider::PerfProvider() 96 PerfProvider::PerfProvider()
113 : weak_factory_(this) { 97 : weak_factory_(this),
Ilya Sherman 2014/05/16 21:48:57 The weak pointer factory should always be the last
Simon Que 2014/05/17 03:25:07 Done.
Simon Que 2014/05/19 22:45:01 Done.
114 size_t collection_interval_minutes = base::RandInt( 98 login_time_(base::Time::Now()) {
115 kPerfCommandStartIntervalLowerBoundMinutes, 99 ScheduleCollection();
116 kPerfCommandStartIntervalUpperBoundMinutes);
117 ScheduleCollection(base::TimeDelta::FromMinutes(collection_interval_minutes));
118 } 100 }
119 101
120 PerfProvider::~PerfProvider() {} 102 PerfProvider::~PerfProvider() {}
121 103
122 bool PerfProvider::GetPerfData(std::vector<PerfDataProto>* perf_data) { 104 bool PerfProvider::GetPerfData(std::vector<SampledProfile>* perf_data) {
123 DCHECK(CalledOnValidThread()); 105 DCHECK(CalledOnValidThread());
124 if (cached_perf_data_.empty()) { 106 if (cached_perf_data_.empty()) {
125 AddToPerfHistogram(NOT_READY_TO_UPLOAD); 107 AddToPerfHistogram(NOT_READY_TO_UPLOAD);
126 return false; 108 return false;
127 } 109 }
128 110
129 perf_data->swap(cached_perf_data_); 111 perf_data->swap(cached_perf_data_);
130 cached_perf_data_.clear(); 112 cached_perf_data_.clear();
131 113
132 AddToPerfHistogram(SUCCESS); 114 AddToPerfHistogram(SUCCESS);
133 return true; 115 return true;
134 } 116 }
135 117
136 void PerfProvider::ScheduleCollection(const base::TimeDelta& interval) { 118 void PerfProvider::ScheduleCollection() {
137 DCHECK(CalledOnValidThread()); 119 DCHECK(CalledOnValidThread());
138 if (timer_.IsRunning()) 120 if (timer_.IsRunning())
139 return; 121 return;
140 122
123 // Determine the start of the current interval, which is a multiple of
124 // |kPerfProfilingIntervalSeconds| since the epoch.
125 base::Time now = base::Time::Now();
126 base::Time epoch = base::Time::UnixEpoch();
127 int64 seconds_since_epoch = (now - epoch).InSeconds();
tipp 2014/05/17 04:18:29 How about milliseconds everywhere instead of secon
Simon Que 2014/05/19 18:37:12 Will do.
128 int64 interval_start_time_s = seconds_since_epoch -
129 (seconds_since_epoch % kPerfProfilingIntervalSeconds);
130
131 // Pick a random time in the current interval. If it has already passed, pick
132 // the same time in the next interval.
Ilya Sherman 2014/05/16 21:48:57 So, the next interval might have two random times
Simon Que 2014/05/19 18:37:12 Yes, using the time of login / initialization woul
133 int64 scheduled_time_s = interval_start_time_s +
134 base::RandGenerator(kPerfProfilingIntervalSeconds);
tipp 2014/05/16 22:17:26 You want repeated calls to ScheduleCollection to b
Simon Que 2014/05/17 03:46:27 I'm not sure what your first sentence means. Shoul
tipp 2014/05/17 04:18:29 You want it to be deterministically random. For e
Simon Que 2014/05/19 22:45:01 Why can't we seed the random generator using the t
135 if (scheduled_time_s < seconds_since_epoch) {
136 scheduled_time_s += kPerfProfilingIntervalSeconds;
137 }
138
139 base::TimeDelta interval =
140 base::TimeDelta::FromSeconds(scheduled_time_s - seconds_since_epoch);
141 timer_.Start(FROM_HERE, interval, this, 141 timer_.Start(FROM_HERE, interval, this,
142 &PerfProvider::CollectIfNecessaryAndReschedule); 142 &PerfProvider::CollectIfNecessaryAndReschedule);
143 } 143 }
144 144
145 void PerfProvider::CollectIfNecessary() { 145 void PerfProvider::CollectIfNecessary() {
146 DCHECK(CalledOnValidThread()); 146 DCHECK(CalledOnValidThread());
147 147
148 // Do not collect further data if we've already collected a substantial amount 148 // Do not collect further data if we've already collected a substantial amount
149 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|. 149 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|.
150 size_t cached_perf_data_size = 0; 150 size_t cached_perf_data_size = 0;
(...skipping 22 matching lines...) Expand all
173 kPerfCommandDurationDefaultSeconds); 173 kPerfCommandDurationDefaultSeconds);
174 174
175 client->GetPerfData(collection_duration.InSeconds(), 175 client->GetPerfData(collection_duration.InSeconds(),
176 base::Bind(&PerfProvider::ParseProtoIfValid, 176 base::Bind(&PerfProvider::ParseProtoIfValid,
177 weak_factory_.GetWeakPtr(), 177 weak_factory_.GetWeakPtr(),
178 base::Passed(&incognito_observer))); 178 base::Passed(&incognito_observer)));
179 } 179 }
180 180
181 void PerfProvider::CollectIfNecessaryAndReschedule() { 181 void PerfProvider::CollectIfNecessaryAndReschedule() {
182 CollectIfNecessary(); 182 CollectIfNecessary();
183 ScheduleCollection( 183 ScheduleCollection();
184 base::TimeDelta::FromSeconds(kPerfCommandIntervalDefaultSeconds));
185 } 184 }
186 185
187 void PerfProvider::ParseProtoIfValid( 186 void PerfProvider::ParseProtoIfValid(
188 scoped_ptr<WindowedIncognitoObserver> incognito_observer, 187 scoped_ptr<WindowedIncognitoObserver> incognito_observer,
189 const std::vector<uint8>& data) { 188 const std::vector<uint8>& data) {
190 DCHECK(CalledOnValidThread()); 189 DCHECK(CalledOnValidThread());
191 190
192 if (incognito_observer->incognito_launched()) { 191 if (incognito_observer->incognito_launched()) {
193 AddToPerfHistogram(INCOGNITO_LAUNCHED); 192 AddToPerfHistogram(INCOGNITO_LAUNCHED);
194 return; 193 return;
195 } 194 }
196 195
197 PerfDataProto perf_data_proto; 196 PerfDataProto perf_data_proto;
198 if (!perf_data_proto.ParseFromArray(data.data(), data.size())) { 197 if (!perf_data_proto.ParseFromArray(data.data(), data.size())) {
199 AddToPerfHistogram(PROTOBUF_NOT_PARSED); 198 AddToPerfHistogram(PROTOBUF_NOT_PARSED);
200 return; 199 return;
201 } 200 }
202 201
203 // Append a new PerfDataProto to the |cached_perf_data_| vector and swap in 202 // Populate a profile collection protobuf with the collected perf data and
204 // the contents. 203 // extra metadata.
205 cached_perf_data_.resize(cached_perf_data_.size() + 1); 204 cached_perf_data_.resize(cached_perf_data_.size() + 1);
206 cached_perf_data_.back().Swap(&perf_data_proto); 205 SampledProfile& collection_data = cached_perf_data_.back();
206 collection_data.set_trigger_event(SampledProfile::PERIODIC_COLLECTION);
207 collection_data.set_ms_after_boot(perf_data_proto.timestamp_sec());
208 collection_data.
209 set_ms_after_login((base::Time::Now() - login_time_).InSeconds());
Ilya Sherman 2014/05/16 21:48:57 The field names for the time fields claim the unit
Simon Que 2014/05/17 03:25:07 Done.
210 *collection_data.mutable_perf_data() = perf_data_proto;
207 } 211 }
208 212
209 } // namespace metrics 213 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698