| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/process_info_snapshot.h" | 5 #include "chrome/browser/process_info_snapshot.h" |
| 6 | 6 |
| 7 #include <sys/sysctl.h> | 7 #include <sys/sysctl.h> |
| 8 | 8 |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac/mac_util.h" | |
| 14 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
| 15 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 16 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
| 17 | 16 |
| 18 // Default constructor. | 17 // Default constructor. |
| 19 ProcessInfoSnapshot::ProcessInfoSnapshot() { } | 18 ProcessInfoSnapshot::ProcessInfoSnapshot() { } |
| 20 | 19 |
| 21 // Destructor: just call |Reset()| to release everything. | 20 // Destructor: just call |Reset()| to release everything. |
| 22 ProcessInfoSnapshot::~ProcessInfoSnapshot() { | 21 ProcessInfoSnapshot::~ProcessInfoSnapshot() { |
| 23 Reset(); | 22 Reset(); |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 proc_info.rshrd = values[1]; | 260 proc_info.rshrd = values[1]; |
| 262 proc_info.rprvt = values[2]; | 261 proc_info.rprvt = values[2]; |
| 263 proc_info.vsize = values[3]; | 262 proc_info.vsize = values[3]; |
| 264 // Record the process information. | 263 // Record the process information. |
| 265 proc_info_entries[proc_info.pid] = proc_info; | 264 proc_info_entries[proc_info.pid] = proc_info; |
| 266 } | 265 } |
| 267 | 266 |
| 268 return true; | 267 return true; |
| 269 } | 268 } |
| 270 | 269 |
| 271 static bool GetProcessMemoryInfoUsingTop_10_5( | |
| 272 std::map<int,ProcessInfoSnapshot::ProcInfoEntry>& proc_info_entries) { | |
| 273 const FilePath kProgram("/usr/bin/top"); | |
| 274 CommandLine command_line(kProgram); | |
| 275 | |
| 276 // -p tells top to print just the given fields as ordered. | |
| 277 command_line.AppendArg("-p"); | |
| 278 command_line.AppendArg( | |
| 279 "^aaaaaaaaaaaaaaaaaaaa " // Process ID (PID) | |
| 280 "^jjjjjjjjjjjjjjjjjjjj " // Resident memory (RSIZE) | |
| 281 "^iiiiiiiiiiiiiiiiiiii " // Resident shared memory (RSHRD) | |
| 282 "^hhhhhhhhhhhhhhhhhhhh " // Resident private memory (RPRVT) | |
| 283 "^llllllllllllllllllll"); // Total virtual memory (VSIZE) | |
| 284 // Run top in logging (non-interactive) mode. | |
| 285 command_line.AppendArg("-l"); | |
| 286 command_line.AppendArg("1"); | |
| 287 // Set the delay between updates to 0. | |
| 288 command_line.AppendArg("-s"); | |
| 289 command_line.AppendArg("0"); | |
| 290 | |
| 291 std::string output; | |
| 292 // Limit output read to a megabyte for safety. | |
| 293 if (!base::GetAppOutputRestricted(command_line, &output, 1024 * 1024)) { | |
| 294 LOG(ERROR) << "Failure running " << kProgram.value() << " to acquire data."; | |
| 295 return false; | |
| 296 } | |
| 297 | |
| 298 // Process lines until done. Lines should look something like this: | |
| 299 // PID RSIZE RSHRD RPRVT VSIZE | |
| 300 // 16943 815104 262144 290816 18489344 | |
| 301 // 16922 954368 720896 278528 18976768 | |
| 302 std::istringstream top_in(output, std::istringstream::in); | |
| 303 std::string line; | |
| 304 while (std::getline(top_in, line)) { | |
| 305 std::istringstream in(line, std::istringstream::in); | |
| 306 | |
| 307 // Try to read the PID. | |
| 308 pid_t pid; | |
| 309 in >> pid; | |
| 310 if (in.fail()) | |
| 311 continue; | |
| 312 | |
| 313 // Make sure that caller is interested in this process. | |
| 314 if (proc_info_entries.find(pid) == proc_info_entries.end()) | |
| 315 continue; | |
| 316 | |
| 317 uint64_t values[4]; | |
| 318 size_t i; | |
| 319 for (i = 0; i < arraysize(values); i++) { | |
| 320 in >> values[i]; | |
| 321 if (in.fail()) | |
| 322 break; | |
| 323 } | |
| 324 if (i != arraysize(values)) | |
| 325 continue; | |
| 326 | |
| 327 ProcessInfoSnapshot::ProcInfoEntry proc_info = proc_info_entries[pid]; | |
| 328 proc_info.rss = values[0]; | |
| 329 proc_info.rshrd = values[1]; | |
| 330 proc_info.rprvt = values[2]; | |
| 331 proc_info.vsize = values[3]; | |
| 332 // Record the process information. | |
| 333 proc_info_entries[proc_info.pid] = proc_info; | |
| 334 } | |
| 335 | |
| 336 return true; | |
| 337 } | |
| 338 | |
| 339 | |
| 340 bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) { | 270 bool ProcessInfoSnapshot::Sample(std::vector<base::ProcessId> pid_list) { |
| 341 Reset(); | 271 Reset(); |
| 342 | 272 |
| 343 // Nothing to do if no PIDs given. | 273 // Nothing to do if no PIDs given. |
| 344 if (pid_list.empty()) | 274 if (pid_list.empty()) |
| 345 return true; | 275 return true; |
| 346 if (pid_list.size() > kMaxPidListSize) { | 276 if (pid_list.size() > kMaxPidListSize) { |
| 347 // The spec says |pid_list| *must* not have more than this many entries. | 277 // The spec says |pid_list| *must* not have more than this many entries. |
| 348 NOTREACHED(); | 278 NOTREACHED(); |
| 349 return false; | 279 return false; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 372 for (std::vector<base::ProcessId>::iterator it = pid_list.begin(); | 302 for (std::vector<base::ProcessId>::iterator it = pid_list.begin(); |
| 373 it != pid_list.end(); ++it) { | 303 it != pid_list.end(); ++it) { |
| 374 std::string exectuable_name; | 304 std::string exectuable_name; |
| 375 if (GetExecutableNameForProcessID(*it, &exectuable_name)) { | 305 if (GetExecutableNameForProcessID(*it, &exectuable_name)) { |
| 376 ProcInfoEntry proc_info = proc_info_entries_[*it]; | 306 ProcInfoEntry proc_info = proc_info_entries_[*it]; |
| 377 proc_info.command = exectuable_name; | 307 proc_info.command = exectuable_name; |
| 378 } | 308 } |
| 379 } | 309 } |
| 380 | 310 |
| 381 // Get memory information using top. | 311 // Get memory information using top. |
| 382 bool memory_info_success = false; | 312 bool memory_info_success = GetProcessMemoryInfoUsingTop(proc_info_entries_); |
| 383 if (base::mac::IsOSLeopardOrEarlier()) | |
| 384 memory_info_success = GetProcessMemoryInfoUsingTop_10_5(proc_info_entries_); | |
| 385 else | |
| 386 memory_info_success = GetProcessMemoryInfoUsingTop(proc_info_entries_); | |
| 387 | 313 |
| 388 // If top didn't work then fall back to ps. | 314 // If top didn't work then fall back to ps. |
| 389 if (!memory_info_success) { | 315 if (!memory_info_success) { |
| 390 memory_info_success = GetProcessMemoryInfoUsingPS(pid_list, | 316 memory_info_success = GetProcessMemoryInfoUsingPS(pid_list, |
| 391 proc_info_entries_); | 317 proc_info_entries_); |
| 392 } | 318 } |
| 393 | 319 |
| 394 return memory_info_success; | 320 return memory_info_success; |
| 395 } | 321 } |
| 396 | 322 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 ws_usage->shareable = 0; | 375 ws_usage->shareable = 0; |
| 450 ws_usage->shared = 0; | 376 ws_usage->shared = 0; |
| 451 return false; | 377 return false; |
| 452 } | 378 } |
| 453 | 379 |
| 454 ws_usage->priv = proc_info.rprvt / 1024; | 380 ws_usage->priv = proc_info.rprvt / 1024; |
| 455 ws_usage->shareable = proc_info.rss / 1024; | 381 ws_usage->shareable = proc_info.rss / 1024; |
| 456 ws_usage->shared = proc_info.rshrd / 1024; | 382 ws_usage->shared = proc_info.rshrd / 1024; |
| 457 return true; | 383 return true; |
| 458 } | 384 } |
| OLD | NEW |