Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/chromeos/power/cpu_data_collector.h" | 5 #include "chrome/browser/chromeos/power/cpu_data_collector.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 234 freq_sample->time_in_state[index] = occupancy_time_centisecond * 10; | 234 freq_sample->time_in_state[index] = occupancy_time_centisecond * 10; |
| 235 } else { | 235 } else { |
| 236 LOG(ERROR) << "Bad format in " << path << ". " | 236 LOG(ERROR) << "Bad format in " << path << ". " |
| 237 << "Dropping sample."; | 237 << "Dropping sample."; |
| 238 return false; | 238 return false; |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 return true; | 241 return true; |
| 242 } | 242 } |
| 243 | 243 |
| 244 bool ReadCpuFreqFromNewFile( | |
|
Daniel Erat
2017/05/01 19:46:32
"old file" and "new file" aren't very descriptive.
weidongg
2017/05/02 22:16:16
Done.
| |
| 245 int cpu_count, | |
| 246 const std::string& path, | |
| 247 std::vector<std::string>* cpu_freq_state_names, | |
|
Daniel Erat
2017/05/01 22:28:38
high-level question about this code: is there any
weidongg
2017/05/02 22:16:15
It seems that the author intentionally separated t
| |
| 248 std::vector<CpuDataCollector::StateOccupancySample>* freq_samples) { | |
|
Daniel Erat
2017/05/01 19:46:32
please document all of these parameters. freq_samp
weidongg
2017/05/02 22:16:16
Done.
| |
| 249 std::string time_in_state_string; | |
| 250 // Note time as close to reading the file as possible. This is | |
| 251 // not possible for idle state samples as the information for | |
| 252 // each state there is recorded in different files. | |
| 253 if (!base::ReadFileToString(base::FilePath(path), &time_in_state_string)) { | |
| 254 LOG(ERROR) << "Error reading " << path << ". " | |
| 255 << "Dropping sample."; | |
| 256 return false; | |
| 257 } | |
| 258 | |
| 259 std::vector<base::StringPiece> lines = base::SplitStringPiece( | |
| 260 time_in_state_string, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 261 // The last line could end with '\n'. Ignore the last empty string in | |
| 262 // such cases. | |
| 263 size_t state_count = lines.size(); | |
| 264 if (state_count > 0 && lines.back().empty()) | |
| 265 state_count -= 1; | |
|
Daniel Erat
2017/05/01 19:46:32
consider just using base::TrimWhitespaceASCII on t
weidongg
2017/05/02 22:16:16
Done.
| |
| 266 // The first line is descriptions in the format "freq\t\tcpu0\t\tcpu1...". | |
| 267 if (state_count > 0) { | |
|
Daniel Erat
2017/05/01 19:46:32
if lines is empty, shouldn't you just return false
weidongg
2017/05/02 22:16:15
Yes, it is supposed to return false.
| |
| 268 state_count -= 1; | |
| 269 lines.erase(lines.begin()); | |
| 270 } | |
| 271 for (size_t state = 0; state < state_count; ++state) { | |
| 272 int freq_in_khz; | |
| 273 | |
| 274 // Occupancy of each state is in the format "<state>\t\t<time>\t\t<time> | |
| 275 // ..." | |
| 276 std::vector<base::StringPiece> array = base::SplitStringPiece( | |
| 277 lines[state], "\t", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); | |
| 278 if (array.size() == size_t(cpu_count) + 1 && | |
| 279 base::StringToInt(array[0], &freq_in_khz)) { | |
| 280 const std::string state_name = base::IntToString(freq_in_khz / 1000); | |
| 281 size_t index = IndexInVector(state_name, cpu_freq_state_names); | |
|
Daniel Erat
2017/05/01 19:46:32
presumably you need to check the index here.
weidongg
2017/05/01 21:50:10
the index returned is always valid, as the state_n
Daniel Erat
2017/05/01 22:28:38
sorry, i was confused by the name IndexInVector. w
weidongg
2017/05/02 22:16:16
Done.
| |
| 282 for (int cpu = 0; cpu < cpu_count; ++cpu) { | |
| 283 if (!(*freq_samples)[cpu].cpu_online) { | |
| 284 continue; | |
| 285 } | |
| 286 if (index >= (*freq_samples)[cpu].time_in_state.size()) | |
| 287 (*freq_samples)[cpu].time_in_state.resize(index + 1); | |
| 288 int64_t occupancy_time_centisecond; | |
| 289 base::StringToInt64(array[cpu + 1], &occupancy_time_centisecond); | |
|
Daniel Erat
2017/05/01 19:46:32
you need to check the return value of this convers
weidongg
2017/05/02 22:16:15
Done.
| |
| 290 (*freq_samples)[cpu].time_in_state[index] = | |
| 291 occupancy_time_centisecond * 10; | |
| 292 } | |
| 293 } else { | |
|
Daniel Erat
2017/05/01 19:46:32
test for bad input and return false immediately; t
weidongg
2017/05/01 21:50:10
Sorry, I don't understand, could you be more speci
Daniel Erat
2017/05/01 22:28:38
i mean this code would be simpler if you did:
i
weidongg
2017/05/02 22:16:15
Ok, I see. Yes, that's better.
| |
| 294 LOG(ERROR) << "Bad format in " << path << ". " | |
| 295 << "Dropping sample."; | |
| 296 return false; | |
| 297 } | |
| 298 } | |
| 299 return true; | |
| 300 } | |
| 301 | |
| 244 // Samples the CPU freq state information from sysfs. |cpu_count| is the number | 302 // Samples the CPU freq state information from sysfs. |cpu_count| is the number |
| 245 // of possible CPUs on the system. Sample at index i in |freq_samples| | 303 // of possible CPUs on the system. Sample at index i in |freq_samples| |
| 246 // corresponds to the freq state information of the i-th CPU. | 304 // corresponds to the freq state information of the i-th CPU. |
| 247 void SampleCpuFreqData( | 305 void SampleCpuFreqData( |
| 248 int cpu_count, | 306 int cpu_count, |
| 249 std::vector<std::string>* cpu_freq_state_names, | 307 std::vector<std::string>* cpu_freq_state_names, |
| 250 std::vector<CpuDataCollector::StateOccupancySample>* freq_samples) { | 308 std::vector<CpuDataCollector::StateOccupancySample>* freq_samples) { |
| 251 base::Time start_time = base::Time::Now(); | 309 base::Time start_time = base::Time::Now(); |
| 252 for (int cpu = 0; cpu < cpu_count; ++cpu) { | 310 for (int cpu = 0; cpu < cpu_count; ++cpu) { |
| 253 CpuDataCollector::StateOccupancySample freq_sample; | 311 CpuDataCollector::StateOccupancySample freq_sample; |
| 254 freq_sample.time_in_state.reserve(cpu_freq_state_names->size()); | 312 freq_sample.time_in_state.reserve(cpu_freq_state_names->size()); |
| 313 freq_sample.time = base::Time::Now(); | |
| 314 freq_sample.cpu_online = CpuIsOnline(cpu); | |
| 315 freq_samples->push_back(freq_sample); | |
| 316 } | |
| 255 | 317 |
| 256 freq_sample.time = base::Time::Now(); | 318 if (!base::PathExists(base::FilePath(kCpuFreqTimeInStateNewPath))) { |
| 257 if (!CpuIsOnline(cpu)) { | 319 if (!ReadCpuFreqFromNewFile(cpu_count, kCpuFreqTimeInStateNewPath, |
| 258 freq_sample.cpu_online = false; | 320 cpu_freq_state_names, freq_samples)) { |
| 259 } else { | 321 freq_samples->clear(); |
| 260 freq_sample.cpu_online = true; | 322 return; |
| 261 | 323 } |
| 262 const std::string time_in_state_path_old_format = base::StringPrintf( | 324 } else { |
| 263 "%s%s", kCpuDataPathBase, kCpuFreqTimeInStatePathSuffixOldFormat); | 325 for (int cpu = 0; cpu < cpu_count; ++cpu) { |
| 264 const std::string time_in_state_path = | 326 if ((*freq_samples)[cpu].cpu_online) { |
| 265 base::StringPrintf(time_in_state_path_old_format.c_str(), cpu); | 327 const std::string time_in_state_path_old_format = base::StringPrintf( |
| 266 if (base::PathExists(base::FilePath(time_in_state_path))) { | 328 "%s%s", kCpuDataPathBase, kCpuFreqTimeInStatePathSuffixOldFormat); |
| 267 if (!ReadCpuFreqFromOldFile(time_in_state_path, cpu_freq_state_names, | 329 const std::string time_in_state_path = |
| 268 &freq_sample)) { | 330 base::StringPrintf(time_in_state_path_old_format.c_str(), cpu); |
| 331 if (base::PathExists(base::FilePath(time_in_state_path))) { | |
| 332 if (!ReadCpuFreqFromOldFile(time_in_state_path, cpu_freq_state_names, | |
| 333 &(*freq_samples)[cpu])) { | |
| 334 freq_samples->clear(); | |
| 335 return; | |
| 336 } | |
| 337 } else { | |
| 338 // If the path to the 'time_in_state' for a single CPU is missing, | |
| 339 // then 'time_in_state' for all CPUs is missing. This could happen | |
| 340 // on a VM where the 'cpufreq_stats' kernel module is not loaded. | |
| 341 LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS()) | |
| 342 << "CPU freq stats not available in sysfs."; | |
| 269 freq_samples->clear(); | 343 freq_samples->clear(); |
| 270 return; | 344 return; |
| 271 } | 345 } |
| 272 } else if (base::PathExists(base::FilePath(kCpuFreqTimeInStateNewPath))) { | |
| 273 // TODO(oshima): Parse the new file. crbug.com/548510. | |
| 274 freq_samples->clear(); | |
| 275 return; | |
| 276 } else { | |
| 277 // If the path to the 'time_in_state' for a single CPU is missing, | |
| 278 // then 'time_in_state' for all CPUs is missing. This could happen | |
| 279 // on a VM where the 'cpufreq_stats' kernel module is not loaded. | |
| 280 LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS()) | |
| 281 << "CPU freq stats not available in sysfs."; | |
| 282 freq_samples->clear(); | |
| 283 return; | |
| 284 } | 346 } |
| 285 } | 347 } |
| 286 | |
| 287 freq_samples->push_back(freq_sample); | |
| 288 } | 348 } |
| 289 | |
| 290 // If there was an interruption in sampling (like system suspended), | 349 // If there was an interruption in sampling (like system suspended), |
| 291 // discard the samples! | 350 // discard the samples! |
| 292 int64_t delay = | 351 int64_t delay = |
| 293 base::TimeDelta(base::Time::Now() - start_time).InMilliseconds(); | 352 base::TimeDelta(base::Time::Now() - start_time).InMilliseconds(); |
| 294 if (delay > kSamplingDurationLimitMs) { | 353 if (delay > kSamplingDurationLimitMs) { |
| 295 freq_samples->clear(); | 354 freq_samples->clear(); |
| 296 LOG(WARNING) << "Dropped a freq state sample due to excessive time delay: " | 355 LOG(WARNING) << "Dropped a freq state sample due to excessive time delay: " |
| 297 << delay << "milliseconds."; | 356 << delay << "milliseconds."; |
| 298 } | 357 } |
| 299 } | 358 } |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 : cpu_online(false) { | 499 : cpu_online(false) { |
| 441 } | 500 } |
| 442 | 501 |
| 443 CpuDataCollector::StateOccupancySample::StateOccupancySample( | 502 CpuDataCollector::StateOccupancySample::StateOccupancySample( |
| 444 const StateOccupancySample& other) = default; | 503 const StateOccupancySample& other) = default; |
| 445 | 504 |
| 446 CpuDataCollector::StateOccupancySample::~StateOccupancySample() { | 505 CpuDataCollector::StateOccupancySample::~StateOccupancySample() { |
| 447 } | 506 } |
| 448 | 507 |
| 449 } // namespace chromeos | 508 } // namespace chromeos |
| OLD | NEW |