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 |