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

Unified Diff: chrome/browser/memory_details_linux.cc

Issue 177024: Linux: about:memory (Closed)
Patch Set: ... Created 11 years, 4 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/memory_details_linux.cc
diff --git a/chrome/browser/memory_details_linux.cc b/chrome/browser/memory_details_linux.cc
new file mode 100644
index 0000000000000000000000000000000000000000..a1ed5e9eef78ef43a46d359997babcb2d656cac8
--- /dev/null
+++ b/chrome/browser/memory_details_linux.cc
@@ -0,0 +1,258 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/memory_details.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#include "app/l10n_util.h"
+#include "base/eintr_wrapper.h"
+#include "base/file_version_info.h"
+#include "base/string_util.h"
+#include "base/process_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/child_process_host.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+
+// Known browsers which we collect details for.
+enum BrowserType {
+ CHROME = 0,
+ FIREFOX,
+ OPERA,
+ KONQUEROR,
+ EPIPHANY,
+ MIDORI,
+ MAX_BROWSERS
+} BrowserProcess;
+
+// The pretty printed names of those browsers. Matches up with enum
+// BrowserType.
+static const char kBrowserPrettyNames[][10] = {
+ "Chrome",
+ "Firefox",
+ "Opera",
+ "Konqueror",
+ "Epiphany",
+ "Midori",
+};
+
+// A mapping from process name to the type of browser.
+static const struct {
+ const char process_name[17];
+ BrowserType browser;
+ } kBrowserBinaryNames[] = {
+ { "firefox", FIREFOX },
+ { "firefox-3.5", FIREFOX },
+ { "firefox-3.0", FIREFOX },
+ { "opera", OPERA },
+ { "konqueror", KONQUEROR },
+ { "epiphany-browser", EPIPHANY },
+ { "epiphany", EPIPHANY },
+ { "midori", MIDORI },
+ { "", MAX_BROWSERS },
+};
+
+MemoryDetails::MemoryDetails()
+ : ui_loop_(NULL) {
+}
+
+ProcessData* MemoryDetails::ChromeBrowser() {
+ return &process_data_[0];
+}
+
+struct Process {
+ pid_t pid;
+ pid_t parent;
+ std::string name;
+};
+
+// Walk /proc and get information on all the processes running on the system.
+static bool GetProcesses(std::vector<Process>* processes) {
+ processes->clear();
+
+ DIR* dir = opendir("/proc");
+ if (!dir)
+ return false;
+
+ struct dirent* dent;
+ while ((dent = readdir(dir))) {
+ bool candidate = true;
+
+ // Filter out names which aren't ^[0-9]*$
+ for (const char* p = dent->d_name; *p; ++p) {
+ if (*p < '0' || *p > '9') {
+ candidate = false;
+ break;
+ }
+ }
+
+ if (!candidate)
+ continue;
+
+ char buf[256];
+ snprintf(buf, sizeof(buf), "/proc/%s/stat", dent->d_name);
+ const int fd = open(buf, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ const ssize_t len = HANDLE_EINTR(read(fd, buf, sizeof(buf) - 1));
+ HANDLE_EINTR(close(fd));
+ if (len < 1)
+ continue;
+ buf[len] = 0;
+
+ // The start of the file looks like:
+ // <pid> (<name>) R <parent pid>
+ unsigned pid, ppid;
+ char *process_name;
+ if (sscanf(buf, "%u (%a[^)]) %*c %u", &pid, &process_name, &ppid) != 3)
+ continue;
+
+ Process process;
+ process.pid = pid;
+ process.parent = ppid;
+ process.name = process_name;
+ free(process_name);
+ processes->push_back(process);
+ }
+
+ closedir(dir);
+ return true;
+}
+
+// Given a process name, return the type of the browser which created that
+// process, or |MAX_BROWSERS| if we don't know about it.
+static BrowserType GetBrowserType(const std::string& process_name) {
+ for (unsigned i = 0; kBrowserBinaryNames[i].process_name[0]; ++i) {
+ if (strcmp(process_name.c_str(), kBrowserBinaryNames[i].process_name) == 0)
+ return kBrowserBinaryNames[i].browser;
+ }
+
+ return MAX_BROWSERS;
+}
+
+// For each of a list of pids, collect memory information about that process
+// and append a record to |out|
+static void GetProcessDataMemoryInformation(
+ const std::vector<pid_t>& pids, ProcessData* out) {
+ for (std::vector<pid_t>::const_iterator
+ i = pids.begin(); i != pids.end(); ++i) {
+ ProcessMemoryInformation pmi;
+
+ pmi.pid = *i;
+ pmi.num_processes = 1;
+
+ if (pmi.pid == base::GetCurrentProcId())
+ pmi.type = ChildProcessInfo::BROWSER_PROCESS;
+ else
+ pmi.type = ChildProcessInfo::UNKNOWN_PROCESS;
+
+ base::ProcessMetrics* metrics =
+ base::ProcessMetrics::CreateProcessMetrics(*i);
+ metrics->GetWorkingSetKBytes(&pmi.working_set);
+ delete metrics;
+
+ out->processes.push_back(pmi);
+ }
+}
+
+// Find all children of the given process.
+static void GetAllChildren(const std::vector<Process>& processes,
+ pid_t root, std::vector<pid_t>* out) {
+ out->clear();
+ out->push_back(root);
+
+ std::set<pid_t> wavefront, next_wavefront;
+ wavefront.insert(root);
+
+ while (wavefront.size()) {
+ for (std::vector<Process>::const_iterator
+ i = processes.begin(); i != processes.end(); ++i) {
+ if (wavefront.count(i->parent)) {
+ out->push_back(i->pid);
+ next_wavefront.insert(i->pid);
+ }
+ }
+
+ wavefront.clear();
+ wavefront.swap(next_wavefront);
+ }
+}
+
+void MemoryDetails::CollectProcessData(
+ std::vector<ProcessMemoryInformation> child_info) {
+ DCHECK(MessageLoop::current() ==
+ ChromeThread::GetMessageLoop(ChromeThread::FILE));
+
+ std::vector<Process> processes;
+ GetProcesses(&processes);
+ std::set<pid_t> browsers_found;
+
+ // For each process on the system, if it appears to be a browser process and
+ // it's parent isn't a browser process, then record it in |browsers_found|.
+ for (std::vector<Process>::const_iterator
+ i = processes.begin(); i != processes.end(); ++i) {
+ const BrowserType type = GetBrowserType(i->name);
+ if (type != MAX_BROWSERS) {
+ bool found_parent = false;
+
+ // Find the parent of |i|
+ for (std::vector<Process>::const_iterator
+ j = processes.begin(); j != processes.end(); ++j) {
+ if (j->pid == i->parent) {
+ found_parent = true;
+
+ if (GetBrowserType(j->name) != type) {
+ // We went too far and ended up with something else, which means
+ // that |i| is a browser.
+ browsers_found.insert(i->pid);
+ break;
+ }
+ }
+ }
+
+ if (!found_parent)
+ browsers_found.insert(i->pid);
+ }
+ }
+
+ std::vector<pid_t> current_browser_processes;
+ GetAllChildren(processes, getpid(), &current_browser_processes);
+ ProcessData current_browser;
+ GetProcessDataMemoryInformation(current_browser_processes, &current_browser);
+ current_browser.name = chrome::kBrowserAppName;
+ current_browser.process_name = L"chrome";
+ process_data_.push_back(current_browser);
+
+ // For each browser process, collect a list of its children and get the
+ // memory usage of each.
+ for (std::set<pid_t>::const_iterator
+ i = browsers_found.begin(); i != browsers_found.end(); ++i) {
+ std::vector<pid_t> browser_processes;
+ GetAllChildren(processes, *i, &browser_processes);
+ ProcessData browser;
+ GetProcessDataMemoryInformation(browser_processes, &browser);
+
+ for (std::vector<Process>::const_iterator
+ j = processes.begin(); j != processes.end(); ++j) {
+ if (j->pid == *i) {
+ BrowserType type = GetBrowserType(j->name);
+ if (type != MAX_BROWSERS)
+ browser.name = ASCIIToWide(kBrowserPrettyNames[type]);
+ break;
+ }
+ }
+
+ process_data_.push_back(browser);
+ }
+
+ // Finally return to the browser thread.
+ ui_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
+}
« 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