Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: chrome/browser/memory_details_linux.cc

Issue 177024: Linux: about:memory (Closed)
Patch Set: ... Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/browser/memory_details.cc ('k') | chrome/browser/memory_details_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 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/browser/memory_details.h"
6
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <dirent.h>
10
11 #include "app/l10n_util.h"
12 #include "base/eintr_wrapper.h"
13 #include "base/file_version_info.h"
14 #include "base/string_util.h"
15 #include "base/process_util.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_thread.h"
18 #include "chrome/common/child_process_host.h"
19 #include "chrome/common/chrome_constants.h"
20 #include "chrome/common/url_constants.h"
21 #include "grit/chromium_strings.h"
22
23 // Known browsers which we collect details for.
24 enum BrowserType {
25 CHROME = 0,
26 FIREFOX,
27 OPERA,
28 KONQUEROR,
29 EPIPHANY,
30 MIDORI,
31 MAX_BROWSERS
32 } BrowserProcess;
33
34 // The pretty printed names of those browsers. Matches up with enum
35 // BrowserType.
36 static const char kBrowserPrettyNames[][10] = {
37 "Chrome",
38 "Firefox",
39 "Opera",
40 "Konqueror",
41 "Epiphany",
42 "Midori",
43 };
44
45 // A mapping from process name to the type of browser.
46 static const struct {
47 const char process_name[17];
48 BrowserType browser;
49 } kBrowserBinaryNames[] = {
50 { "firefox", FIREFOX },
51 { "firefox-3.5", FIREFOX },
52 { "firefox-3.0", FIREFOX },
53 { "opera", OPERA },
54 { "konqueror", KONQUEROR },
55 { "epiphany-browser", EPIPHANY },
56 { "epiphany", EPIPHANY },
57 { "midori", MIDORI },
58 { "", MAX_BROWSERS },
59 };
60
61 MemoryDetails::MemoryDetails()
62 : ui_loop_(NULL) {
63 }
64
65 ProcessData* MemoryDetails::ChromeBrowser() {
66 return &process_data_[0];
67 }
68
69 struct Process {
70 pid_t pid;
71 pid_t parent;
72 std::string name;
73 };
74
75 // Walk /proc and get information on all the processes running on the system.
76 static bool GetProcesses(std::vector<Process>* processes) {
77 processes->clear();
78
79 DIR* dir = opendir("/proc");
80 if (!dir)
81 return false;
82
83 struct dirent* dent;
84 while ((dent = readdir(dir))) {
85 bool candidate = true;
86
87 // Filter out names which aren't ^[0-9]*$
88 for (const char* p = dent->d_name; *p; ++p) {
89 if (*p < '0' || *p > '9') {
90 candidate = false;
91 break;
92 }
93 }
94
95 if (!candidate)
96 continue;
97
98 char buf[256];
99 snprintf(buf, sizeof(buf), "/proc/%s/stat", dent->d_name);
100 const int fd = open(buf, O_RDONLY);
101 if (fd < 0)
102 continue;
103
104 const ssize_t len = HANDLE_EINTR(read(fd, buf, sizeof(buf) - 1));
105 HANDLE_EINTR(close(fd));
106 if (len < 1)
107 continue;
108 buf[len] = 0;
109
110 // The start of the file looks like:
111 // <pid> (<name>) R <parent pid>
112 unsigned pid, ppid;
113 char *process_name;
114 if (sscanf(buf, "%u (%a[^)]) %*c %u", &pid, &process_name, &ppid) != 3)
115 continue;
116
117 Process process;
118 process.pid = pid;
119 process.parent = ppid;
120 process.name = process_name;
121 free(process_name);
122 processes->push_back(process);
123 }
124
125 closedir(dir);
126 return true;
127 }
128
129 // Given a process name, return the type of the browser which created that
130 // process, or |MAX_BROWSERS| if we don't know about it.
131 static BrowserType GetBrowserType(const std::string& process_name) {
132 for (unsigned i = 0; kBrowserBinaryNames[i].process_name[0]; ++i) {
133 if (strcmp(process_name.c_str(), kBrowserBinaryNames[i].process_name) == 0)
134 return kBrowserBinaryNames[i].browser;
135 }
136
137 return MAX_BROWSERS;
138 }
139
140 // For each of a list of pids, collect memory information about that process
141 // and append a record to |out|
142 static void GetProcessDataMemoryInformation(
143 const std::vector<pid_t>& pids, ProcessData* out) {
144 for (std::vector<pid_t>::const_iterator
145 i = pids.begin(); i != pids.end(); ++i) {
146 ProcessMemoryInformation pmi;
147
148 pmi.pid = *i;
149 pmi.num_processes = 1;
150
151 if (pmi.pid == base::GetCurrentProcId())
152 pmi.type = ChildProcessInfo::BROWSER_PROCESS;
153 else
154 pmi.type = ChildProcessInfo::UNKNOWN_PROCESS;
155
156 base::ProcessMetrics* metrics =
157 base::ProcessMetrics::CreateProcessMetrics(*i);
158 metrics->GetWorkingSetKBytes(&pmi.working_set);
159 delete metrics;
160
161 out->processes.push_back(pmi);
162 }
163 }
164
165 // Find all children of the given process.
166 static void GetAllChildren(const std::vector<Process>& processes,
167 pid_t root, std::vector<pid_t>* out) {
168 out->clear();
169 out->push_back(root);
170
171 std::set<pid_t> wavefront, next_wavefront;
172 wavefront.insert(root);
173
174 while (wavefront.size()) {
175 for (std::vector<Process>::const_iterator
176 i = processes.begin(); i != processes.end(); ++i) {
177 if (wavefront.count(i->parent)) {
178 out->push_back(i->pid);
179 next_wavefront.insert(i->pid);
180 }
181 }
182
183 wavefront.clear();
184 wavefront.swap(next_wavefront);
185 }
186 }
187
188 void MemoryDetails::CollectProcessData(
189 std::vector<ProcessMemoryInformation> child_info) {
190 DCHECK(MessageLoop::current() ==
191 ChromeThread::GetMessageLoop(ChromeThread::FILE));
192
193 std::vector<Process> processes;
194 GetProcesses(&processes);
195 std::set<pid_t> browsers_found;
196
197 // For each process on the system, if it appears to be a browser process and
198 // it's parent isn't a browser process, then record it in |browsers_found|.
199 for (std::vector<Process>::const_iterator
200 i = processes.begin(); i != processes.end(); ++i) {
201 const BrowserType type = GetBrowserType(i->name);
202 if (type != MAX_BROWSERS) {
203 bool found_parent = false;
204
205 // Find the parent of |i|
206 for (std::vector<Process>::const_iterator
207 j = processes.begin(); j != processes.end(); ++j) {
208 if (j->pid == i->parent) {
209 found_parent = true;
210
211 if (GetBrowserType(j->name) != type) {
212 // We went too far and ended up with something else, which means
213 // that |i| is a browser.
214 browsers_found.insert(i->pid);
215 break;
216 }
217 }
218 }
219
220 if (!found_parent)
221 browsers_found.insert(i->pid);
222 }
223 }
224
225 std::vector<pid_t> current_browser_processes;
226 GetAllChildren(processes, getpid(), &current_browser_processes);
227 ProcessData current_browser;
228 GetProcessDataMemoryInformation(current_browser_processes, &current_browser);
229 current_browser.name = chrome::kBrowserAppName;
230 current_browser.process_name = L"chrome";
231 process_data_.push_back(current_browser);
232
233 // For each browser process, collect a list of its children and get the
234 // memory usage of each.
235 for (std::set<pid_t>::const_iterator
236 i = browsers_found.begin(); i != browsers_found.end(); ++i) {
237 std::vector<pid_t> browser_processes;
238 GetAllChildren(processes, *i, &browser_processes);
239 ProcessData browser;
240 GetProcessDataMemoryInformation(browser_processes, &browser);
241
242 for (std::vector<Process>::const_iterator
243 j = processes.begin(); j != processes.end(); ++j) {
244 if (j->pid == *i) {
245 BrowserType type = GetBrowserType(j->name);
246 if (type != MAX_BROWSERS)
247 browser.name = ASCIIToWide(kBrowserPrettyNames[type]);
248 break;
249 }
250 }
251
252 process_data_.push_back(browser);
253 }
254
255 // Finally return to the browser thread.
256 ui_loop_->PostTask(FROM_HERE,
257 NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
258 }
OLDNEW
« no previous file with comments | « chrome/browser/memory_details.cc ('k') | chrome/browser/memory_details_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698