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 3 // found in the LICENSE file. 4 5 #include "chrome/test/base/chrome_process_util.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/command_line.h" 11 #include "base/process/launch.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_split.h" 14 #include "base/strings/string_util.h" 15 #include "base/strings/stringprintf.h" 16 17 MacChromeProcessInfoList GetRunningMacProcessInfo( 18 const ChromeProcessList& process_list) { 19 MacChromeProcessInfoList result; 20 21 // Build up the ps command line 22 std::vector<std::string> cmdline; 23 cmdline.push_back("ps"); 24 cmdline.push_back("-o"); 25 cmdline.push_back("pid=,rss=,vsz="); // fields we need, no headings 26 ChromeProcessList::const_iterator process_iter; 27 for (process_iter = process_list.begin(); 28 process_iter != process_list.end(); 29 ++process_iter) { 30 cmdline.push_back("-p"); 31 cmdline.push_back(base::StringPrintf("%d", *process_iter)); 32 } 33 34 // Invoke it 35 std::string ps_output; 36 if (!base::GetAppOutput(CommandLine(cmdline), &ps_output)) 37 return result; // All the pids might have exited 38 39 // Process the results 40 std::vector<std::string> ps_output_lines; 41 base::SplitString(ps_output, '\n', &ps_output_lines); 42 std::vector<std::string>::const_iterator line_iter; 43 for (line_iter = ps_output_lines.begin(); 44 line_iter != ps_output_lines.end(); 45 ++line_iter) { 46 std::string line(CollapseWhitespaceASCII(*line_iter, false)); 47 std::vector<std::string> values; 48 base::SplitString(line, ' ', &values); 49 if (values.size() == 3) { 50 MacChromeProcessInfo proc_info; 51 int pid; 52 base::StringToInt(values[0], &pid); 53 proc_info.pid = pid; 54 base::StringToInt(values[1], &proc_info.rsz_in_kb); 55 base::StringToInt(values[2], &proc_info.vsz_in_kb); 56 if (proc_info.pid && proc_info.rsz_in_kb && proc_info.vsz_in_kb) 57 result.push_back(proc_info); 58 } 59 } 60 61 return result; 62 } 63 64 // Common interface for fetching memory values from parsed ps output. 65 // We fill in both values we may get called for, even though our 66 // callers typically only care about one, just to keep the code 67 // simple and because this is a test. 68 static bool GetMemoryValuesHack(uint32 process_id, 69 size_t* virtual_size, 70 size_t* working_set_size) { 71 DCHECK(virtual_size && working_set_size); 72 73 std::vector<base::ProcessId> processes; 74 processes.push_back(process_id); 75 76 MacChromeProcessInfoList process_info = GetRunningMacProcessInfo(processes); 77 if (process_info.empty()) 78 return false; 79 80 bool found_process = false; 81 *virtual_size = 0; 82 *working_set_size = 0; 83 84 MacChromeProcessInfoList::iterator it = process_info.begin(); 85 for (; it != process_info.end(); ++it) { 86 if (it->pid != static_cast<base::ProcessId>(process_id)) 87 continue; 88 found_process = true; 89 *virtual_size = it->vsz_in_kb * 1024; 90 *working_set_size = it->rsz_in_kb * 1024; 91 break; 92 } 93 94 return found_process; 95 } 96 97 size_t ChromeTestProcessMetrics::GetPagefileUsage() { 98 size_t virtual_size; 99 size_t working_set_size; 100 GetMemoryValuesHack(process_handle_, &virtual_size, &working_set_size); 101 return virtual_size; 102 } 103 104 size_t ChromeTestProcessMetrics::GetWorkingSetSize() { 105 size_t virtual_size; 106 size_t working_set_size; 107 GetMemoryValuesHack(process_handle_, &virtual_size, &working_set_size); 108 return working_set_size; 109 } 110