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 |