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 <stddef.h> |
| 10 #include <stdint.h> |
9 #include <sys/stat.h> | 11 #include <sys/stat.h> |
10 #include <sys/time.h> | 12 #include <sys/time.h> |
11 #include <sys/types.h> | 13 #include <sys/types.h> |
12 #include <unistd.h> | 14 #include <unistd.h> |
13 #include <utility> | 15 #include <utility> |
14 | 16 |
15 #include "base/files/dir_reader_posix.h" | 17 #include "base/files/dir_reader_posix.h" |
16 #include "base/files/file_util.h" | 18 #include "base/files/file_util.h" |
17 #include "base/logging.h" | 19 #include "base/logging.h" |
18 #include "base/process/internal_linux.h" | 20 #include "base/process/internal_linux.h" |
19 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/string_split.h" | 22 #include "base/strings/string_split.h" |
21 #include "base/strings/string_tokenizer.h" | 23 #include "base/strings/string_tokenizer.h" |
22 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
23 #include "base/sys_info.h" | 25 #include "base/sys_info.h" |
24 #include "base/threading/thread_restrictions.h" | 26 #include "base/threading/thread_restrictions.h" |
| 27 #include "build/build_config.h" |
25 | 28 |
26 namespace base { | 29 namespace base { |
27 | 30 |
28 namespace { | 31 namespace { |
29 | 32 |
30 void TrimKeyValuePairs(StringPairs* pairs) { | 33 void TrimKeyValuePairs(StringPairs* pairs) { |
31 DCHECK(pairs); | 34 DCHECK(pairs); |
32 StringPairs& p_ref = *pairs; | 35 StringPairs& p_ref = *pairs; |
33 for (size_t i = 0; i < p_ref.size(); ++i) { | 36 for (size_t i = 0; i < p_ref.size(); ++i) { |
34 TrimWhitespaceASCII(p_ref[i].first, TRIM_ALL, &p_ref[i].first); | 37 TrimWhitespaceASCII(p_ref[i].first, TRIM_ALL, &p_ref[i].first); |
35 TrimWhitespaceASCII(p_ref[i].second, TRIM_ALL, &p_ref[i].second); | 38 TrimWhitespaceASCII(p_ref[i].second, TRIM_ALL, &p_ref[i].second); |
36 } | 39 } |
37 } | 40 } |
38 | 41 |
39 #if defined(OS_CHROMEOS) | 42 #if defined(OS_CHROMEOS) |
40 // Read a file with a single number string and return the number as a uint64. | 43 // Read a file with a single number string and return the number as a uint64_t. |
41 static uint64 ReadFileToUint64(const FilePath file) { | 44 static uint64_t ReadFileToUint64(const FilePath file) { |
42 std::string file_as_string; | 45 std::string file_as_string; |
43 if (!ReadFileToString(file, &file_as_string)) | 46 if (!ReadFileToString(file, &file_as_string)) |
44 return 0; | 47 return 0; |
45 TrimWhitespaceASCII(file_as_string, TRIM_ALL, &file_as_string); | 48 TrimWhitespaceASCII(file_as_string, TRIM_ALL, &file_as_string); |
46 uint64 file_as_uint64 = 0; | 49 uint64_t file_as_uint64 = 0; |
47 if (!StringToUint64(file_as_string, &file_as_uint64)) | 50 if (!StringToUint64(file_as_string, &file_as_uint64)) |
48 return 0; | 51 return 0; |
49 return file_as_uint64; | 52 return file_as_uint64; |
50 } | 53 } |
51 #endif | 54 #endif |
52 | 55 |
53 // Read /proc/<pid>/status and return the value for |field|, or 0 on failure. | 56 // Read /proc/<pid>/status and return the value for |field|, or 0 on failure. |
54 // Only works for fields in the form of "Field: value kB". | 57 // Only works for fields in the form of "Field: value kB". |
55 size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) { | 58 size_t ReadProcStatusAndGetFieldAsSizeT(pid_t pid, const std::string& field) { |
56 std::string status; | 59 std::string status; |
(...skipping 29 matching lines...) Expand all Loading... |
86 NOTREACHED(); | 89 NOTREACHED(); |
87 return 0; | 90 return 0; |
88 } | 91 } |
89 | 92 |
90 #if defined(OS_LINUX) | 93 #if defined(OS_LINUX) |
91 // Read /proc/<pid>/sched and look for |field|. On succes, return true and | 94 // Read /proc/<pid>/sched and look for |field|. On succes, return true and |
92 // write the value for |field| into |result|. | 95 // write the value for |field| into |result|. |
93 // Only works for fields in the form of "field : uint_value" | 96 // Only works for fields in the form of "field : uint_value" |
94 bool ReadProcSchedAndGetFieldAsUint64(pid_t pid, | 97 bool ReadProcSchedAndGetFieldAsUint64(pid_t pid, |
95 const std::string& field, | 98 const std::string& field, |
96 uint64* result) { | 99 uint64_t* result) { |
97 std::string sched_data; | 100 std::string sched_data; |
98 { | 101 { |
99 // Synchronously reading files in /proc does not hit the disk. | 102 // Synchronously reading files in /proc does not hit the disk. |
100 ThreadRestrictions::ScopedAllowIO allow_io; | 103 ThreadRestrictions::ScopedAllowIO allow_io; |
101 FilePath sched_file = internal::GetProcPidDir(pid).Append("sched"); | 104 FilePath sched_file = internal::GetProcPidDir(pid).Append("sched"); |
102 if (!ReadFileToString(sched_file, &sched_data)) | 105 if (!ReadFileToString(sched_file, &sched_data)) |
103 return false; | 106 return false; |
104 } | 107 } |
105 | 108 |
106 StringPairs pairs; | 109 StringPairs pairs; |
107 SplitStringIntoKeyValuePairs(sched_data, ':', '\n', &pairs); | 110 SplitStringIntoKeyValuePairs(sched_data, ':', '\n', &pairs); |
108 TrimKeyValuePairs(&pairs); | 111 TrimKeyValuePairs(&pairs); |
109 for (size_t i = 0; i < pairs.size(); ++i) { | 112 for (size_t i = 0; i < pairs.size(); ++i) { |
110 const std::string& key = pairs[i].first; | 113 const std::string& key = pairs[i].first; |
111 const std::string& value_str = pairs[i].second; | 114 const std::string& value_str = pairs[i].second; |
112 if (key == field) { | 115 if (key == field) { |
113 uint64 value; | 116 uint64_t value; |
114 if (!StringToUint64(value_str, &value)) | 117 if (!StringToUint64(value_str, &value)) |
115 return false; | 118 return false; |
116 *result = value; | 119 *result = value; |
117 return true; | 120 return true; |
118 } | 121 } |
119 } | 122 } |
120 return false; | 123 return false; |
121 } | 124 } |
122 #endif // defined(OS_LINUX) | 125 #endif // defined(OS_LINUX) |
123 | 126 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 | 266 |
264 io_counters->OtherOperationCount = 0; | 267 io_counters->OtherOperationCount = 0; |
265 io_counters->OtherTransferCount = 0; | 268 io_counters->OtherTransferCount = 0; |
266 | 269 |
267 StringPairs pairs; | 270 StringPairs pairs; |
268 SplitStringIntoKeyValuePairs(proc_io_contents, ':', '\n', &pairs); | 271 SplitStringIntoKeyValuePairs(proc_io_contents, ':', '\n', &pairs); |
269 TrimKeyValuePairs(&pairs); | 272 TrimKeyValuePairs(&pairs); |
270 for (size_t i = 0; i < pairs.size(); ++i) { | 273 for (size_t i = 0; i < pairs.size(); ++i) { |
271 const std::string& key = pairs[i].first; | 274 const std::string& key = pairs[i].first; |
272 const std::string& value_str = pairs[i].second; | 275 const std::string& value_str = pairs[i].second; |
273 uint64* target_counter = NULL; | 276 uint64_t* target_counter = NULL; |
274 if (key == "syscr") | 277 if (key == "syscr") |
275 target_counter = &io_counters->ReadOperationCount; | 278 target_counter = &io_counters->ReadOperationCount; |
276 else if (key == "syscw") | 279 else if (key == "syscw") |
277 target_counter = &io_counters->WriteOperationCount; | 280 target_counter = &io_counters->WriteOperationCount; |
278 else if (key == "rchar") | 281 else if (key == "rchar") |
279 target_counter = &io_counters->ReadTransferCount; | 282 target_counter = &io_counters->ReadTransferCount; |
280 else if (key == "wchar") | 283 else if (key == "wchar") |
281 target_counter = &io_counters->WriteTransferCount; | 284 target_counter = &io_counters->WriteTransferCount; |
282 if (!target_counter) | 285 if (!target_counter) |
283 continue; | 286 continue; |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 sectors_written = 0; | 762 sectors_written = 0; |
760 write_time = 0; | 763 write_time = 0; |
761 io = 0; | 764 io = 0; |
762 io_time = 0; | 765 io_time = 0; |
763 weighted_io_time = 0; | 766 weighted_io_time = 0; |
764 } | 767 } |
765 | 768 |
766 scoped_ptr<Value> SystemDiskInfo::ToValue() const { | 769 scoped_ptr<Value> SystemDiskInfo::ToValue() const { |
767 scoped_ptr<DictionaryValue> res(new DictionaryValue()); | 770 scoped_ptr<DictionaryValue> res(new DictionaryValue()); |
768 | 771 |
769 // Write out uint64 variables as doubles. | 772 // Write out uint64_t variables as doubles. |
770 // Note: this may discard some precision, but for JS there's no other option. | 773 // Note: this may discard some precision, but for JS there's no other option. |
771 res->SetDouble("reads", static_cast<double>(reads)); | 774 res->SetDouble("reads", static_cast<double>(reads)); |
772 res->SetDouble("reads_merged", static_cast<double>(reads_merged)); | 775 res->SetDouble("reads_merged", static_cast<double>(reads_merged)); |
773 res->SetDouble("sectors_read", static_cast<double>(sectors_read)); | 776 res->SetDouble("sectors_read", static_cast<double>(sectors_read)); |
774 res->SetDouble("read_time", static_cast<double>(read_time)); | 777 res->SetDouble("read_time", static_cast<double>(read_time)); |
775 res->SetDouble("writes", static_cast<double>(writes)); | 778 res->SetDouble("writes", static_cast<double>(writes)); |
776 res->SetDouble("writes_merged", static_cast<double>(writes_merged)); | 779 res->SetDouble("writes_merged", static_cast<double>(writes_merged)); |
777 res->SetDouble("sectors_written", static_cast<double>(sectors_written)); | 780 res->SetDouble("sectors_written", static_cast<double>(sectors_written)); |
778 res->SetDouble("write_time", static_cast<double>(write_time)); | 781 res->SetDouble("write_time", static_cast<double>(write_time)); |
779 res->SetDouble("io", static_cast<double>(io)); | 782 res->SetDouble("io", static_cast<double>(io)); |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 diskinfo->sectors_read = 0; | 837 diskinfo->sectors_read = 0; |
835 diskinfo->read_time = 0; | 838 diskinfo->read_time = 0; |
836 diskinfo->writes = 0; | 839 diskinfo->writes = 0; |
837 diskinfo->writes_merged = 0; | 840 diskinfo->writes_merged = 0; |
838 diskinfo->sectors_written = 0; | 841 diskinfo->sectors_written = 0; |
839 diskinfo->write_time = 0; | 842 diskinfo->write_time = 0; |
840 diskinfo->io = 0; | 843 diskinfo->io = 0; |
841 diskinfo->io_time = 0; | 844 diskinfo->io_time = 0; |
842 diskinfo->weighted_io_time = 0; | 845 diskinfo->weighted_io_time = 0; |
843 | 846 |
844 uint64 reads = 0; | 847 uint64_t reads = 0; |
845 uint64 reads_merged = 0; | 848 uint64_t reads_merged = 0; |
846 uint64 sectors_read = 0; | 849 uint64_t sectors_read = 0; |
847 uint64 read_time = 0; | 850 uint64_t read_time = 0; |
848 uint64 writes = 0; | 851 uint64_t writes = 0; |
849 uint64 writes_merged = 0; | 852 uint64_t writes_merged = 0; |
850 uint64 sectors_written = 0; | 853 uint64_t sectors_written = 0; |
851 uint64 write_time = 0; | 854 uint64_t write_time = 0; |
852 uint64 io = 0; | 855 uint64_t io = 0; |
853 uint64 io_time = 0; | 856 uint64_t io_time = 0; |
854 uint64 weighted_io_time = 0; | 857 uint64_t weighted_io_time = 0; |
855 | 858 |
856 for (const StringPiece& line : diskinfo_lines) { | 859 for (const StringPiece& line : diskinfo_lines) { |
857 std::vector<StringPiece> disk_fields = SplitStringPiece( | 860 std::vector<StringPiece> disk_fields = SplitStringPiece( |
858 line, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); | 861 line, kWhitespaceASCII, TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY); |
859 | 862 |
860 // Fields may have overflowed and reset to zero. | 863 // Fields may have overflowed and reset to zero. |
861 if (IsValidDiskName(disk_fields[kDiskDriveName].as_string())) { | 864 if (IsValidDiskName(disk_fields[kDiskDriveName].as_string())) { |
862 StringToUint64(disk_fields[kDiskReads], &reads); | 865 StringToUint64(disk_fields[kDiskReads], &reads); |
863 StringToUint64(disk_fields[kDiskReadsMerged], &reads_merged); | 866 StringToUint64(disk_fields[kDiskReadsMerged], &reads_merged); |
864 StringToUint64(disk_fields[kDiskSectorsRead], §ors_read); | 867 StringToUint64(disk_fields[kDiskSectorsRead], §ors_read); |
(...skipping 20 matching lines...) Expand all Loading... |
885 } | 888 } |
886 } | 889 } |
887 | 890 |
888 return true; | 891 return true; |
889 } | 892 } |
890 | 893 |
891 #if defined(OS_CHROMEOS) | 894 #if defined(OS_CHROMEOS) |
892 scoped_ptr<Value> SwapInfo::ToValue() const { | 895 scoped_ptr<Value> SwapInfo::ToValue() const { |
893 scoped_ptr<DictionaryValue> res(new DictionaryValue()); | 896 scoped_ptr<DictionaryValue> res(new DictionaryValue()); |
894 | 897 |
895 // Write out uint64 variables as doubles. | 898 // Write out uint64_t variables as doubles. |
896 // Note: this may discard some precision, but for JS there's no other option. | 899 // Note: this may discard some precision, but for JS there's no other option. |
897 res->SetDouble("num_reads", static_cast<double>(num_reads)); | 900 res->SetDouble("num_reads", static_cast<double>(num_reads)); |
898 res->SetDouble("num_writes", static_cast<double>(num_writes)); | 901 res->SetDouble("num_writes", static_cast<double>(num_writes)); |
899 res->SetDouble("orig_data_size", static_cast<double>(orig_data_size)); | 902 res->SetDouble("orig_data_size", static_cast<double>(orig_data_size)); |
900 res->SetDouble("compr_data_size", static_cast<double>(compr_data_size)); | 903 res->SetDouble("compr_data_size", static_cast<double>(compr_data_size)); |
901 res->SetDouble("mem_used_total", static_cast<double>(mem_used_total)); | 904 res->SetDouble("mem_used_total", static_cast<double>(mem_used_total)); |
902 if (compr_data_size > 0) | 905 if (compr_data_size > 0) |
903 res->SetDouble("compression_ratio", static_cast<double>(orig_data_size) / | 906 res->SetDouble("compression_ratio", static_cast<double>(orig_data_size) / |
904 static_cast<double>(compr_data_size)); | 907 static_cast<double>(compr_data_size)); |
905 else | 908 else |
906 res->SetDouble("compression_ratio", 0); | 909 res->SetDouble("compression_ratio", 0); |
907 | 910 |
908 return std::move(res); | 911 return std::move(res); |
909 } | 912 } |
910 | 913 |
911 void GetSwapInfo(SwapInfo* swap_info) { | 914 void GetSwapInfo(SwapInfo* swap_info) { |
912 // Synchronously reading files in /sys/block/zram0 does not hit the disk. | 915 // Synchronously reading files in /sys/block/zram0 does not hit the disk. |
913 ThreadRestrictions::ScopedAllowIO allow_io; | 916 ThreadRestrictions::ScopedAllowIO allow_io; |
914 | 917 |
915 FilePath zram_path("/sys/block/zram0"); | 918 FilePath zram_path("/sys/block/zram0"); |
916 uint64 orig_data_size = ReadFileToUint64(zram_path.Append("orig_data_size")); | 919 uint64_t orig_data_size = |
| 920 ReadFileToUint64(zram_path.Append("orig_data_size")); |
917 if (orig_data_size <= 4096) { | 921 if (orig_data_size <= 4096) { |
918 // A single page is compressed at startup, and has a high compression | 922 // A single page is compressed at startup, and has a high compression |
919 // ratio. We ignore this as it doesn't indicate any real swapping. | 923 // ratio. We ignore this as it doesn't indicate any real swapping. |
920 swap_info->orig_data_size = 0; | 924 swap_info->orig_data_size = 0; |
921 swap_info->num_reads = 0; | 925 swap_info->num_reads = 0; |
922 swap_info->num_writes = 0; | 926 swap_info->num_writes = 0; |
923 swap_info->compr_data_size = 0; | 927 swap_info->compr_data_size = 0; |
924 swap_info->mem_used_total = 0; | 928 swap_info->mem_used_total = 0; |
925 return; | 929 return; |
926 } | 930 } |
927 swap_info->orig_data_size = orig_data_size; | 931 swap_info->orig_data_size = orig_data_size; |
928 swap_info->num_reads = ReadFileToUint64(zram_path.Append("num_reads")); | 932 swap_info->num_reads = ReadFileToUint64(zram_path.Append("num_reads")); |
929 swap_info->num_writes = ReadFileToUint64(zram_path.Append("num_writes")); | 933 swap_info->num_writes = ReadFileToUint64(zram_path.Append("num_writes")); |
930 swap_info->compr_data_size = | 934 swap_info->compr_data_size = |
931 ReadFileToUint64(zram_path.Append("compr_data_size")); | 935 ReadFileToUint64(zram_path.Append("compr_data_size")); |
932 swap_info->mem_used_total = | 936 swap_info->mem_used_total = |
933 ReadFileToUint64(zram_path.Append("mem_used_total")); | 937 ReadFileToUint64(zram_path.Append("mem_used_total")); |
934 } | 938 } |
935 #endif // defined(OS_CHROMEOS) | 939 #endif // defined(OS_CHROMEOS) |
936 | 940 |
937 #if defined(OS_LINUX) | 941 #if defined(OS_LINUX) |
938 int ProcessMetrics::GetIdleWakeupsPerSecond() { | 942 int ProcessMetrics::GetIdleWakeupsPerSecond() { |
939 uint64 wake_ups; | 943 uint64_t wake_ups; |
940 const char kWakeupStat[] = "se.statistics.nr_wakeups"; | 944 const char kWakeupStat[] = "se.statistics.nr_wakeups"; |
941 return ReadProcSchedAndGetFieldAsUint64(process_, kWakeupStat, &wake_ups) ? | 945 return ReadProcSchedAndGetFieldAsUint64(process_, kWakeupStat, &wake_ups) ? |
942 CalculateIdleWakeupsPerSecond(wake_ups) : 0; | 946 CalculateIdleWakeupsPerSecond(wake_ups) : 0; |
943 } | 947 } |
944 #endif // defined(OS_LINUX) | 948 #endif // defined(OS_LINUX) |
945 | 949 |
946 } // namespace base | 950 } // namespace base |
OLD | NEW |