OLD | NEW |
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 <string> | 8 #include <string> |
8 | 9 |
9 #include "base/bind.h" | 10 #include "base/bind.h" |
10 #include "base/callback.h" | 11 #include "base/callback.h" |
11 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
12 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
13 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 15 #include "base/strings/string_split.h" |
14 #include "base/threading/sequenced_worker_pool.h" | 16 #include "base/threading/sequenced_worker_pool.h" |
15 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h" | 17 #include "chrome/browser/metrics/perf/windowed_incognito_observer.h" |
16 #include "chrome/browser/ui/browser_list.h" | 18 #include "chrome/browser/ui/browser_list.h" |
17 #include "chromeos/dbus/dbus_thread_manager.h" | 19 #include "chromeos/dbus/dbus_thread_manager.h" |
18 #include "chromeos/dbus/debug_daemon_client.h" | 20 #include "chromeos/dbus/debug_daemon_client.h" |
19 | 21 |
20 namespace metrics { | 22 namespace metrics { |
21 | 23 |
22 namespace { | 24 namespace { |
23 | 25 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 bool IsNormalUserLoggedIn() { | 61 bool IsNormalUserLoggedIn() { |
60 return chromeos::LoginState::Get()->IsUserAuthenticated(); | 62 return chromeos::LoginState::Get()->IsUserAuthenticated(); |
61 } | 63 } |
62 | 64 |
63 // Returns a random TimeDelta between zero and |max|. | 65 // Returns a random TimeDelta between zero and |max|. |
64 base::TimeDelta RandomTimeDelta(base::TimeDelta max) { | 66 base::TimeDelta RandomTimeDelta(base::TimeDelta max) { |
65 return base::TimeDelta::FromMicroseconds( | 67 return base::TimeDelta::FromMicroseconds( |
66 base::RandGenerator(max.InMicroseconds())); | 68 base::RandGenerator(max.InMicroseconds())); |
67 } | 69 } |
68 | 70 |
| 71 // Hopefully we never need a space in a command argument. |
| 72 const char kPerfCommandDelimiter[] = " "; |
| 73 |
| 74 const char kPerfRecordCyclesCmd[] = |
| 75 "perf record -a -e cycles -c 1000003"; |
| 76 |
| 77 const char kPerfRecordCallgraphCmd[] = |
| 78 "perf record -a -e cycles -g -c 4000037"; |
| 79 |
| 80 const char kPerfRecordLBRCmd[] = |
| 81 "perf record -a -e r2c4 -b -c 20011"; |
| 82 |
| 83 const char kPerfRecordInstructionTLBMissesCmd[] = |
| 84 "perf record -a -e iTLB-misses -c 2003"; |
| 85 |
| 86 const char kPerfRecordDataTLBMissesCmd[] = |
| 87 "perf record -a -e dTLB-misses -c 2003"; |
| 88 |
| 89 const char kPerfStatMemoryBandwidthCmd[] = |
| 90 "perf stat -a -e cycles -e instructions " |
| 91 "-e uncore_imc/data_reads/ -e uncore_imc/data_writes/ " |
| 92 "-e cpu/event=0xD0,umask=0x11,name=MEM_UOPS_RETIRED-STLB_MISS_LOADS/ " |
| 93 "-e cpu/event=0xD0,umask=0x12,name=MEM_UOPS_RETIRED-STLB_MISS_STORES/"; |
| 94 |
| 95 const std::vector<RandomSelector::WeightAndValue> GetDefaultCommands_x86_64( |
| 96 const CPUIdentity& cpuid) { |
| 97 using WeightAndValue = RandomSelector::WeightAndValue; |
| 98 std::vector<WeightAndValue> cmds; |
| 99 DCHECK_EQ(cpuid.arch, "x86_64"); |
| 100 const std::string intel_uarch = GetIntelUarch(cpuid); |
| 101 if (intel_uarch == "IvyBridge" || |
| 102 intel_uarch == "Haswell" || |
| 103 intel_uarch == "Broadwell") { |
| 104 cmds.push_back(WeightAndValue(60.0, kPerfRecordCyclesCmd)); |
| 105 cmds.push_back(WeightAndValue(20.0, kPerfRecordCallgraphCmd)); |
| 106 cmds.push_back(WeightAndValue(5.0, kPerfRecordLBRCmd)); |
| 107 cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd)); |
| 108 cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd)); |
| 109 cmds.push_back(WeightAndValue(5.0, kPerfStatMemoryBandwidthCmd)); |
| 110 return cmds; |
| 111 } |
| 112 if (intel_uarch == "SandyBridge") { |
| 113 cmds.push_back(WeightAndValue(65.0, kPerfRecordCyclesCmd)); |
| 114 cmds.push_back(WeightAndValue(20.0, kPerfRecordCallgraphCmd)); |
| 115 cmds.push_back(WeightAndValue(5.0, kPerfRecordLBRCmd)); |
| 116 cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd)); |
| 117 cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd)); |
| 118 return cmds; |
| 119 } |
| 120 // Other 64-bit x86 |
| 121 cmds.push_back(WeightAndValue(70.0, kPerfRecordCyclesCmd)); |
| 122 cmds.push_back(WeightAndValue(20.0, kPerfRecordCallgraphCmd)); |
| 123 cmds.push_back(WeightAndValue(5.0, kPerfRecordInstructionTLBMissesCmd)); |
| 124 cmds.push_back(WeightAndValue(5.0, kPerfRecordDataTLBMissesCmd)); |
| 125 return cmds; |
| 126 } |
| 127 |
69 } // namespace | 128 } // namespace |
70 | 129 |
| 130 namespace internal { |
| 131 |
| 132 std::vector<RandomSelector::WeightAndValue> GetDefaultCommandsForCpu( |
| 133 const CPUIdentity& cpuid) { |
| 134 using WeightAndValue = RandomSelector::WeightAndValue; |
| 135 |
| 136 if (cpuid.arch == "x86_64") // 64-bit x86 |
| 137 return GetDefaultCommands_x86_64(cpuid); |
| 138 |
| 139 std::vector<WeightAndValue> cmds; |
| 140 if (cpuid.arch == "x86" || // 32-bit x86, or... |
| 141 cpuid.arch == "armv7l") { // ARM |
| 142 cmds.push_back(WeightAndValue(80.0, kPerfRecordCyclesCmd)); |
| 143 cmds.push_back(WeightAndValue(20.0, kPerfRecordCallgraphCmd)); |
| 144 return cmds; |
| 145 } |
| 146 |
| 147 // Unknown CPUs |
| 148 cmds.push_back(WeightAndValue(1.0, kPerfRecordCyclesCmd)); |
| 149 return cmds; |
| 150 } |
| 151 |
| 152 } // namespace internal |
| 153 |
71 PerfProvider::CollectionParams::CollectionParams( | 154 PerfProvider::CollectionParams::CollectionParams( |
72 base::TimeDelta collection_duration, | 155 base::TimeDelta collection_duration, |
73 base::TimeDelta periodic_interval, | 156 base::TimeDelta periodic_interval, |
74 TriggerParams resume_from_suspend, | 157 TriggerParams resume_from_suspend, |
75 TriggerParams restore_session) | 158 TriggerParams restore_session) |
76 : collection_duration_(collection_duration.ToInternalValue()), | 159 : collection_duration_(collection_duration.ToInternalValue()), |
77 periodic_interval_(periodic_interval.ToInternalValue()), | 160 periodic_interval_(periodic_interval.ToInternalValue()), |
78 resume_from_suspend_(resume_from_suspend), | 161 resume_from_suspend_(resume_from_suspend), |
79 restore_session_(restore_session) { | 162 restore_session_(restore_session) { |
80 } | 163 } |
(...skipping 13 matching lines...) Expand all Loading... |
94 /* max_collection_delay = */ base::TimeDelta::FromSeconds(5)), | 177 /* max_collection_delay = */ base::TimeDelta::FromSeconds(5)), |
95 /* restore_session = */ PerfProvider::CollectionParams::TriggerParams( | 178 /* restore_session = */ PerfProvider::CollectionParams::TriggerParams( |
96 /* sampling_factor = */ 10, | 179 /* sampling_factor = */ 10, |
97 /* max_collection_delay = */ base::TimeDelta::FromSeconds(10))); | 180 /* max_collection_delay = */ base::TimeDelta::FromSeconds(10))); |
98 | 181 |
99 PerfProvider::PerfProvider() | 182 PerfProvider::PerfProvider() |
100 : collection_params_(kDefaultParameters), | 183 : collection_params_(kDefaultParameters), |
101 login_observer_(this), | 184 login_observer_(this), |
102 next_profiling_interval_start_(base::TimeTicks::Now()), | 185 next_profiling_interval_start_(base::TimeTicks::Now()), |
103 weak_factory_(this) { | 186 weak_factory_(this) { |
| 187 command_selector_.SetOdds( |
| 188 internal::GetDefaultCommandsForCpu(GetCPUIdentity())), |
| 189 |
104 // Register the login observer with LoginState. | 190 // Register the login observer with LoginState. |
105 chromeos::LoginState::Get()->AddObserver(&login_observer_); | 191 chromeos::LoginState::Get()->AddObserver(&login_observer_); |
106 | 192 |
107 // Register as an observer of power manager events. | 193 // Register as an observer of power manager events. |
108 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> | 194 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()-> |
109 AddObserver(this); | 195 AddObserver(this); |
110 | 196 |
111 // Register as an observer of session restore. | 197 // Register as an observer of session restore. |
112 on_session_restored_callback_subscription_ = | 198 on_session_restored_callback_subscription_ = |
113 SessionRestore::RegisterOnSessionRestoredCallback( | 199 SessionRestore::RegisterOnSessionRestoredCallback( |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 AddToPerfHistogram(INCOGNITO_ACTIVE); | 419 AddToPerfHistogram(INCOGNITO_ACTIVE); |
334 return; | 420 return; |
335 } | 421 } |
336 | 422 |
337 scoped_ptr<WindowedIncognitoObserver> incognito_observer( | 423 scoped_ptr<WindowedIncognitoObserver> incognito_observer( |
338 new WindowedIncognitoObserver); | 424 new WindowedIncognitoObserver); |
339 | 425 |
340 chromeos::DebugDaemonClient* client = | 426 chromeos::DebugDaemonClient* client = |
341 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); | 427 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); |
342 | 428 |
| 429 std::vector<std::string> command = base::SplitString( |
| 430 command_selector_.Select(), kPerfCommandDelimiter, |
| 431 base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); |
343 client->GetPerfOutput( | 432 client->GetPerfOutput( |
344 collection_params_.collection_duration().InSeconds(), | 433 collection_params_.collection_duration().InSeconds(), command, |
345 base::Bind(&PerfProvider::ParseOutputProtoIfValid, | 434 base::Bind(&PerfProvider::ParseOutputProtoIfValid, |
346 weak_factory_.GetWeakPtr(), base::Passed(&incognito_observer), | 435 weak_factory_.GetWeakPtr(), base::Passed(&incognito_observer), |
347 base::Passed(&sampled_profile))); | 436 base::Passed(&sampled_profile))); |
348 } | 437 } |
349 | 438 |
350 void PerfProvider::DoPeriodicCollection() { | 439 void PerfProvider::DoPeriodicCollection() { |
351 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); | 440 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); |
352 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); | 441 sampled_profile->set_trigger_event(SampledProfile::PERIODIC_COLLECTION); |
353 | 442 |
354 CollectIfNecessary(sampled_profile.Pass()); | 443 CollectIfNecessary(sampled_profile.Pass()); |
(...skipping 18 matching lines...) Expand all Loading... |
373 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); | 462 scoped_ptr<SampledProfile> sampled_profile(new SampledProfile); |
374 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); | 463 sampled_profile->set_trigger_event(SampledProfile::RESTORE_SESSION); |
375 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds()); | 464 sampled_profile->set_ms_after_restore(time_after_restore.InMilliseconds()); |
376 sampled_profile->set_num_tabs_restored(num_tabs_restored); | 465 sampled_profile->set_num_tabs_restored(num_tabs_restored); |
377 | 466 |
378 CollectIfNecessary(sampled_profile.Pass()); | 467 CollectIfNecessary(sampled_profile.Pass()); |
379 last_session_restore_collection_time_ = base::TimeTicks::Now(); | 468 last_session_restore_collection_time_ = base::TimeTicks::Now(); |
380 } | 469 } |
381 | 470 |
382 } // namespace metrics | 471 } // namespace metrics |
OLD | NEW |