Chromium Code Reviews| 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> | |
| 9 #include <sys/stat.h> | |
| 8 #include <sys/time.h> | 10 #include <sys/time.h> |
| 9 #include <sys/types.h> | 11 #include <sys/types.h> |
| 10 #include <unistd.h> | 12 #include <unistd.h> |
| 11 | 13 |
| 12 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 15 #include "base/files/memory_mapped_file.h" | |
| 13 #include "base/logging.h" | 16 #include "base/logging.h" |
| 14 #include "base/process/internal_linux.h" | 17 #include "base/process/internal_linux.h" |
| 15 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 16 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
| 17 #include "base/strings/string_split.h" | 20 #include "base/strings/string_split.h" |
| 18 #include "base/strings/string_tokenizer.h" | 21 #include "base/strings/string_tokenizer.h" |
| 19 #include "base/sys_info.h" | 22 #include "base/sys_info.h" |
| 20 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
| 21 | 24 |
| 22 namespace base { | 25 namespace base { |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 149 | 152 |
| 150 if (private_bytes) | 153 if (private_bytes) |
| 151 *private_bytes = ws_usage.priv * 1024; | 154 *private_bytes = ws_usage.priv * 1024; |
| 152 | 155 |
| 153 if (shared_bytes) | 156 if (shared_bytes) |
| 154 *shared_bytes = ws_usage.shared * 1024; | 157 *shared_bytes = ws_usage.shared * 1024; |
| 155 | 158 |
| 156 return true; | 159 return true; |
| 157 } | 160 } |
| 158 | 161 |
| 159 // Private and Shared working set sizes are obtained from /proc/<pid>/statm. | |
| 160 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { | 162 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { |
| 161 // Use statm instead of smaps because smaps is: | 163 #if defined(OS_CHROMEOS) |
| 162 // a) Large and slow to parse. | 164 if (GetWorkingSetKBytesTotmaps(ws_usage)) |
| 163 // b) Unavailable in the SUID sandbox. | 165 return true; |
| 164 | 166 #endif |
| 165 // First we need to get the page size, since everything is measured in pages. | 167 return GetWorkingSetKBytesStatm(ws_usage); |
| 166 // For details, see: man 5 proc. | |
| 167 const int page_size_kb = getpagesize() / 1024; | |
| 168 if (page_size_kb <= 0) | |
| 169 return false; | |
| 170 | |
| 171 std::string statm; | |
| 172 { | |
| 173 FilePath statm_file = internal::GetProcPidDir(process_).Append("statm"); | |
| 174 // Synchronously reading files in /proc is safe. | |
| 175 ThreadRestrictions::ScopedAllowIO allow_io; | |
| 176 bool ret = file_util::ReadFileToString(statm_file, &statm); | |
| 177 if (!ret || statm.length() == 0) | |
| 178 return false; | |
| 179 } | |
| 180 | |
| 181 std::vector<std::string> statm_vec; | |
| 182 SplitString(statm, ' ', &statm_vec); | |
| 183 if (statm_vec.size() != 7) | |
| 184 return false; // Not the format we expect. | |
| 185 | |
| 186 int statm_rss, statm_shared; | |
| 187 StringToInt(statm_vec[1], &statm_rss); | |
| 188 StringToInt(statm_vec[2], &statm_shared); | |
| 189 | |
| 190 ws_usage->priv = (statm_rss - statm_shared) * page_size_kb; | |
| 191 ws_usage->shared = statm_shared * page_size_kb; | |
| 192 | |
| 193 // Sharable is not calculated, as it does not provide interesting data. | |
| 194 ws_usage->shareable = 0; | |
| 195 | |
| 196 return true; | |
| 197 } | 168 } |
| 198 | 169 |
| 199 double ProcessMetrics::GetCPUUsage() { | 170 double ProcessMetrics::GetCPUUsage() { |
| 200 // This queries the /proc-specific scaling factor which is | 171 // This queries the /proc-specific scaling factor which is |
| 201 // conceptually the system hertz. To dump this value on another | 172 // conceptually the system hertz. To dump this value on another |
| 202 // system, try | 173 // system, try |
| 203 // od -t dL /proc/self/auxv | 174 // od -t dL /proc/self/auxv |
| 204 // and look for the number after 17 in the output; mine is | 175 // and look for the number after 17 in the output; mine is |
| 205 // 0000040 17 100 3 134512692 | 176 // 0000040 17 100 3 134512692 |
| 206 // which means the answer is 100. | 177 // which means the answer is 100. |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 285 } | 256 } |
| 286 | 257 |
| 287 ProcessMetrics::ProcessMetrics(ProcessHandle process) | 258 ProcessMetrics::ProcessMetrics(ProcessHandle process) |
| 288 : process_(process), | 259 : process_(process), |
| 289 last_time_(0), | 260 last_time_(0), |
| 290 last_system_time_(0), | 261 last_system_time_(0), |
| 291 last_cpu_(0) { | 262 last_cpu_(0) { |
| 292 processor_count_ = base::SysInfo::NumberOfProcessors(); | 263 processor_count_ = base::SysInfo::NumberOfProcessors(); |
| 293 } | 264 } |
| 294 | 265 |
| 266 #if defined(OS_CHROMEOS) | |
| 267 // Private, Shared and Proportional working set sizes are obtained from | |
| 268 // /proc/<pid>/totmaps | |
| 269 bool ProcessMetrics::GetWorkingSetKBytesTotmaps(WorkingSetKBytes *ws_usage) | |
| 270 const { | |
| 271 // The format of /proc/<pid>/totmaps is: | |
| 272 // | |
| 273 // Rss: 6120 kB | |
| 274 // Pss: 3335 kB | |
| 275 // Shared_Clean: 1008 kB | |
| 276 // Shared_Dirty: 4012 kB | |
| 277 // Private_Clean: 4 kB | |
| 278 // Private_Dirty: 1096 kB | |
| 279 // ... | |
| 280 const size_t kPssIndex = 4; | |
| 281 const size_t kPrivate_CleanIndex = 13; | |
| 282 const size_t kPrivate_DirtyIndex = 16; | |
| 283 | |
| 284 std::string totmaps_data; | |
| 285 { | |
| 286 FilePath totmaps_file = internal::GetProcPidDir(process_).Append("totmaps"); | |
| 287 ThreadRestrictions::ScopedAllowIO allow_io; | |
| 288 bool ret = file_util::ReadFileToString(totmaps_file, &totmaps_data); | |
| 289 if (!ret || totmaps_data.length() == 0) | |
| 290 return false; | |
| 291 } | |
| 292 | |
| 293 std::vector<std::string> totmaps_fields; | |
| 294 SplitStringAlongWhitespace(totmaps_data, &totmaps_fields); | |
| 295 | |
| 296 DCHECK_EQ(totmaps_fields[kPssIndex-1], "Pss:"); | |
|
Lei Zhang
2013/05/28 03:37:41
nit: prefer DCHECK_EQ(expected, actual)
| |
| 297 DCHECK_EQ(totmaps_fields[kPrivate_CleanIndex-1], "Private_Clean:"); | |
| 298 DCHECK_EQ(totmaps_fields[kPrivate_DirtyIndex-1], "Private_Dirty:"); | |
| 299 | |
| 300 int pss, private_clean, private_dirty; | |
| 301 base::StringToInt(totmaps_fields[kPssIndex], &pss); | |
|
Lei Zhang
2013/05/28 03:37:41
nit: already in namespace base, no need for base::
Lei Zhang
2013/05/28 03:37:41
StringToInt() can fail - check return result.
Get
| |
| 302 base::StringToInt(totmaps_fields[kPrivate_CleanIndex], &private_clean); | |
| 303 base::StringToInt(totmaps_fields[kPrivate_DirtyIndex], &private_dirty); | |
| 304 | |
| 305 ws_usage->priv = private_clean + private_dirty; | |
| 306 ws_usage->shared = pss; | |
| 307 ws_usage->shareable = 0; | |
| 308 | |
| 309 return true; | |
| 310 } | |
| 311 #endif | |
| 312 | |
| 313 // Private and Shared working set sizes are obtained from /proc/<pid>/statm. | |
| 314 bool ProcessMetrics::GetWorkingSetKBytesStatm(WorkingSetKBytes* ws_usage) | |
| 315 const { | |
| 316 // Use statm instead of smaps because smaps is: | |
| 317 // a) Large and slow to parse. | |
| 318 // b) Unavailable in the SUID sandbox. | |
| 319 | |
| 320 // First we need to get the page size, since everything is measured in pages. | |
| 321 // For details, see: man 5 proc. | |
| 322 const int page_size_kb = getpagesize() / 1024; | |
| 323 if (page_size_kb <= 0) | |
| 324 return false; | |
| 325 | |
| 326 std::string statm; | |
| 327 { | |
| 328 FilePath statm_file = internal::GetProcPidDir(process_).Append("statm"); | |
| 329 // Synchronously reading files in /proc is safe. | |
| 330 ThreadRestrictions::ScopedAllowIO allow_io; | |
| 331 bool ret = file_util::ReadFileToString(statm_file, &statm); | |
| 332 if (!ret || statm.length() == 0) | |
| 333 return false; | |
| 334 } | |
| 335 | |
| 336 std::vector<std::string> statm_vec; | |
| 337 SplitString(statm, ' ', &statm_vec); | |
| 338 if (statm_vec.size() != 7) | |
| 339 return false; // Not the format we expect. | |
| 340 | |
| 341 int statm_rss, statm_shared; | |
| 342 StringToInt(statm_vec[1], &statm_rss); | |
| 343 StringToInt(statm_vec[2], &statm_shared); | |
| 344 | |
| 345 ws_usage->priv = (statm_rss - statm_shared) * page_size_kb; | |
| 346 ws_usage->shared = statm_shared * page_size_kb; | |
| 347 | |
| 348 // Sharable is not calculated, as it does not provide interesting data. | |
| 349 ws_usage->shareable = 0; | |
| 350 | |
| 351 return true; | |
| 352 } | |
| 353 | |
| 295 size_t GetSystemCommitCharge() { | 354 size_t GetSystemCommitCharge() { |
| 296 SystemMemoryInfoKB meminfo; | 355 SystemMemoryInfoKB meminfo; |
| 297 if (!GetSystemMemoryInfo(&meminfo)) | 356 if (!GetSystemMemoryInfo(&meminfo)) |
| 298 return 0; | 357 return 0; |
| 299 return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached; | 358 return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached; |
| 300 } | 359 } |
| 301 | 360 |
| 302 // Exposed for testing. | 361 // Exposed for testing. |
| 303 int ParseProcStatCPU(const std::string& input) { | 362 int ParseProcStatCPU(const std::string& input) { |
| 304 std::vector<std::string> proc_stats; | 363 std::vector<std::string> proc_stats; |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 430 if (num_res == 1) | 489 if (num_res == 1) |
| 431 meminfo->gem_size += mali_size; | 490 meminfo->gem_size += mali_size; |
| 432 } | 491 } |
| 433 #endif // defined(ARCH_CPU_ARM_FAMILY) | 492 #endif // defined(ARCH_CPU_ARM_FAMILY) |
| 434 #endif // defined(OS_CHROMEOS) | 493 #endif // defined(OS_CHROMEOS) |
| 435 | 494 |
| 436 return true; | 495 return true; |
| 437 } | 496 } |
| 438 | 497 |
| 439 } // namespace base | 498 } // namespace base |
| OLD | NEW |