OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 "base/process/process_metrics.h" | 5 #include "base/process/process_metrics.h" |
6 | 6 |
7 #include <dirent.h> | 7 #include <dirent.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <sys/stat.h> | 9 #include <sys/stat.h> |
10 #include <sys/time.h> | 10 #include <sys/time.h> |
11 #include <sys/types.h> | 11 #include <sys/types.h> |
12 #include <unistd.h> | 12 #include <unistd.h> |
13 | 13 |
14 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
15 #include "base/logging.h" | 15 #include "base/logging.h" |
16 #include "base/process/internal_linux.h" | 16 #include "base/process/internal_linux.h" |
17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
18 #include "base/strings/string_split.h" | 18 #include "base/strings/string_split.h" |
19 #include "base/strings/string_tokenizer.h" | 19 #include "base/strings/string_tokenizer.h" |
20 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
21 #include "base/sys_info.h" | 21 #include "base/sys_info.h" |
22 #include "base/threading/thread_restrictions.h" | 22 #include "base/threading/thread_restrictions.h" |
23 | 23 |
24 namespace base { | 24 namespace base { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 enum ParsingState { | 28 #if defined(OS_CHROMEOS) |
29 KEY_NAME, | |
30 KEY_VALUE | |
31 }; | |
32 | |
33 #ifdef OS_CHROMEOS | |
34 // Read a file with a single number string and return the number as a uint64. | 29 // Read a file with a single number string and return the number as a uint64. |
35 static uint64 ReadFileToUint64(const base::FilePath file) { | 30 static uint64 ReadFileToUint64(const FilePath file) { |
36 std::string file_as_string; | 31 std::string file_as_string; |
37 if (!ReadFileToString(file, &file_as_string)) | 32 if (!ReadFileToString(file, &file_as_string)) |
38 return 0; | 33 return 0; |
39 base::TrimWhitespaceASCII(file_as_string, base::TRIM_ALL, &file_as_string); | 34 TrimWhitespaceASCII(file_as_string, TRIM_ALL, &file_as_string); |
40 uint64 file_as_uint64 = 0; | 35 uint64 file_as_uint64 = 0; |
41 if (!base::StringToUint64(file_as_string, &file_as_uint64)) | 36 if (!StringToUint64(file_as_string, &file_as_uint64)) |
42 return 0; | 37 return 0; |
43 return file_as_uint64; | 38 return file_as_uint64; |
44 } | 39 } |
45 #endif | 40 #endif |
46 | 41 |
47 // Read /proc/<pid>/status and returns the value for |field|, or 0 on failure. | 42 // Read /proc/<pid>/status and return the value for |field|, or 0 on failure. |
48 // Only works for fields in the form of "Field: value kB". | 43 // Only works for fields in the form of "Field: value kB". |
49 size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) { | 44 size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) { |
50 FilePath stat_file = internal::GetProcPidDir(pid).Append("status"); | |
51 std::string status; | 45 std::string status; |
52 { | 46 { |
53 // Synchronously reading files in /proc is safe. | 47 // Synchronously reading files in /proc is safe. |
54 ThreadRestrictions::ScopedAllowIO allow_io; | 48 ThreadRestrictions::ScopedAllowIO allow_io; |
49 FilePath stat_file = internal::GetProcPidDir(pid).Append("status"); | |
55 if (!ReadFileToString(stat_file, &status)) | 50 if (!ReadFileToString(stat_file, &status)) |
56 return 0; | 51 return 0; |
57 } | 52 } |
58 | 53 |
59 StringTokenizer tokenizer(status, ":\n"); | 54 std::vector<std::pair<std::string, std::string> > pairs; |
60 ParsingState state = KEY_NAME; | 55 SplitStringIntoKeyValuePairs(status, ':', '\n', &pairs); |
61 StringPiece last_key_name; | 56 for (size_t i = 0; i < pairs.size(); ++i) { |
62 while (tokenizer.GetNext()) { | 57 std::string key, value_str; |
63 switch (state) { | 58 TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key); |
64 case KEY_NAME: | 59 TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value_str); |
65 last_key_name = tokenizer.token_piece(); | 60 if (key == field) { |
66 state = KEY_VALUE; | 61 std::vector<std::string> split_value_str; |
67 break; | 62 SplitString(value_str, ' ', &split_value_str); |
68 case KEY_VALUE: | 63 if (split_value_str.size() != 2 || split_value_str[1] != "kB") { |
69 DCHECK(!last_key_name.empty()); | 64 NOTREACHED(); |
70 if (last_key_name == field) { | 65 return 0; |
71 std::string value_str; | 66 } |
72 tokenizer.token_piece().CopyToString(&value_str); | 67 size_t value; |
73 std::string value_str_trimmed; | 68 if (!StringToSizeT(split_value_str[0], &value)) { |
74 base::TrimWhitespaceASCII(value_str, base::TRIM_ALL, | 69 NOTREACHED(); |
75 &value_str_trimmed); | 70 return 0; |
76 std::vector<std::string> split_value_str; | 71 } |
77 SplitString(value_str_trimmed, ' ', &split_value_str); | 72 return value; |
78 if (split_value_str.size() != 2 || split_value_str[1] != "kB") { | |
79 NOTREACHED(); | |
80 return 0; | |
81 } | |
82 size_t value; | |
83 if (!StringToSizeT(split_value_str[0], &value)) { | |
84 NOTREACHED(); | |
85 return 0; | |
86 } | |
87 return value; | |
88 } | |
89 state = KEY_NAME; | |
90 break; | |
91 } | 73 } |
92 } | 74 } |
93 NOTREACHED(); | 75 NOTREACHED(); |
94 return 0; | 76 return 0; |
95 } | 77 } |
96 | 78 |
97 // Get the total CPU of a single process. Return value is number of jiffies | 79 // Get the total CPU of a single process. Return value is number of jiffies |
98 // on success or -1 on error. | 80 // on success or -1 on error. |
99 int GetProcessCPU(pid_t pid) { | 81 int GetProcessCPU(pid_t pid) { |
100 // Use /proc/<pid>/task to find all threads and parse their /stat file. | 82 // Use /proc/<pid>/task to find all threads and parse their /stat file. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
216 // in your kernel configuration. | 198 // in your kernel configuration. |
217 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { | 199 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { |
218 // Synchronously reading files in /proc is safe. | 200 // Synchronously reading files in /proc is safe. |
219 ThreadRestrictions::ScopedAllowIO allow_io; | 201 ThreadRestrictions::ScopedAllowIO allow_io; |
220 | 202 |
221 std::string proc_io_contents; | 203 std::string proc_io_contents; |
222 FilePath io_file = internal::GetProcPidDir(process_).Append("io"); | 204 FilePath io_file = internal::GetProcPidDir(process_).Append("io"); |
223 if (!ReadFileToString(io_file, &proc_io_contents)) | 205 if (!ReadFileToString(io_file, &proc_io_contents)) |
224 return false; | 206 return false; |
225 | 207 |
226 (*io_counters).OtherOperationCount = 0; | 208 io_counters->OtherOperationCount = 0; |
227 (*io_counters).OtherTransferCount = 0; | 209 io_counters->OtherTransferCount = 0; |
228 | 210 |
229 StringTokenizer tokenizer(proc_io_contents, ": \n"); | 211 std::vector<std::pair<std::string, std::string> > pairs; |
230 ParsingState state = KEY_NAME; | 212 SplitStringIntoKeyValuePairs(proc_io_contents, ':', '\n', &pairs); |
231 StringPiece last_key_name; | 213 for (size_t i = 0; i < pairs.size(); ++i) { |
232 while (tokenizer.GetNext()) { | 214 std::string key, value_str; |
233 switch (state) { | 215 TrimWhitespaceASCII(pairs[i].first, TRIM_ALL, &key); |
234 case KEY_NAME: | 216 TrimWhitespaceASCII(pairs[i].second, TRIM_ALL, &value_str); |
235 last_key_name = tokenizer.token_piece(); | 217 uint64* target_counter = NULL; |
236 state = KEY_VALUE; | 218 if (key == "syscr") |
237 break; | 219 target_counter = &io_counters->ReadOperationCount; |
238 case KEY_VALUE: | 220 else if (key == "syscw") |
239 DCHECK(!last_key_name.empty()); | 221 target_counter = &io_counters->WriteOperationCount; |
240 if (last_key_name == "syscr") { | 222 else if (key == "rchar") |
241 StringToInt64(tokenizer.token_piece(), | 223 target_counter = &io_counters->ReadTransferCount; |
242 reinterpret_cast<int64*>(&(*io_counters).ReadOperationCount)); | 224 else if (key == "wchar") |
243 } else if (last_key_name == "syscw") { | 225 target_counter = &io_counters->WriteTransferCount; |
244 StringToInt64(tokenizer.token_piece(), | 226 if (!target_counter) |
245 reinterpret_cast<int64*>(&(*io_counters).WriteOperationCount)); | 227 continue; |
246 } else if (last_key_name == "rchar") { | 228 bool converted = StringToUint64(value_str, target_counter); |
247 StringToInt64(tokenizer.token_piece(), | 229 DCHECK(converted); |
248 reinterpret_cast<int64*>(&(*io_counters).ReadTransferCount)); | |
249 } else if (last_key_name == "wchar") { | |
250 StringToInt64(tokenizer.token_piece(), | |
251 reinterpret_cast<int64*>(&(*io_counters).WriteTransferCount)); | |
252 } | |
253 state = KEY_NAME; | |
254 break; | |
255 } | |
256 } | 230 } |
257 return true; | 231 return true; |
258 } | 232 } |
259 | 233 |
260 ProcessMetrics::ProcessMetrics(ProcessHandle process) | 234 ProcessMetrics::ProcessMetrics(ProcessHandle process) |
261 : process_(process), | 235 : process_(process), |
262 last_system_time_(0), | 236 last_system_time_(0), |
263 last_cpu_(0) { | 237 last_cpu_(0) { |
264 processor_count_ = base::SysInfo::NumberOfProcessors(); | 238 processor_count_ = SysInfo::NumberOfProcessors(); |
265 } | 239 } |
266 | 240 |
267 #if defined(OS_CHROMEOS) | 241 #if defined(OS_CHROMEOS) |
268 // Private, Shared and Proportional working set sizes are obtained from | 242 // Private, Shared and Proportional working set sizes are obtained from |
269 // /proc/<pid>/totmaps | 243 // /proc/<pid>/totmaps |
270 bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) | 244 bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) |
271 const { | 245 const { |
272 // The format of /proc/<pid>/totmaps is: | 246 // The format of /proc/<pid>/totmaps is: |
273 // | 247 // |
274 // Rss: 6120 kB | 248 // Rss: 6120 kB |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
473 | 447 |
474 #ifdef OS_CHROMEOS | 448 #ifdef OS_CHROMEOS |
475 shmem = 0; | 449 shmem = 0; |
476 slab = 0; | 450 slab = 0; |
477 gem_objects = -1; | 451 gem_objects = -1; |
478 gem_size = -1; | 452 gem_size = -1; |
479 #endif | 453 #endif |
480 } | 454 } |
481 | 455 |
482 scoped_ptr<Value> SystemMemoryInfoKB::ToValue() const { | 456 scoped_ptr<Value> SystemMemoryInfoKB::ToValue() const { |
483 scoped_ptr<DictionaryValue> res(new base::DictionaryValue()); | 457 scoped_ptr<DictionaryValue> res(new DictionaryValue()); |
484 | 458 |
485 res->SetInteger("total", total); | 459 res->SetInteger("total", total); |
486 res->SetInteger("free", free); | 460 res->SetInteger("free", free); |
487 res->SetInteger("buffers", buffers); | 461 res->SetInteger("buffers", buffers); |
488 res->SetInteger("cached", cached); | 462 res->SetInteger("cached", cached); |
489 res->SetInteger("active_anon", active_anon); | 463 res->SetInteger("active_anon", active_anon); |
490 res->SetInteger("inactive_anon", inactive_anon); | 464 res->SetInteger("inactive_anon", inactive_anon); |
491 res->SetInteger("active_file", active_file); | 465 res->SetInteger("active_file", active_file); |
492 res->SetInteger("inactive_file", inactive_file); | 466 res->SetInteger("inactive_file", inactive_file); |
493 res->SetInteger("swap_total", swap_total); | 467 res->SetInteger("swap_total", swap_total); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
525 meminfo->total = 0; | 499 meminfo->total = 0; |
526 | 500 |
527 std::vector<std::string> meminfo_lines; | 501 std::vector<std::string> meminfo_lines; |
528 Tokenize(meminfo_data, "\n", &meminfo_lines); | 502 Tokenize(meminfo_data, "\n", &meminfo_lines); |
529 for (std::vector<std::string>::iterator it = meminfo_lines.begin(); | 503 for (std::vector<std::string>::iterator it = meminfo_lines.begin(); |
530 it != meminfo_lines.end(); ++it) { | 504 it != meminfo_lines.end(); ++it) { |
531 std::vector<std::string> tokens; | 505 std::vector<std::string> tokens; |
532 SplitStringAlongWhitespace(*it, &tokens); | 506 SplitStringAlongWhitespace(*it, &tokens); |
533 // HugePages_* only has a number and no suffix so we can't rely on | 507 // HugePages_* only has a number and no suffix so we can't rely on |
534 // there being exactly 3 tokens. | 508 // there being exactly 3 tokens. |
535 if (tokens.size() > 1) { | 509 if (tokens.size() <= 1) { |
536 if (tokens[0] == "MemTotal:") { | |
537 StringToInt(tokens[1], &meminfo->total); | |
538 continue; | |
539 } if (tokens[0] == "MemFree:") { | |
540 StringToInt(tokens[1], &meminfo->free); | |
541 continue; | |
542 } if (tokens[0] == "Buffers:") { | |
543 StringToInt(tokens[1], &meminfo->buffers); | |
544 continue; | |
545 } if (tokens[0] == "Cached:") { | |
546 StringToInt(tokens[1], &meminfo->cached); | |
547 continue; | |
548 } if (tokens[0] == "Active(anon):") { | |
549 StringToInt(tokens[1], &meminfo->active_anon); | |
550 continue; | |
551 } if (tokens[0] == "Inactive(anon):") { | |
552 StringToInt(tokens[1], &meminfo->inactive_anon); | |
553 continue; | |
554 } if (tokens[0] == "Active(file):") { | |
555 StringToInt(tokens[1], &meminfo->active_file); | |
556 continue; | |
557 } if (tokens[0] == "Inactive(file):") { | |
558 StringToInt(tokens[1], &meminfo->inactive_file); | |
559 continue; | |
560 } if (tokens[0] == "SwapTotal:") { | |
561 StringToInt(tokens[1], &meminfo->swap_total); | |
562 continue; | |
563 } if (tokens[0] == "SwapFree:") { | |
564 StringToInt(tokens[1], &meminfo->swap_free); | |
565 continue; | |
566 } if (tokens[0] == "Dirty:") { | |
567 StringToInt(tokens[1], &meminfo->dirty); | |
568 continue; | |
569 #if defined(OS_CHROMEOS) | |
570 // Chrome OS has a tweaked kernel that allows us to query Shmem, which is | |
571 // usually video memory otherwise invisible to the OS. | |
572 } if (tokens[0] == "Shmem:") { | |
573 StringToInt(tokens[1], &meminfo->shmem); | |
574 continue; | |
575 } if (tokens[0] == "Slab:") { | |
576 StringToInt(tokens[1], &meminfo->slab); | |
577 continue; | |
578 #endif | |
579 } | |
580 } else | |
581 DLOG(WARNING) << "meminfo: tokens: " << tokens.size() | 510 DLOG(WARNING) << "meminfo: tokens: " << tokens.size() |
582 << " malformed line: " << *it; | 511 << " malformed line: " << *it; |
512 continue; | |
513 } | |
514 | |
515 int* target = NULL; | |
516 if (tokens[0] == "MemTotal:") | |
517 target = &meminfo->total; | |
518 else if (tokens[0] == "MemFree:") | |
519 target = &meminfo->free; | |
520 else if (tokens[0] == "Buffers:") | |
521 target = &meminfo->buffers; | |
522 else if (tokens[0] == "Cached:") | |
523 target = &meminfo->cached; | |
524 else if (tokens[0] == "Active(anon):") | |
525 target = &meminfo->active_anon; | |
526 else if (tokens[0] == "Inactive(anon):") | |
527 target = &meminfo->inactive_anon; | |
528 else if (tokens[0] == "Active(file):") | |
529 target = &meminfo->active_file; | |
530 else if (tokens[0] == "Inactive(file):") | |
531 target = &meminfo->inactive_file; | |
532 else if (tokens[0] == "SwapTotal:") | |
533 target = &meminfo->swap_total; | |
534 else if (tokens[0] == "SwapFree:") | |
535 target = &meminfo->swap_free; | |
536 else if (tokens[0] == "Dirty:") | |
537 target = &meminfo->dirty; | |
538 #if defined(OS_CHROMEOS) | |
539 // Chrome OS has a tweaked kernel that allows us to query Shmem, which is | |
540 // usually video memory otherwise invisible to the OS. | |
541 else if (tokens[0] == "Shmem:") | |
542 target = &meminfo->shmem; | |
543 else if (tokens[0] == "Slab:") | |
544 target = &meminfo->slab; | |
545 #endif | |
546 if (target) | |
547 StringToInt(tokens[1], target); | |
583 } | 548 } |
584 | 549 |
585 // Make sure we got a valid MemTotal. | 550 // Make sure we got a valid MemTotal. |
586 if (!meminfo->total) | 551 return meminfo->total > 0; |
587 return false; | |
588 | |
589 return true; | |
590 } | 552 } |
591 | 553 |
592 // exposed for testing | 554 // exposed for testing |
593 bool ParseProcVmstat(const std::string& vmstat_data, | 555 bool ParseProcVmstat(const std::string& vmstat_data, |
594 SystemMemoryInfoKB* meminfo) { | 556 SystemMemoryInfoKB* meminfo) { |
595 // The format of /proc/vmstat is: | 557 // The format of /proc/vmstat is: |
596 // | 558 // |
597 // nr_free_pages 299878 | 559 // nr_free_pages 299878 |
598 // nr_inactive_anon 239863 | 560 // nr_inactive_anon 239863 |
599 // nr_active_anon 1318966 | 561 // nr_active_anon 1318966 |
600 // nr_inactive_file 2015629 | 562 // nr_inactive_file 2015629 |
601 // ... | 563 // ... |
602 // | 564 // |
603 // We iterate through the whole file because the position of the | 565 // We iterate through the whole file because the position of the |
604 // fields are dependent on the kernel version and configuration. | 566 // fields are dependent on the kernel version and configuration. |
605 | 567 |
606 std::vector<std::string> vmstat_lines; | 568 std::vector<std::string> vmstat_lines; |
607 Tokenize(vmstat_data, "\n", &vmstat_lines); | 569 Tokenize(vmstat_data, "\n", &vmstat_lines); |
608 for (std::vector<std::string>::iterator it = vmstat_lines.begin(); | 570 for (std::vector<std::string>::iterator it = vmstat_lines.begin(); |
609 it != vmstat_lines.end(); ++it) { | 571 it != vmstat_lines.end(); ++it) { |
610 std::vector<std::string> tokens; | 572 std::vector<std::string> tokens; |
611 SplitString(*it, ' ', &tokens); | 573 SplitString(*it, ' ', &tokens); |
612 if (tokens.size() == 2) { | 574 if (tokens.size() != 2) |
613 if (tokens[0] == "pswpin") { | 575 continue; |
614 StringToInt(tokens[1], &meminfo->pswpin); | 576 |
615 continue; | 577 if (tokens[0] == "pswpin") { |
616 } if (tokens[0] == "pswpout") { | 578 StringToInt(tokens[1], &meminfo->pswpin); |
617 StringToInt(tokens[1], &meminfo->pswpout); | 579 } else if (tokens[0] == "pswpout") { |
618 continue; | 580 StringToInt(tokens[1], &meminfo->pswpout); |
619 } if (tokens[0] == "pgmajfault") | 581 } else if (tokens[0] == "pgmajfault") { |
620 StringToInt(tokens[1], &meminfo->pgmajfault); | 582 StringToInt(tokens[1], &meminfo->pgmajfault); |
621 } | 583 } |
622 } | 584 } |
623 | 585 |
624 return true; | 586 return true; |
625 } | 587 } |
626 | 588 |
627 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { | 589 bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) { |
628 // Synchronously reading files in /proc is safe. | 590 // Synchronously reading files in /proc and /sys are safe. |
629 ThreadRestrictions::ScopedAllowIO allow_io; | 591 ThreadRestrictions::ScopedAllowIO allow_io; |
630 | 592 |
631 // Used memory is: total - free - buffers - caches | 593 // Used memory is: total - free - buffers - caches |
632 FilePath meminfo_file("/proc/meminfo"); | 594 FilePath meminfo_file("/proc/meminfo"); |
633 std::string meminfo_data; | 595 std::string meminfo_data; |
634 if (!ReadFileToString(meminfo_file, &meminfo_data)) { | 596 if (!ReadFileToString(meminfo_file, &meminfo_data)) { |
635 DLOG(WARNING) << "Failed to open " << meminfo_file.value(); | 597 DLOG(WARNING) << "Failed to open " << meminfo_file.value(); |
636 return false; | 598 return false; |
637 } | 599 } |
638 | 600 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
700 writes = 0; | 662 writes = 0; |
701 writes_merged = 0; | 663 writes_merged = 0; |
702 sectors_written = 0; | 664 sectors_written = 0; |
703 write_time = 0; | 665 write_time = 0; |
704 io = 0; | 666 io = 0; |
705 io_time = 0; | 667 io_time = 0; |
706 weighted_io_time = 0; | 668 weighted_io_time = 0; |
707 } | 669 } |
708 | 670 |
709 scoped_ptr<Value> SystemDiskInfo::ToValue() const { | 671 scoped_ptr<Value> SystemDiskInfo::ToValue() const { |
710 scoped_ptr<DictionaryValue> res(new base::DictionaryValue()); | 672 scoped_ptr<DictionaryValue> res(new DictionaryValue()); |
711 | 673 |
712 // Write out uint64 variables as doubles. | 674 // Write out uint64 variables as doubles. |
713 // Note: this may discard some precision, but for JS there's no other option. | 675 // Note: this may discard some precision, but for JS there's no other option. |
714 res->SetDouble("reads", static_cast<double>(reads)); | 676 res->SetDouble("reads", static_cast<double>(reads)); |
715 res->SetDouble("reads_merged", static_cast<double>(reads_merged)); | 677 res->SetDouble("reads_merged", static_cast<double>(reads_merged)); |
716 res->SetDouble("sectors_read", static_cast<double>(sectors_read)); | 678 res->SetDouble("sectors_read", static_cast<double>(sectors_read)); |
717 res->SetDouble("read_time", static_cast<double>(read_time)); | 679 res->SetDouble("read_time", static_cast<double>(read_time)); |
718 res->SetDouble("writes", static_cast<double>(writes)); | 680 res->SetDouble("writes", static_cast<double>(writes)); |
719 res->SetDouble("writes_merged", static_cast<double>(writes_merged)); | 681 res->SetDouble("writes_merged", static_cast<double>(writes_merged)); |
720 res->SetDouble("sectors_written", static_cast<double>(sectors_written)); | 682 res->SetDouble("sectors_written", static_cast<double>(sectors_written)); |
721 res->SetDouble("write_time", static_cast<double>(write_time)); | 683 res->SetDouble("write_time", static_cast<double>(write_time)); |
722 res->SetDouble("io", static_cast<double>(io)); | 684 res->SetDouble("io", static_cast<double>(io)); |
723 res->SetDouble("io_time", static_cast<double>(io_time)); | 685 res->SetDouble("io_time", static_cast<double>(io_time)); |
724 res->SetDouble("weighted_io_time", static_cast<double>(weighted_io_time)); | 686 res->SetDouble("weighted_io_time", static_cast<double>(weighted_io_time)); |
725 | 687 |
726 return res.PassAs<Value>(); | 688 return res.PassAs<Value>(); |
727 } | 689 } |
728 | 690 |
729 bool IsValidDiskName(const std::string& candidate) { | 691 bool IsValidDiskName(const std::string& candidate) { |
730 if (candidate.length() < 3) | 692 if (candidate.length() < 3) |
731 return false; | 693 return false; |
732 if (candidate.substr(0,2) == "sd" || candidate.substr(0,2) == "hd") { | 694 if (candidate[1] == 'd' && |
733 // [sh]d[a-z]+ case | 695 (candidate[0] == 'h' || candidate[0] == 's' || candidate[0] == 'v')) { |
734 for (size_t i = 2; i < candidate.length(); i++) { | 696 // [hsv]d[a-z]+ case |
Lei Zhang
2014/09/06 09:31:58
vd* are virtual disks
| |
697 for (size_t i = 2; i < candidate.length(); ++i) { | |
735 if (!islower(candidate[i])) | 698 if (!islower(candidate[i])) |
736 return false; | 699 return false; |
737 } | 700 } |
738 } else { | 701 return true; |
739 if (candidate.length() < 7) { | |
740 return false; | |
741 } | |
742 if (candidate.substr(0,6) == "mmcblk") { | |
743 // mmcblk[0-9]+ case | |
744 for (size_t i = 6; i < candidate.length(); i++) { | |
745 if (!isdigit(candidate[i])) | |
746 return false; | |
747 } | |
748 } else { | |
749 return false; | |
750 } | |
751 } | 702 } |
752 | 703 |
704 const char kMMCName[] = "mmcblk"; | |
705 const size_t kMMCNameLen = strlen(kMMCName); | |
706 if (candidate.length() < kMMCNameLen + 1) | |
707 return false; | |
708 if (candidate.compare(0, kMMCNameLen, kMMCName) != 0) | |
709 return false; | |
710 | |
711 // mmcblk[0-9]+ case | |
712 for (size_t i = kMMCNameLen; i < candidate.length(); ++i) { | |
713 if (!isdigit(candidate[i])) | |
714 return false; | |
715 } | |
753 return true; | 716 return true; |
754 } | 717 } |
755 | 718 |
756 bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) { | 719 bool GetSystemDiskInfo(SystemDiskInfo* diskinfo) { |
757 // Synchronously reading files in /proc is safe. | 720 // Synchronously reading files in /proc is safe. |
758 ThreadRestrictions::ScopedAllowIO allow_io; | 721 ThreadRestrictions::ScopedAllowIO allow_io; |
759 | 722 |
760 FilePath diskinfo_file("/proc/diskstats"); | 723 FilePath diskinfo_file("/proc/diskstats"); |
761 std::string diskinfo_data; | 724 std::string diskinfo_data; |
762 if (!ReadFileToString(diskinfo_file, &diskinfo_data)) { | 725 if (!ReadFileToString(diskinfo_file, &diskinfo_data)) { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
847 else | 810 else |
848 res->SetDouble("compression_ratio", 0); | 811 res->SetDouble("compression_ratio", 0); |
849 | 812 |
850 return res.PassAs<Value>(); | 813 return res.PassAs<Value>(); |
851 } | 814 } |
852 | 815 |
853 void GetSwapInfo(SwapInfo* swap_info) { | 816 void GetSwapInfo(SwapInfo* swap_info) { |
854 // Synchronously reading files in /sys/block/zram0 is safe. | 817 // Synchronously reading files in /sys/block/zram0 is safe. |
855 ThreadRestrictions::ScopedAllowIO allow_io; | 818 ThreadRestrictions::ScopedAllowIO allow_io; |
856 | 819 |
857 base::FilePath zram_path("/sys/block/zram0"); | 820 FilePath zram_path("/sys/block/zram0"); |
858 uint64 orig_data_size = ReadFileToUint64(zram_path.Append("orig_data_size")); | 821 uint64 orig_data_size = ReadFileToUint64(zram_path.Append("orig_data_size")); |
859 if (orig_data_size <= 4096) { | 822 if (orig_data_size <= 4096) { |
860 // A single page is compressed at startup, and has a high compression | 823 // A single page is compressed at startup, and has a high compression |
861 // ratio. We ignore this as it doesn't indicate any real swapping. | 824 // ratio. We ignore this as it doesn't indicate any real swapping. |
862 swap_info->orig_data_size = 0; | 825 swap_info->orig_data_size = 0; |
863 swap_info->num_reads = 0; | 826 swap_info->num_reads = 0; |
864 swap_info->num_writes = 0; | 827 swap_info->num_writes = 0; |
865 swap_info->compr_data_size = 0; | 828 swap_info->compr_data_size = 0; |
866 swap_info->mem_used_total = 0; | 829 swap_info->mem_used_total = 0; |
867 return; | 830 return; |
868 } | 831 } |
869 swap_info->orig_data_size = orig_data_size; | 832 swap_info->orig_data_size = orig_data_size; |
870 swap_info->num_reads = ReadFileToUint64(zram_path.Append("num_reads")); | 833 swap_info->num_reads = ReadFileToUint64(zram_path.Append("num_reads")); |
871 swap_info->num_writes = ReadFileToUint64(zram_path.Append("num_writes")); | 834 swap_info->num_writes = ReadFileToUint64(zram_path.Append("num_writes")); |
872 swap_info->compr_data_size = | 835 swap_info->compr_data_size = |
873 ReadFileToUint64(zram_path.Append("compr_data_size")); | 836 ReadFileToUint64(zram_path.Append("compr_data_size")); |
874 swap_info->mem_used_total = | 837 swap_info->mem_used_total = |
875 ReadFileToUint64(zram_path.Append("mem_used_total")); | 838 ReadFileToUint64(zram_path.Append("mem_used_total")); |
876 } | 839 } |
877 #endif // defined(OS_CHROMEOS) | 840 #endif // defined(OS_CHROMEOS) |
878 | 841 |
879 } // namespace base | 842 } // namespace base |
OLD | NEW |