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

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: Addressed nits Created 6 years, 6 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"
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 login into successive intervals of this size. In each
28 // This period is roughly 6.5 hours. 28 // interval, 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 twenty-four hours.
30 // - one minute (60) 30 const size_t kPerfProfilingIntervalMs = 24 * 60 * 60 * 1000;
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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 virtual void OnBrowserAdded(Browser* browser) OVERRIDE { 96 virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
113 if (browser->profile()->IsOffTheRecord()) 97 if (browser->profile()->IsOffTheRecord())
114 incognito_launched_ = true; 98 incognito_launched_ = true;
115 } 99 }
116 100
117 bool incognito_launched_; 101 bool incognito_launched_;
118 }; 102 };
119 103
120 PerfProvider::PerfProvider() 104 PerfProvider::PerfProvider()
121 : login_observer_(this), 105 : login_observer_(this),
106 next_profiling_interval_start_(base::TimeTicks::Now()),
122 weak_factory_(this) { 107 weak_factory_(this) {
123 // Register the login observer with LoginState. 108 // Register the login observer with LoginState.
124 chromeos::LoginState::Get()->AddObserver(&login_observer_); 109 chromeos::LoginState::Get()->AddObserver(&login_observer_);
125 110
126 // Check the login state. At the time of writing, this class is instantiated 111 // Check the login state. At the time of writing, this class is instantiated
127 // before login. A subsequent login would activate the profiling. However, 112 // before login. A subsequent login would activate the profiling. However,
128 // that behavior may change in the future so that the user is already logged 113 // that behavior may change in the future so that the user is already logged
129 // when this class is instantiated. By calling LoggedInStateChanged() here, 114 // when this class is instantiated. By calling LoggedInStateChanged() here,
130 // PerfProvider will recognize that the system is already logged in. 115 // PerfProvider will recognize that the system is already logged in.
131 login_observer_.LoggedInStateChanged(); 116 login_observer_.LoggedInStateChanged();
132 } 117 }
133 118
134 PerfProvider::~PerfProvider() { 119 PerfProvider::~PerfProvider() {
135 chromeos::LoginState::Get()->RemoveObserver(&login_observer_); 120 chromeos::LoginState::Get()->RemoveObserver(&login_observer_);
136 } 121 }
137 122
138 bool PerfProvider::GetPerfData(std::vector<PerfDataProto>* perf_data) { 123 bool PerfProvider::GetSampledProfiles(
124 std::vector<SampledProfile>* sampled_profiles) {
139 DCHECK(CalledOnValidThread()); 125 DCHECK(CalledOnValidThread());
140 if (cached_perf_data_.empty()) { 126 if (cached_perf_data_.empty()) {
141 AddToPerfHistogram(NOT_READY_TO_UPLOAD); 127 AddToPerfHistogram(NOT_READY_TO_UPLOAD);
142 return false; 128 return false;
143 } 129 }
144 130
145 perf_data->swap(cached_perf_data_); 131 sampled_profiles->swap(cached_perf_data_);
146 cached_perf_data_.clear(); 132 cached_perf_data_.clear();
147 133
148 AddToPerfHistogram(SUCCESS); 134 AddToPerfHistogram(SUCCESS);
149 return true; 135 return true;
150 } 136 }
151 137
152 PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider) 138 PerfProvider::LoginObserver::LoginObserver(PerfProvider* perf_provider)
153 : perf_provider_(perf_provider) {} 139 : perf_provider_(perf_provider) {}
154 140
155 void PerfProvider::LoginObserver::LoggedInStateChanged() { 141 void PerfProvider::LoginObserver::LoggedInStateChanged() {
156 if (IsNormalUserLoggedIn()) 142 if (IsNormalUserLoggedIn())
157 perf_provider_->Activate(); 143 perf_provider_->OnUserLoggedIn();
158 else 144 else
159 perf_provider_->Deactivate(); 145 perf_provider_->Deactivate();
160 } 146 }
161 147
162 void PerfProvider::Activate() { 148 void PerfProvider::OnUserLoggedIn() {
163 size_t collection_interval_minutes = base::RandInt( 149 login_time_ = base::TimeTicks::Now();
164 kPerfCommandStartIntervalLowerBoundMinutes, 150 ScheduleCollection();
165 kPerfCommandStartIntervalUpperBoundMinutes);
166 ScheduleCollection(base::TimeDelta::FromMinutes(collection_interval_minutes));
167 } 151 }
168 152
169 void PerfProvider::Deactivate() { 153 void PerfProvider::Deactivate() {
170 // Stop the timer, but leave |cached_perf_data_| intact. 154 // Stop the timer, but leave |cached_perf_data_| intact.
171 timer_.Stop(); 155 timer_.Stop();
172 } 156 }
173 157
174 void PerfProvider::ScheduleCollection(const base::TimeDelta& interval) { 158 void PerfProvider::ScheduleCollection() {
175 DCHECK(CalledOnValidThread()); 159 DCHECK(CalledOnValidThread());
176 if (timer_.IsRunning()) 160 if (timer_.IsRunning())
177 return; 161 return;
178 162
179 timer_.Start(FROM_HERE, interval, this, 163 // Pick a random time in the current interval.
180 &PerfProvider::CollectIfNecessaryAndReschedule); 164 base::TimeTicks scheduled_time =
165 next_profiling_interval_start_ +
166 base::TimeDelta::FromMilliseconds(
167 base::RandGenerator(kPerfProfilingIntervalMs));
168
169 // If the scheduled time has already passed in the time it took to make the
170 // above calculations, trigger the collection event immediately.
171 base::TimeTicks now = base::TimeTicks::Now();
172 if (scheduled_time < now)
173 scheduled_time = now;
174
175 timer_.Start(FROM_HERE, scheduled_time - now, this,
176 &PerfProvider::DoPeriodicCollection);
177
178 // Update the profiling interval tracker to the start of the next interval.
179 next_profiling_interval_start_ +=
180 base::TimeDelta::FromMilliseconds(kPerfProfilingIntervalMs);
181 } 181 }
182 182
183 void PerfProvider::CollectIfNecessary() { 183 void PerfProvider::CollectIfNecessary(
184 SampledProfile::TriggerEvent trigger_event) {
184 DCHECK(CalledOnValidThread()); 185 DCHECK(CalledOnValidThread());
185 186
186 // Do not collect further data if we've already collected a substantial amount 187 // Do not collect further data if we've already collected a substantial amount
187 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|. 188 // of data, as indicated by |kCachedPerfDataProtobufSizeThreshold|.
188 size_t cached_perf_data_size = 0; 189 size_t cached_perf_data_size = 0;
189 for (size_t i = 0; i < cached_perf_data_.size(); ++i) { 190 for (size_t i = 0; i < cached_perf_data_.size(); ++i) {
190 cached_perf_data_size += cached_perf_data_[i].ByteSize(); 191 cached_perf_data_size += cached_perf_data_[i].ByteSize();
191 } 192 }
192 if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) { 193 if (cached_perf_data_size >= kCachedPerfDataProtobufSizeThreshold) {
193 AddToPerfHistogram(NOT_READY_TO_COLLECT); 194 AddToPerfHistogram(NOT_READY_TO_COLLECT);
(...skipping 12 matching lines...) Expand all
206 207
207 chromeos::DebugDaemonClient* client = 208 chromeos::DebugDaemonClient* client =
208 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); 209 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
209 210
210 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds( 211 base::TimeDelta collection_duration = base::TimeDelta::FromSeconds(
211 kPerfCommandDurationDefaultSeconds); 212 kPerfCommandDurationDefaultSeconds);
212 213
213 client->GetPerfData(collection_duration.InSeconds(), 214 client->GetPerfData(collection_duration.InSeconds(),
214 base::Bind(&PerfProvider::ParseProtoIfValid, 215 base::Bind(&PerfProvider::ParseProtoIfValid,
215 weak_factory_.GetWeakPtr(), 216 weak_factory_.GetWeakPtr(),
216 base::Passed(&incognito_observer))); 217 base::Passed(&incognito_observer),
218 trigger_event));
217 } 219 }
218 220
219 void PerfProvider::CollectIfNecessaryAndReschedule() { 221 void PerfProvider::DoPeriodicCollection() {
220 CollectIfNecessary(); 222 CollectIfNecessary(SampledProfile::PERIODIC_COLLECTION);
221 ScheduleCollection( 223 ScheduleCollection();
222 base::TimeDelta::FromSeconds(kPerfCommandIntervalDefaultSeconds));
223 } 224 }
224 225
225 void PerfProvider::ParseProtoIfValid( 226 void PerfProvider::ParseProtoIfValid(
226 scoped_ptr<WindowedIncognitoObserver> incognito_observer, 227 scoped_ptr<WindowedIncognitoObserver> incognito_observer,
228 SampledProfile::TriggerEvent trigger_event,
227 const std::vector<uint8>& data) { 229 const std::vector<uint8>& data) {
228 DCHECK(CalledOnValidThread()); 230 DCHECK(CalledOnValidThread());
229 231
230 if (incognito_observer->incognito_launched()) { 232 if (incognito_observer->incognito_launched()) {
231 AddToPerfHistogram(INCOGNITO_LAUNCHED); 233 AddToPerfHistogram(INCOGNITO_LAUNCHED);
232 return; 234 return;
233 } 235 }
234 236
235 PerfDataProto perf_data_proto; 237 PerfDataProto perf_data_proto;
236 if (!perf_data_proto.ParseFromArray(data.data(), data.size())) { 238 if (!perf_data_proto.ParseFromArray(data.data(), data.size())) {
237 AddToPerfHistogram(PROTOBUF_NOT_PARSED); 239 AddToPerfHistogram(PROTOBUF_NOT_PARSED);
238 return; 240 return;
239 } 241 }
240 242
241 // Append a new PerfDataProto to the |cached_perf_data_| vector and swap in 243 // Populate a profile collection protobuf with the collected perf data and
242 // the contents. 244 // extra metadata.
243 cached_perf_data_.resize(cached_perf_data_.size() + 1); 245 cached_perf_data_.resize(cached_perf_data_.size() + 1);
244 cached_perf_data_.back().Swap(&perf_data_proto); 246 SampledProfile& collection_data = cached_perf_data_.back();
247 collection_data.set_trigger_event(trigger_event);
248 collection_data.set_ms_after_boot(
249 perf_data_proto.timestamp_sec() * base::Time::kMillisecondsPerSecond);
250
251 DCHECK(!login_time_.is_null());
252 collection_data.
253 set_ms_after_login((base::TimeTicks::Now() - login_time_)
254 .InMilliseconds());
255 *collection_data.mutable_perf_data() = perf_data_proto;
245 } 256 }
246 257
247 } // namespace metrics 258 } // 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