Hi all,
I don't have the resources (disk space + tools) to compile my patch under
Windows and OSX, so can someone on this list quickly try it before I post it
for review? And on Windows, do a sanity check on the about:memory page.
Patch is attached.
Thanks,
- Anand
--~--~---------~--~----~------------~-------~--~----~
Chromium Developers mailing list: [email protected]
View archives, change email options, or unsubscribe:
http://groups.google.com/group/chromium-dev
-~----------~----~----~----~------~----~------~--~---
Index: base/process_util.h
===================================================================
--- base/process_util.h (revision 22256)
+++ base/process_util.h (working copy)
@@ -293,6 +293,7 @@
// shared : These pages (kbytes) are currently shared with at least one
// other process.
struct WorkingSetKBytes {
+ WorkingSetKBytes() : priv(0), shareable(0), shared(0) {}
size_t priv;
size_t shareable;
size_t shared;
@@ -305,6 +306,7 @@
// image: These pages are mapped into the view of an image section (backed by
// file system)
struct CommittedKBytes {
+ CommittedKBytes() : priv(0), mapped(0), image(0) {}
size_t priv;
size_t mapped;
size_t image;
Index: base/process_util_linux.cc
===================================================================
--- base/process_util_linux.cc (revision 22256)
+++ base/process_util_linux.cc (working copy)
@@ -326,6 +326,71 @@
return 0;
}
+void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const {
+ FilePath stat_file =
+ FilePath("/proc").Append(IntToString(process_)).Append("maps");
+ std::string maps;
+ size_t file_mapped_size = 0;
+ size_t anon_size = 0;
+ size_t private_size = 0;
+ if (!file_util::ReadFileToString(stat_file, &maps))
+ return;
+
+ std::vector<std::string> map_lines;
+ SplitString(maps, '\n', &map_lines);
+ for (std::vector<std::string>::iterator iter = map_lines.begin();
+ iter != map_lines.end(); ++iter) {
+ if (*iter == "") {
+ continue;
+ }
+
+ std::vector<std::string> fields;
+ SplitString(*iter, ' ', &fields);
+ if (fields.size() < 5) {
+ LOG(ERROR) << "Badly formatted /proc/*/maps line: " << *iter;
+ continue;
+ }
+
+ // First fields is memory range, which gives us size. Formatted as:
+ // XXXXXXXX-XXXXXXXX
+ unsigned int sep_pos = fields[0].find('-');
+ if (sep_pos == std::string::npos) {
+ LOG(ERROR) << "Badly formatted address range: " << fields[0];
+ continue;
+ }
+ int address_begin = HexStringToInt(fields[0].substr(0, sep_pos));
+ int address_end = HexStringToInt(fields[0].substr(sep_pos + 1));
+ if (address_end < address_begin)
+ continue;
+ size_t size = address_end - address_begin;
+
+ // Second field is permissions formatted as:
+ // [r-][w-][x-][ps]
+ // Where:
+ // r = read
+ // w = write
+ // x = execute
+ // p = private
+ // s = shared
+ if (fields[1][3] == 'p')
+ private_size += size;
+
+ // Fifth field is inode. If non-zero, this memory region is mapped by a
+ // file.
+ int inode = 0;
+ StringToInt(fields[4], &inode);
+ if (inode) {
+ file_mapped_size += size;
+ } else {
+ anon_size += size;
+ }
+ }
+
+ usage->priv = private_size / 1024;
+ usage->image = file_mapped_size / 1024;
+ usage->mapped = anon_size / 1024;
+}
+
// Private and Shared working set sizes are obtained from /proc/<pid>/smaps,
// as in http://www.pixelbeat.org/scripts/ps_mem.py
bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
@@ -367,13 +432,14 @@
}
}
ws_usage->priv = private_kb;
- // Sharable is not calculated, as it does not provide interesting data.
- ws_usage->shareable = 0;
if (have_pss) {
- ws_usage->shared = pss_kb - private_kb;
+ ws_usage->shared = pss_kb - private_kb;
} else {
ws_usage->shared = shared_kb;
}
+ // Shared pages are sharable, so even if this isn't that useful, fill it in
+ // with the most sensible value since the about:memory handler page needs it.
+ ws_usage->shareable = ws_usage->shared;
return true;
}
Index: chrome/browser/memory_details_linux.cc
===================================================================
--- chrome/browser/memory_details_linux.cc (revision 0)
+++ chrome/browser/memory_details_linux.cc (revision 0)
@@ -0,0 +1,106 @@
+// 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 "app/l10n_util.h"
+#include "base/file_version_info.h"
+#include "base/string_util.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/common/child_process_host.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+
+// Known browsers which we collect details for.
+enum _BrowserProcess {
+ CHROME_BROWSER = 0,
+ FIREFOX_BROWSER,
+ OPERA_BROWSER,
+ KONQUEROR_BROWSER,
+ MAX_BROWSERS
+} BrowserProcess;
+
+// Template of static data we use for finding browser process information.
+// These entries must match the ordering for MemoryDetails::BrowserProcess.
+static ProcessData g_process_template[MAX_BROWSERS];
+
+MemoryDetails::MemoryDetails()
+ : ui_loop_(NULL) {
+ static const std::wstring google_browser_name =
+ l10n_util::GetString(IDS_PRODUCT_NAME);
+ ProcessData g_process_template[MAX_BROWSERS] = {
+ { google_browser_name.c_str(), L"chrome", },
+ { L"Firefox", L"firefox-bin", },
+ { L"Opera", L"opera", },
+ { L"Konqueror", L"konqueror", },
+ };
+
+ for (unsigned int index = 0; index < arraysize(g_process_template); ++index) {
+ ProcessData process;
+ process.name = g_process_template[index].name;
+ process.process_name = g_process_template[index].process_name;
+ process_data_.push_back(process);
+ }
+}
+
+ProcessData* MemoryDetails::ChromeBrowser() {
+ return &process_data_[CHROME_BROWSER];
+}
+
+void MemoryDetails::CollectProcessData(
+ std::vector<ProcessMemoryInformation> child_info) {
+ DCHECK(MessageLoop::current() ==
+ ChromeThread::GetMessageLoop(ChromeThread::FILE));
+
+ for (unsigned int index = 0; index < arraysize(g_process_template); index++) {
+ process_data_[index].processes.clear();
+
+ base::NamedProcessIterator process_iter(process_data_[index].process_name,
+ NULL);
+
+ const ProcessEntry* entry;
+ while ((entry = process_iter.NextProcessEntry())) {
+ ProcessMemoryInformation info;
+ info.pid = entry->pid;
+
+ if (info.pid == base::GetCurrentProcId())
+ info.type = ChildProcessInfo::BROWSER_PROCESS;
+ else
+ info.type = ChildProcessInfo::UNKNOWN_PROCESS;
+
+ base::ProcessHandle handle;
+ if (!base::OpenProcessHandle(entry->pid, &handle))
+ continue;
+ scoped_ptr<base::ProcessMetrics> metrics;
+ metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
+ metrics->GetCommittedKBytes(&info.committed);
+ metrics->GetWorkingSetKBytes(&info.working_set);
+
+ // Get Version Information.
+ if (index == CHROME_BROWSER) {
+ scoped_ptr<FileVersionInfo> version_info(
+ FileVersionInfo::CreateFileVersionInfoForCurrentModule());
+ if (version_info != NULL)
+ info.version = version_info->file_version();
+ // Check if this is one of the child processes whose data we collected
+ // on the IO thread, and if so copy over that data.
+ for (size_t child = 0; child < child_info.size(); child++) {
+ if (child_info[child].pid != info.pid)
+ continue;
+ info.titles = child_info[child].titles;
+ info.type = child_info[child].type;
+ break;
+ }
+ }
+
+ // Add the process info to our list.
+ process_data_[index].processes.push_back(info);
+ }
+ }
+
+ // Finally return to the browser thread.
+ ui_loop_->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
+}
Index: chrome/browser/memory_details.h
===================================================================
--- chrome/browser/memory_details.h (revision 22256)
+++ chrome/browser/memory_details.h (working copy)
@@ -17,8 +17,9 @@
// have multiple processes (of course!). Even IE has multiple
// processes these days.
struct ProcessMemoryInformation {
- ProcessMemoryInformation() {
- memset(this, 0, sizeof(ProcessMemoryInformation));
+ ProcessMemoryInformation() : pid(0),
+ num_processes(0),
+ is_diagnostics(false) {
}
// The process id.
@@ -71,18 +72,6 @@
// }
class MemoryDetails : public base::RefCountedThreadSafe<MemoryDetails> {
public:
- // Known browsers which we collect details for.
- enum {
- CHROME_BROWSER = 0,
- IE_BROWSER,
- FIREFOX_BROWSER,
- OPERA_BROWSER,
- SAFARI_BROWSER,
- IE_64BIT_BROWSER,
- KONQUEROR_BROWSER,
- MAX_BROWSERS
- } BrowserProcess;
-
// Constructor.
MemoryDetails();
virtual ~MemoryDetails() {}
@@ -90,7 +79,7 @@
// Access to the process detail information. This is an array
// of MAX_BROWSER ProcessData structures. This data is only available
// after OnDetailsAvailable() has been called.
- ProcessData* processes() { return process_data_; }
+ const std::vector<ProcessData>& processes() { return process_data_; }
// Initiate updating the current memory details. These are fetched
// asynchronously because data must be collected from multiple threads.
@@ -123,7 +112,10 @@
// the global histograms for tracking memory usage.
void UpdateHistograms();
- ProcessData process_data_[MAX_BROWSERS];
+ // Returns a pointer to the ProcessData structure for Chrome.
+ ProcessData* ChromeBrowser();
+
+ std::vector<ProcessData> process_data_;
MessageLoop* ui_loop_;
DISALLOW_EVIL_CONSTRUCTORS(MemoryDetails);
Index: chrome/browser/browser_about_handler.cc
===================================================================
--- chrome/browser/browser_about_handler.cc (revision 22256)
+++ chrome/browser/browser_about_handler.cc (working copy)
@@ -510,17 +510,17 @@
ListValue* browsers = new ListValue();
root.Set(L"browsers", browsers);
- ProcessData* browser_processes = processes();
+ const std::vector<ProcessData>& browser_processes = processes();
// Aggregate per-process data into browser summary data.
std::wstring log_string;
- for (int index = 0; index < MemoryDetails::MAX_BROWSERS; index++) {
+ for (unsigned int index = 0; index < browser_processes.size(); index++) {
if (browser_processes[index].processes.size() == 0)
continue;
// Sum the information for the processes within this browser.
ProcessMemoryInformation aggregate;
- ProcessMemoryInformationList::iterator iterator;
+ ProcessMemoryInformationList::const_iterator iterator;
iterator = browser_processes[index].processes.begin();
aggregate.pid = iterator->pid;
aggregate.version = iterator->version;
Index: chrome/browser/memory_details.cc
===================================================================
--- chrome/browser/memory_details.cc (revision 22256)
+++ chrome/browser/memory_details.cc (working copy)
@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "chrome/browser/memory_details.h"
-#include <psapi.h>
#include "app/l10n_util.h"
#include "base/file_version_info.h"
@@ -17,12 +16,6 @@
#include "chrome/common/url_constants.h"
#include "grit/chromium_strings.h"
-class RenderViewHostDelegate;
-
-// Template of static data we use for finding browser process information.
-// These entries must match the ordering for MemoryDetails::BrowserProcess.
-static ProcessData g_process_template[MemoryDetails::MAX_BROWSERS];
-
// About threading:
//
// This operation will hit no fewer than 3 threads.
@@ -36,26 +29,6 @@
// expensive parts of this operation over on the file thread.
//
-MemoryDetails::MemoryDetails()
- : ui_loop_(NULL) {
- static const std::wstring google_browser_name =
- l10n_util::GetString(IDS_PRODUCT_NAME);
- ProcessData g_process_template[MemoryDetails::MAX_BROWSERS] = {
- { google_browser_name.c_str(), L"chrome.exe", },
- { L"IE", L"iexplore.exe", },
- { L"Firefox", L"firefox.exe", },
- { L"Opera", L"opera.exe", },
- { L"Safari", L"safari.exe", },
- { L"IE (64bit)", L"iexplore.exe", },
- { L"Konqueror", L"konqueror.exe", },
- };
-
- for (int index = 0; index < arraysize(g_process_template); ++index) {
- process_data_[index].name = g_process_template[index].name;
- process_data_[index].process_name = g_process_template[index].process_name;
- }
-}
-
void MemoryDetails::StartFetch() {
ui_loop_ = MessageLoop::current();
@@ -91,106 +64,12 @@
NewRunnableMethod(this, &MemoryDetails::CollectProcessData, child_info));
}
-void MemoryDetails::CollectProcessData(
- std::vector<ProcessMemoryInformation> child_info) {
- DCHECK(MessageLoop::current() ==
- ChromeThread::GetMessageLoop(ChromeThread::FILE));
-
- // Clear old data.
- for (int index = 0; index < arraysize(g_process_template); index++)
- process_data_[index].processes.clear();
-
- SYSTEM_INFO system_info;
- GetNativeSystemInfo(&system_info);
- bool is_64bit_os =
- system_info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64;
-
- ScopedHandle snapshot(::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0));
- PROCESSENTRY32 process_entry = {sizeof(PROCESSENTRY32)};
- if (!snapshot.Get()) {
- LOG(ERROR) << "CreateToolhelp32Snaphot failed: " << GetLastError();
- return;
- }
- if (!::Process32First(snapshot, &process_entry)) {
- LOG(ERROR) << "Process32First failed: " << GetLastError();
- return;
- }
- do {
- int pid = process_entry.th32ProcessID;
- ScopedHandle handle(::OpenProcess(
- PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid));
- if (!handle.Get())
- continue;
- bool is_64bit_process = false;
- // IsWow64Process() returns FALSE for a 32bit process on a 32bit OS.
- // We need to check if the real OS is 64bit.
- if (is_64bit_os) {
- BOOL is_wow64 = FALSE;
- // IsWow64Process() is supported by Windows XP SP2 or later.
- IsWow64Process(handle, &is_wow64);
- is_64bit_process = !is_wow64;
- }
- for (int index2 = 0; index2 < arraysize(g_process_template); index2++) {
- if (_wcsicmp(process_data_[index2].process_name,
- process_entry.szExeFile) != 0)
- continue;
- if (index2 == IE_BROWSER && is_64bit_process)
- continue; // Should use IE_64BIT_BROWSER
- // Get Memory Information.
- ProcessMemoryInformation info;
- info.pid = pid;
- if (info.pid == GetCurrentProcessId())
- info.type = ChildProcessInfo::BROWSER_PROCESS;
- else
- info.type = ChildProcessInfo::UNKNOWN_PROCESS;
-
- scoped_ptr<base::ProcessMetrics> metrics;
- metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle));
- metrics->GetCommittedKBytes(&info.committed);
- metrics->GetWorkingSetKBytes(&info.working_set);
-
- // Get Version Information.
- TCHAR name[MAX_PATH];
- if (index2 == CHROME_BROWSER) {
- scoped_ptr<FileVersionInfo> version_info(
- FileVersionInfo::CreateFileVersionInfoForCurrentModule());
- if (version_info != NULL)
- info.version = version_info->file_version();
- // Check if this is one of the child processes whose data we collected
- // on the IO thread, and if so copy over that data.
- for (size_t child = 0; child < child_info.size(); child++) {
- if (child_info[child].pid != info.pid)
- continue;
- info.titles = child_info[child].titles;
- info.type = child_info[child].type;
- break;
- }
- } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) {
- std::wstring str_name(name);
- scoped_ptr<FileVersionInfo> version_info(
- FileVersionInfo::CreateFileVersionInfo(str_name));
- if (version_info != NULL) {
- info.version = version_info->product_version();
- info.product_name = version_info->product_name();
- }
- }
-
- // Add the process info to our list.
- process_data_[index2].processes.push_back(info);
- break;
- }
- } while (::Process32Next(snapshot, &process_entry));
-
- // Finally return to the browser thread.
- ui_loop_->PostTask(FROM_HERE,
- NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
-}
-
void MemoryDetails::CollectChildInfoOnUIThread() {
DCHECK(MessageLoop::current() == ui_loop_);
+ ProcessData* chrome_browser = ChromeBrowser();
// Get more information about the process.
- for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
+ for (size_t index = 0; index < chrome_browser->processes.size();
index++) {
// Check if it's a renderer, if so get the list of page titles in it and
// check if it's a diagnostics-related process. We skip all diagnostics
@@ -201,7 +80,7 @@
RenderProcessHost::end(); ++renderer_iter) {
DCHECK(renderer_iter->second);
ProcessMemoryInformation& process =
- process_data_[CHROME_BROWSER].processes[index];
+ chrome_browser->processes[index];
if (process.pid != renderer_iter->second->process().pid())
continue;
process.type = ChildProcessInfo::RENDER_PROCESS;
@@ -259,12 +138,12 @@
}
// Get rid of other Chrome processes that are from a different profile.
- for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
+ for (size_t index = 0; index < chrome_browser->processes.size();
index++) {
- if (process_data_[CHROME_BROWSER].processes[index].type ==
+ if (chrome_browser->processes[index].type ==
ChildProcessInfo::UNKNOWN_PROCESS) {
- process_data_[CHROME_BROWSER].processes.erase(
- process_data_[CHROME_BROWSER].processes.begin() + index);
+ chrome_browser->processes.erase(
+ chrome_browser->processes.begin() + index);
index--;
}
}
@@ -278,7 +157,7 @@
// Reports a set of memory metrics to UMA.
// Memory is measured in units of 10KB.
- ProcessData browser = process_data_[CHROME_BROWSER];
+ const ProcessData& browser = *ChromeBrowser();
size_t aggregate_memory = 0;
int plugin_count = 0;
int worker_count = 0;
@@ -300,6 +179,8 @@
UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample);
worker_count++;
break;
+ default:
+ break;
}
}
Index: chrome/browser/memory_details_win.cc
===================================================================
--- chrome/browser/memory_details_win.cc (revision 18899)
+++ chrome/browser/memory_details_win.cc (working copy)
@@ -5,6 +5,7 @@
#include "chrome/browser/memory_details.h"
#include <psapi.h>
+#include "app/l10n_util.h"
#include "base/file_version_info.h"
#include "base/string_util.h"
#include "chrome/browser/browser_process.h"
@@ -14,14 +15,30 @@
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/child_process_host.h"
#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
-class RenderViewHostDelegate;
+// Known browsers which we collect details for.
+enum {
+ CHROME_BROWSER = 0,
+ IE_BROWSER,
+ FIREFOX_BROWSER,
+ OPERA_BROWSER,
+ SAFARI_BROWSER,
+ IE_64BIT_BROWSER,
+ KONQUEROR_BROWSER,
+ MAX_BROWSERS
+} BrowserProcess;
// Template of static data we use for finding browser process information.
// These entries must match the ordering for MemoryDetails::BrowserProcess.
-static ProcessData
- g_process_template[MemoryDetails::MAX_BROWSERS] = {
- { L"Chromium", L"chrome.exe", },
+static ProcessData g_process_template[MAX_BROWSERS];
+
+MemoryDetails::MemoryDetails()
+ : ui_loop_(NULL) {
+ static const std::wstring google_browser_name =
+ l10n_util::GetString(IDS_PRODUCT_NAME);
+ ProcessData g_process_template[MAX_BROWSERS] = {
+ { google_browser_name.c_str(), L"chrome.exe", },
{ L"IE", L"iexplore.exe", },
{ L"Firefox", L"firefox.exe", },
{ L"Opera", L"opera.exe", },
@@ -30,63 +47,18 @@
{ L"Konqueror", L"konqueror.exe", },
};
-
-// About threading:
-//
-// This operation will hit no fewer than 3 threads.
-//
-// The ChildProcessInfo::Iterator can only be accessed from the IO thread.
-//
-// The RenderProcessHostIterator can only be accessed from the UI thread.
-//
-// This operation can take 30-100ms to complete. We never want to have
-// one task run for that long on the UI or IO threads. So, we run the
-// expensive parts of this operation over on the file thread.
-//
-
-MemoryDetails::MemoryDetails()
- : ui_loop_(NULL) {
for (int index = 0; index < arraysize(g_process_template); ++index) {
- process_data_[index].name = g_process_template[index].name;
- process_data_[index].process_name = g_process_template[index].process_name;
+ ProcessData process;
+ process.name = g_process_template[index].name;
+ process.process_name = g_process_template[index].process_name;
+ process_data_.push_back(process);
}
}
-void MemoryDetails::StartFetch() {
- ui_loop_ = MessageLoop::current();
-
- DCHECK(ui_loop_ != g_browser_process->io_thread()->message_loop());
- DCHECK(ui_loop_ != g_browser_process->file_thread()->message_loop());
-
- // In order to process this request, we need to use the plugin information.
- // However, plugin process information is only available from the IO thread.
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE,
- NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnIOThread));
+ProcessData* MemoryDetails::ChromeBrowser() {
+ return &process_data_[CHROME_BROWSER];
}
-void MemoryDetails::CollectChildInfoOnIOThread() {
- DCHECK(MessageLoop::current() ==
- ChromeThread::GetMessageLoop(ChromeThread::IO));
-
- std::vector<ProcessMemoryInformation> child_info;
-
- // Collect the list of child processes.
- for (ChildProcessHost::Iterator iter; !iter.Done(); ++iter) {
- ProcessMemoryInformation info;
- info.pid = iter->GetProcessId();
- if (!info.pid)
- continue;
-
- info.type = iter->type();
- info.titles.push_back(iter->name());
- child_info.push_back(info);
- }
-
- // Now go do expensive memory lookups from the file thread.
- ChromeThread::GetMessageLoop(ChromeThread::FILE)->PostTask(FROM_HERE,
- NewRunnableMethod(this, &MemoryDetails::CollectProcessData, child_info));
-}
-
void MemoryDetails::CollectProcessData(
std::vector<ProcessMemoryInformation> child_info) {
DCHECK(MessageLoop::current() ==
@@ -181,129 +153,3 @@
ui_loop_->PostTask(FROM_HERE,
NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread));
}
-
-void MemoryDetails::CollectChildInfoOnUIThread() {
- DCHECK(MessageLoop::current() == ui_loop_);
-
- // Get more information about the process.
- for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
- index++) {
- // Check if it's a renderer, if so get the list of page titles in it and
- // check if it's a diagnostics-related process. We skip all diagnostics
- // pages (e.g. "about:xxx" URLs). Iterate the RenderProcessHosts to find
- // the tab contents.
- RenderProcessHost::iterator renderer_iter;
- for (renderer_iter = RenderProcessHost::begin(); renderer_iter !=
- RenderProcessHost::end(); ++renderer_iter) {
- DCHECK(renderer_iter->second);
- ProcessMemoryInformation& process =
- process_data_[CHROME_BROWSER].processes[index];
- if (process.pid != renderer_iter->second->process().pid())
- continue;
- process.type = ChildProcessInfo::RENDER_PROCESS;
- // The RenderProcessHost may host multiple TabContents. Any
- // of them which contain diagnostics information make the whole
- // process be considered a diagnostics process.
- //
- // NOTE: This is a bit dangerous. We know that for now, listeners
- // are always RenderWidgetHosts. But in theory, they don't
- // have to be.
- RenderProcessHost::listeners_iterator iter;
- for (iter = renderer_iter->second->listeners_begin();
- iter != renderer_iter->second->listeners_end(); ++iter) {
- RenderWidgetHost* widget =
- static_cast<RenderWidgetHost*>(iter->second);
- DCHECK(widget);
- if (!widget || !widget->IsRenderView())
- continue;
-
- RenderViewHost* host = static_cast<RenderViewHost*>(widget);
- TabContents* contents = NULL;
- if (host->delegate())
- contents = host->delegate()->GetAsTabContents();
- if (!contents)
- continue;
- std::wstring title = UTF16ToWideHack(contents->GetTitle());
- if (!title.length())
- title = L"Untitled";
- process.titles.push_back(title);
-
- // We need to check the pending entry as well as the display_url to
- // see if it's an about:memory URL (we don't want to count these in the
- // total memory usage of the browser).
- //
- // When we reach here, about:memory will be the pending entry since we
- // haven't responded with any data such that it would be committed. If
- // you have another about:memory tab open (which would be committed),
- // we don't want to count it either, so we also check the last committed
- // entry.
- //
- // Either the pending or last committed entries can be NULL.
- const NavigationEntry* pending_entry =
- contents->controller().pending_entry();
- const NavigationEntry* last_committed_entry =
- contents->controller().GetLastCommittedEntry();
- if ((last_committed_entry &&
- LowerCaseEqualsASCII(last_committed_entry->display_url().spec(),
- chrome::kAboutMemoryURL)) ||
- (pending_entry &&
- LowerCaseEqualsASCII(pending_entry->display_url().spec(),
- chrome::kAboutMemoryURL)))
- process.is_diagnostics = true;
- }
- }
- }
-
- // Get rid of other Chrome processes that are from a different profile.
- for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size();
- index++) {
- if (process_data_[CHROME_BROWSER].processes[index].type ==
- ChildProcessInfo::UNKNOWN_PROCESS) {
- process_data_[CHROME_BROWSER].processes.erase(
- process_data_[CHROME_BROWSER].processes.begin() + index);
- index--;
- }
- }
-
- UpdateHistograms();
-
- OnDetailsAvailable();
-}
-
-void MemoryDetails::UpdateHistograms() {
- // Reports a set of memory metrics to UMA.
- // Memory is measured in units of 10KB.
-
- ProcessData browser = process_data_[CHROME_BROWSER];
- size_t aggregate_memory = 0;
- int plugin_count = 0;
- int worker_count = 0;
- for (size_t index = 0; index < browser.processes.size(); index++) {
- int sample = static_cast<int>(browser.processes[index].working_set.priv);
- aggregate_memory += sample;
- switch (browser.processes[index].type) {
- case ChildProcessInfo::BROWSER_PROCESS:
- UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample);
- break;
- case ChildProcessInfo::RENDER_PROCESS:
- UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample);
- break;
- case ChildProcessInfo::PLUGIN_PROCESS:
- UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample);
- plugin_count++;
- break;
- case ChildProcessInfo::WORKER_PROCESS:
- UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample);
- worker_count++;
- break;
- }
- }
-
- UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
- static_cast<int>(browser.processes.size()));
- UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count);
- UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count);
-
- int total_sample = static_cast<int>(aggregate_memory / 1000);
- UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample);
-}
Index: chrome/common/temp_scaffolding_stubs.cc
===================================================================
--- chrome/common/temp_scaffolding_stubs.cc (revision 22256)
+++ chrome/common/temp_scaffolding_stubs.cc (working copy)
@@ -236,6 +236,7 @@
//--------------------------------------------------------------------------
+#if defined(OS_MACOSX)
MemoryDetails::MemoryDetails() {
NOTIMPLEMENTED();
}
@@ -244,6 +245,8 @@
NOTIMPLEMENTED();
}
+#endif
+
#if defined(OS_MACOSX) || (defined(OS_LINUX) && defined(TOOLKIT_VIEWS))
// This should prompt the user if she wants to allow more than one concurrent
// download per tab. Until this is in place, always allow multiple downloads.
Index: chrome/chrome.gyp
===================================================================
--- chrome/chrome.gyp (revision 22256)
+++ chrome/chrome.gyp (working copy)
@@ -1292,6 +1292,8 @@
'browser/login_prompt_gtk.cc',
'browser/login_prompt_win.cc',
'browser/memory_details.cc',
+ 'browser/memory_details_linux.cc',
+ 'browser/memory_details_win.cc',
'browser/memory_details.h',
'browser/meta_table_helper.cc',
'browser/meta_table_helper.h',
@@ -1978,6 +1980,7 @@
'browser/download/download_request_dialog_delegate_win.cc',
'browser/jankometer.cc',
'browser/login_prompt.cc',
+ 'browser/memory_details.cc',
'browser/password_manager/password_store_gnome.h',
'browser/password_manager/password_store_gnome.cc',
'browser/password_manager/password_store_kwallet.h',
@@ -2353,7 +2356,6 @@
'browser/ime_input.cc',
'browser/importer/ie_importer.cc',
'browser/jumplist.cc',
- 'browser/memory_details.cc',
'browser/modal_html_dialog_delegate.cc',
'browser/sandbox_policy.cc',
'browser/tab_contents/web_drag_source.cc',