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

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

Issue 1392153003: PerfProvider: Get collection parameters from Finch (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@perf_commands
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 <algorithm> 7 #include <algorithm>
8 #include <map>
8 #include <string> 9 #include <string>
9 10
10 #include "base/bind.h" 11 #include "base/bind.h"
11 #include "base/callback.h" 12 #include "base/callback.h"
12 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/metrics/field_trial.h"
13 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
14 #include "base/rand_util.h" 16 #include "base/rand_util.h"
17 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/string_split.h" 18 #include "base/strings/string_split.h"
16 #include "base/threading/sequenced_worker_pool.h" 19 #include "base/threading/sequenced_worker_pool.h"
17 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h" 20 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h"
18 #include "chrome/browser/ui/browser_list.h" 21 #include "chrome/browser/ui/browser_list.h"
19 #include "chromeos/dbus/dbus_thread_manager.h" 22 #include "chromeos/dbus/dbus_thread_manager.h"
20 #include "chromeos/dbus/debug_daemon_client.h" 23 #include "chromeos/dbus/debug_daemon_client.h"
24 #include "components/variations/variations_associated_data.h"
21 25
22 namespace metrics { 26 namespace metrics {
23 27
24 namespace { 28 namespace {
25 29
30 const char kCWPFieldTrialName[] = "ChromeOSWideProfilingCollection";
31
26 // Limit the total size of protobufs that can be cached, so they don't take up 32 // Limit the total size of protobufs that can be cached, so they don't take up
27 // too much memory. If the size of cached protobufs exceeds this value, stop 33 // too much memory. If the size of cached protobufs exceeds this value, stop
28 // collecting further perf data. The current value is 4 MB. 34 // collecting further perf data. The current value is 4 MB.
29 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024; 35 const size_t kCachedPerfDataProtobufSizeThreshold = 4 * 1024 * 1024;
30 36
31 // This is used to space out session restore collections in the face of several 37 // This is used to space out session restore collections in the face of several
32 // notifications in a short period of time. There should be no less than this 38 // notifications in a short period of time. There should be no less than this
33 // much time between collections. 39 // much time between collections.
34 const int kMinIntervalBetweenSessionRestoreCollectionsInSec = 30; 40 const int kMinIntervalBetweenSessionRestoreCollectionsInSec = 30;
35 41
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 /* max_collection_delay = */ base::TimeDelta::FromSeconds(5)), 183 /* max_collection_delay = */ base::TimeDelta::FromSeconds(5)),
178 /* restore_session = */ PerfProvider::CollectionParams::TriggerParams( 184 /* restore_session = */ PerfProvider::CollectionParams::TriggerParams(
179 /* sampling_factor = */ 10, 185 /* sampling_factor = */ 10,
180 /* max_collection_delay = */ base::TimeDelta::FromSeconds(10))); 186 /* max_collection_delay = */ base::TimeDelta::FromSeconds(10)));
181 187
182 PerfProvider::PerfProvider() 188 PerfProvider::PerfProvider()
183 : collection_params_(kDefaultParameters), 189 : collection_params_(kDefaultParameters),
184 login_observer_(this), 190 login_observer_(this),
185 next_profiling_interval_start_(base::TimeTicks::Now()), 191 next_profiling_interval_start_(base::TimeTicks::Now()),
186 weak_factory_(this) { 192 weak_factory_(this) {
187 command_selector_.SetOdds( 193 CHECK(command_selector_.SetOdds(
188 internal::GetDefaultCommandsForCpu(GetCPUIdentity())), 194 internal::GetDefaultCommandsForCpu(GetCPUIdentity())));
195 std::map<std::string, std::string> params;
196 if (variations::GetVariationParams(kCWPFieldTrialName, &params))
197 SetCollectionParamsFromVariationParams(params);
189 198
190 // Register the login observer with LoginState. 199 // Register the login observer with LoginState.
191 chromeos::LoginState::Get()->AddObserver(&login_observer_); 200 chromeos::LoginState::Get()->AddObserver(&login_observer_);
192 201
193 // Register as an observer of power manager events. 202 // Register as an observer of power manager events.
194 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> 203 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
195 AddObserver(this); 204 AddObserver(this);
196 205
197 // Register as an observer of session restore. 206 // Register as an observer of session restore.
198 on_session_restored_callback_subscription_ = 207 on_session_restored_callback_subscription_ =
199 SessionRestore::RegisterOnSessionRestoredCallback( 208 SessionRestore::RegisterOnSessionRestoredCallback(
200 base::Bind(&PerfProvider::OnSessionRestoreDone, 209 base::Bind(&PerfProvider::OnSessionRestoreDone,
201 weak_factory_.GetWeakPtr())); 210 weak_factory_.GetWeakPtr()));
202 211
203 // Check the login state. At the time of writing, this class is instantiated 212 // Check the login state. At the time of writing, this class is instantiated
204 // before login. A subsequent login would activate the profiling. However, 213 // before login. A subsequent login would activate the profiling. However,
205 // that behavior may change in the future so that the user is already logged 214 // that behavior may change in the future so that the user is already logged
206 // when this class is instantiated. By calling LoggedInStateChanged() here, 215 // when this class is instantiated. By calling LoggedInStateChanged() here,
207 // PerfProvider will recognize that the system is already logged in. 216 // PerfProvider will recognize that the system is already logged in.
208 login_observer_.LoggedInStateChanged(); 217 login_observer_.LoggedInStateChanged();
209 } 218 }
210 219
211 PerfProvider::~PerfProvider() { 220 PerfProvider::~PerfProvider() {
212 chromeos::LoginState::Get()->RemoveObserver(&login_observer_); 221 chromeos::LoginState::Get()->RemoveObserver(&login_observer_);
213 } 222 }
214 223
224 namespace {
225
226 bool GetInt64Param(const std::map<std::string, std::string>& params,
Alexei Svitkine (slow) 2015/10/20 20:24:58 Nit: Add a short comment.
dhsharp 2015/10/21 02:17:02 Done.
227 const std::string& key, int64* out) {
Alexei Svitkine (slow) 2015/10/20 20:24:58 Nit: I'd prefer the last param be on a separate li
dhsharp 2015/10/21 02:17:02 Done.
228 auto it = params.find(key);
229 if (it == params.end())
230 return false;
231 int64 value;
232 // NB: StringToInt64 will set value even if the conversion fails.
233 if (!base::StringToInt64(it->second, &value))
Alexei Svitkine (slow) 2015/10/20 20:24:58 Nit: How about this more concise form: if (it ==
dhsharp 2015/10/21 02:17:02 I don't like to combine unrelated conditions. In t
234 return false;
235 *out = value;
236 return true;
237 }
238
239 // Parse the key. e.g.: "PerfCommand::arm::0" returns "arm"
240 bool ExtractPerfCommandCpuSpecifier(const std::string& key,
241 std::string* cpu_specifier) {
242 std::vector<std::string> tokens;
243 base::SplitStringUsingSubstr(key, "::", &tokens);
244 if (tokens.size() != 3)
245 return false;
246 if (tokens[0] != "PerfCommand")
Alexei Svitkine (slow) 2015/10/20 20:24:58 Nit: Ditto, combine the ifs.
dhsharp 2015/10/21 02:17:03 I don't like how the code reads. I think it minimi
247 return false;
248 *cpu_specifier = tokens[1];
249 // tokens[2] is just a unique string (usually an index).
250 return true;
251 }
252
253 } // namespace
254
255 namespace internal {
256
257 std::string FindBestCpuSpecifierFromParams(
258 const std::map<std::string, std::string>& params,
259 const CPUIdentity& cpuid) {
260 std::string ret;
261 // The CPU specified in the variation params could be "default", a system
262 // architecture, a CPU microarchitecture, or a CPU model substring. We should
263 // prefer to match the most specific.
264 enum MatchSpecificity {
265 NO_MATCH,
266 DEFAULT,
267 SYSTEM_ARCH,
268 CPU_UARCH,
269 CPU_MODEL,
270 };
271 MatchSpecificity match_level = NO_MATCH;
272
273 const std::string intel_uarch = GetIntelUarch(cpuid);
274 const std::string simplified_cpu_model =
275 SimplifyCPUModelName(cpuid.model_name);
276
277 for (const auto& key_val : params) {
278 const std::string& key = key_val.first;
279
280 std::string cpu_specifier;
281 if (!ExtractPerfCommandCpuSpecifier(key, &cpu_specifier))
282 continue;
283
284 if (match_level < DEFAULT && cpu_specifier == "default") {
285 match_level = DEFAULT;
286 ret = cpu_specifier;
287 }
288 if (match_level < SYSTEM_ARCH && cpu_specifier == cpuid.arch) {
289 match_level = SYSTEM_ARCH;
290 ret = cpu_specifier;
291 }
292 if (match_level < CPU_UARCH &&
293 intel_uarch != "" && cpu_specifier == intel_uarch) {
Alexei Svitkine (slow) 2015/10/20 20:24:58 Nit: !intel_uarch.empty()
dhsharp 2015/10/21 02:17:03 Done.
294 match_level = CPU_UARCH;
295 ret = cpu_specifier;
296 }
297 if (match_level < CPU_MODEL &&
298 simplified_cpu_model.find(cpu_specifier) != std::string::npos) {
299 match_level = CPU_MODEL;
300 ret = cpu_specifier;
301 }
302 }
303 return ret;
304 }
305
306 } // namespace internal
307
308 void PerfProvider::SetCollectionParamsFromVariationParams(
309 const std::map<std::string, std::string>& params) {
310 int64 value;
311 if (GetInt64Param(params, "ProfileCollectionDurationSec", &value)) {
312 collection_params_.set_collection_duration(
313 base::TimeDelta::FromSeconds(value));
314 }
315 if (GetInt64Param(params, "PeriodicProfilingIntervalMs", &value)) {
316 collection_params_.set_periodic_interval(
317 base::TimeDelta::FromMilliseconds(value));
318 }
319 if (GetInt64Param(params, "ResumeFromSuspend::SamplingFactor", &value)) {
320 collection_params_.mutable_resume_from_suspend()
321 ->set_sampling_factor(value);
322 }
323 if (GetInt64Param(params, "ResumeFromSuspend::MaxDelaySec", &value)) {
324 collection_params_.mutable_resume_from_suspend()->set_max_collection_delay(
325 base::TimeDelta::FromSeconds(value));
326 }
327 if (GetInt64Param(params, "RestoreSession::SamplingFactor", &value)) {
328 collection_params_.mutable_restore_session()->set_sampling_factor(value);
329 }
330 if (GetInt64Param(params, "RestoreSession::MaxDelaySec", &value)) {
331 collection_params_.mutable_restore_session()->set_max_collection_delay(
332 base::TimeDelta::FromSeconds(value));
333 }
334
335 const std::string best_cpu_specifier =
336 internal::FindBestCpuSpecifierFromParams(params, GetCPUIdentity());
337
338 if (best_cpu_specifier.empty()) // no matching cpu specifier. Keep defaults.
Alexei Svitkine (slow) 2015/10/20 20:24:58 Nit: Capitalize No
dhsharp 2015/10/21 02:17:03 Done.
339 return;
340
341 std::vector<RandomSelector::WeightAndValue> commands;
342 for (const auto& key_val : params) {
343 const std::string& key = key_val.first;
344 const std::string& val = key_val.second;
345
346 std::string cpu_specifier;
347 if (!ExtractPerfCommandCpuSpecifier(key, &cpu_specifier))
348 continue;
349 if (cpu_specifier != best_cpu_specifier)
350 continue;
351
352 auto split = val.find(" ");
353 if (split == std::string::npos)
354 continue; // Just drop invalid commands.
355 std::string weight_str = std::string(val.begin(), val.begin() + split);
356
357 double weight;
358 if (!(base::StringToDouble(weight_str, &weight) && weight > 0.0))
359 continue; // Just drop invalid commands.
360 std::string command(val.begin() + split + 1, val.end());
361 commands.push_back(RandomSelector::WeightAndValue(weight, command));
362 }
363 command_selector_.SetOdds(commands);
364 }
365
215 bool PerfProvider::GetSampledProfiles( 366 bool PerfProvider::GetSampledProfiles(
216 std::vector<SampledProfile>* sampled_profiles) { 367 std::vector<SampledProfile>* sampled_profiles) {
217 DCHECK(CalledOnValidThread()); 368 DCHECK(CalledOnValidThread());
218 if (cached_perf_data_.empty()) { 369 if (cached_perf_data_.empty()) {
219 AddToPerfHistogram(NOT_READY_TO_UPLOAD); 370 AddToPerfHistogram(NOT_READY_TO_UPLOAD);
220 return false; 371 return false;
221 } 372 }
222 373
223 sampled_profiles->swap(cached_perf_data_); 374 sampled_profiles->swap(cached_perf_data_);
224 cached_perf_data_.clear(); 375 cached_perf_data_.clear();
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); 613 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile);
463 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); 614 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION);
464 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds()); 615 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds());
465 sampled_profile->set_num_tabs_restored(num_tabs_restored); 616 sampled_profile->set_num_tabs_restored(num_tabs_restored);
466 617
467 CollectIfNecessary(sampled_profile.Pass()); 618 CollectIfNecessary(sampled_profile.Pass());
468 last_session_restore_collection_time_ = base::TimeTicks::Now(); 619 last_session_restore_collection_time_ = base::TimeTicks::Now();
469 } 620 }
470 621
471 } // namespace metrics 622 } // namespace metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698