summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/process_util.h20
-rw-r--r--base/process_util_linux.cc36
-rw-r--r--chrome/browser/chromeos/status/memory_menu_button.cc68
-rw-r--r--chrome/browser/chromeos/status/memory_menu_button.h32
4 files changed, 109 insertions, 47 deletions
diff --git a/base/process_util.h b/base/process_util.h
index acaa2d7..b98e266 100644
--- a/base/process_util.h
+++ b/base/process_util.h
@@ -657,11 +657,23 @@ class BASE_EXPORT ProcessMetrics {
};
#if defined(OS_LINUX)
+// Data from /proc/meminfo about system-wide memory consumption.
+// Values are in KB.
+struct SystemMemoryInfoKB {
+ SystemMemoryInfoKB() : total(0), free(0), buffers(0), cached(0),
+ active_anon(0), inactive_anon(0), shmem(0) {}
+ int total;
+ int free;
+ int buffers;
+ int cached;
+ int active_anon;
+ int inactive_anon;
+ int shmem;
+};
// Retrieves data from /proc/meminfo about system-wide memory consumption.
-// Values are in KB. Returns true on success.
-BASE_EXPORT bool GetSystemMemoryInfo(int* total_kb, int* free_kb,
- int* buffers_kb, int* cache_kb,
- int* shmem_kb);
+// Fills in the provided |meminfo| structure. Returns true on success.
+// Exposed for memory debugging widget.
+BASE_EXPORT bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo);
#endif
// Returns the memory committed by the system in KBytes.
diff --git a/base/process_util_linux.cc b/base/process_util_linux.cc
index 3ea383f..1f71f4d 100644
--- a/base/process_util_linux.cc
+++ b/base/process_util_linux.cc
@@ -558,12 +558,13 @@ namespace {
const size_t kMemTotalIndex = 1;
const size_t kMemFreeIndex = 4;
const size_t kMemBuffersIndex = 7;
-const size_t kMemCacheIndex = 10;
+const size_t kMemCachedIndex = 10;
+const size_t kMemActiveAnonIndex = 22;
+const size_t kMemInactiveAnonIndex = 25;
} // namespace
-bool GetSystemMemoryInfo(int* mem_total, int* mem_free, int* mem_buffers,
- int* mem_cache, int* shmem) {
+bool GetSystemMemoryInfo(SystemMemoryInfoKB* meminfo) {
// Synchronously reading files in /proc is safe.
base::ThreadRestrictions::ScopedAllowIO allow_io;
@@ -577,7 +578,7 @@ bool GetSystemMemoryInfo(int* mem_total, int* mem_free, int* mem_buffers,
std::vector<std::string> meminfo_fields;
SplitStringAlongWhitespace(meminfo_data, &meminfo_fields);
- if (meminfo_fields.size() < kMemCacheIndex) {
+ if (meminfo_fields.size() < kMemCachedIndex) {
LOG(WARNING) << "Failed to parse /proc/meminfo. Only found " <<
meminfo_fields.size() << " fields.";
return false;
@@ -586,20 +587,25 @@ bool GetSystemMemoryInfo(int* mem_total, int* mem_free, int* mem_buffers,
DCHECK_EQ(meminfo_fields[kMemTotalIndex-1], "MemTotal:");
DCHECK_EQ(meminfo_fields[kMemFreeIndex-1], "MemFree:");
DCHECK_EQ(meminfo_fields[kMemBuffersIndex-1], "Buffers:");
- DCHECK_EQ(meminfo_fields[kMemCacheIndex-1], "Cached:");
-
- base::StringToInt(meminfo_fields[kMemTotalIndex], mem_total);
- base::StringToInt(meminfo_fields[kMemFreeIndex], mem_free);
- base::StringToInt(meminfo_fields[kMemBuffersIndex], mem_buffers);
- base::StringToInt(meminfo_fields[kMemCacheIndex], mem_cache);
+ DCHECK_EQ(meminfo_fields[kMemCachedIndex-1], "Cached:");
+ DCHECK_EQ(meminfo_fields[kMemActiveAnonIndex-1], "Active(anon):");
+ DCHECK_EQ(meminfo_fields[kMemInactiveAnonIndex-1], "Inactive(anon):");
+
+ base::StringToInt(meminfo_fields[kMemTotalIndex], &meminfo->total);
+ base::StringToInt(meminfo_fields[kMemFreeIndex], &meminfo->free);
+ base::StringToInt(meminfo_fields[kMemBuffersIndex], &meminfo->buffers);
+ base::StringToInt(meminfo_fields[kMemCachedIndex], &meminfo->cached);
+ base::StringToInt(meminfo_fields[kMemActiveAnonIndex], &meminfo->active_anon);
+ base::StringToInt(meminfo_fields[kMemInactiveAnonIndex],
+ &meminfo->inactive_anon);
#if defined(OS_CHROMEOS)
// Chrome OS has a tweaked kernel that allows us to query Shmem, which is
// usually video memory otherwise invisible to the OS. Unfortunately, the
// meminfo format varies on different hardware so we have to search for the
// string. It always appears after "Cached:".
- for (size_t i = kMemCacheIndex+2; i < meminfo_fields.size(); i += 3) {
+ for (size_t i = kMemCachedIndex+2; i < meminfo_fields.size(); i += 3) {
if (meminfo_fields[i] == "Shmem:") {
- base::StringToInt(meminfo_fields[i+1], shmem);
+ base::StringToInt(meminfo_fields[i+1], &meminfo->shmem);
break;
}
}
@@ -608,10 +614,10 @@ bool GetSystemMemoryInfo(int* mem_total, int* mem_free, int* mem_buffers,
}
size_t GetSystemCommitCharge() {
- int total, free, buffers, cache, shmem;
- if (!GetSystemMemoryInfo(&total, &free, &buffers, &cache, &shmem))
+ SystemMemoryInfoKB meminfo;
+ if (!GetSystemMemoryInfo(&meminfo))
return 0;
- return total - free - buffers - cache;
+ return meminfo.total - meminfo.free - meminfo.buffers - meminfo.cached;
}
namespace {
diff --git a/chrome/browser/chromeos/status/memory_menu_button.cc b/chrome/browser/chromeos/status/memory_menu_button.cc
index 606ebc1..634c985 100644
--- a/chrome/browser/chromeos/status/memory_menu_button.cc
+++ b/chrome/browser/chromeos/status/memory_menu_button.cc
@@ -8,6 +8,8 @@
#include "base/stringprintf.h"
#include "chrome/browser/chromeos/status/status_area_host.h"
#include "chrome/browser/memory_purger.h"
+#include "content/browser/renderer_host/render_process_host.h"
+#include "content/common/notification_service.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "views/widget/widget.h"
@@ -33,11 +35,12 @@ const int kUpdateIntervalSeconds = 5;
MemoryMenuButton::MemoryMenuButton(StatusAreaHost* host)
: StatusAreaButton(host, this),
- mem_total_(0),
- shmem_(0),
- mem_free_(0),
- mem_buffers_(0),
- mem_cache_(0) {
+ meminfo_(new base::SystemMemoryInfoKB()),
+ renderer_kills_(0) {
+ // Track renderer kills, as the kernel OOM killer will start to kill our
+ // renderers as we run out of memory.
+ registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ NotificationService::AllSources());
UpdateTextAndSetNextTimer();
}
@@ -52,17 +55,20 @@ void MemoryMenuButton::UpdateTextAndSetNextTimer() {
}
void MemoryMenuButton::UpdateText() {
- base::GetSystemMemoryInfo(&mem_total_, &mem_free_, &mem_buffers_, &mem_cache_,
- &shmem_);
- std::wstring label = base::StringPrintf(L"%d MB", mem_free_ / 1024);
+ base::GetSystemMemoryInfo(meminfo_.get());
+ // "Anonymous" memory, meaning not mapped to a file (which has a name),
+ // represents memory that has been dynamically allocated to a process.
+ // It thus approximates heap memory usage across all processes.
+ int anon_kb = meminfo_->active_anon + meminfo_->inactive_anon;
+ std::wstring label = base::StringPrintf(L"%d MB (%d)",
+ anon_kb / 1024,
+ renderer_kills_);
SetText(label);
std::wstring tooltip = base::StringPrintf(
- L"%d MB total\n%d MB free\n%d MB buffers\n%d MB cache\n%d MB shmem",
- mem_total_ / 1024,
- mem_free_ / 1024,
- mem_buffers_ / 1024,
- mem_cache_ / 1024,
- shmem_ / 1024);
+ L"%d MB allocated (anonymous)\n"
+ L"%d renderer kill(s)",
+ anon_kb / 1024,
+ renderer_kills_);
SetTooltipText(tooltip);
SchedulePaint();
}
@@ -71,15 +77,15 @@ void MemoryMenuButton::UpdateText() {
std::wstring MemoryMenuButton::GetLabel(int id) const {
switch (id) {
case MEM_TOTAL_ITEM:
- return StringPrintf(L"%d MB total", mem_total_ / 1024);
+ return StringPrintf(L"%d MB total", meminfo_->total / 1024);
case MEM_FREE_ITEM:
- return StringPrintf(L"%d MB free", mem_free_ / 1024);
+ return StringPrintf(L"%d MB free", meminfo_->free / 1024);
case MEM_BUFFERS_ITEM:
- return StringPrintf(L"%d MB buffers", mem_buffers_ / 1024);
+ return StringPrintf(L"%d MB buffers", meminfo_->buffers / 1024);
case MEM_CACHE_ITEM:
- return StringPrintf(L"%d MB cache", mem_cache_ / 1024);
+ return StringPrintf(L"%d MB cache", meminfo_->cached / 1024);
case SHMEM_ITEM:
- return StringPrintf(L"%d MB shmem", shmem_ / 1024);
+ return StringPrintf(L"%d MB shmem", meminfo_->shmem / 1024);
case PURGE_MEMORY_ITEM:
return L"Purge memory";
default:
@@ -146,4 +152,28 @@ void MemoryMenuButton::EnsureMenu() {
menu_->AppendDelegateMenuItem(PURGE_MEMORY_ITEM);
}
+/////////////////////////////////////////////////////////////////////////////
+// NotificationObserver overrides.
+
+void MemoryMenuButton::Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ switch (type) {
+ case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: {
+ RenderProcessHost::RendererClosedDetails* process_details =
+ Details<RenderProcessHost::RendererClosedDetails>(details).ptr();
+ if (process_details->status ==
+ base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
+ renderer_kills_++;
+ // A kill is a very interesting event, so repaint immediately.
+ UpdateText();
+ }
+ break;
+ }
+ default:
+ NOTREACHED() << L"Received unexpected notification";
+ break;
+ }
+}
+
} // namespace chromeos
diff --git a/chrome/browser/chromeos/status/memory_menu_button.h b/chrome/browser/chromeos/status/memory_menu_button.h
index feddcac..d404c39 100644
--- a/chrome/browser/chromeos/status/memory_menu_button.h
+++ b/chrome/browser/chromeos/status/memory_menu_button.h
@@ -9,9 +9,15 @@
#include "base/memory/scoped_ptr.h"
#include "base/timer.h"
#include "chrome/browser/chromeos/status/status_area_button.h"
+#include "content/common/notification_observer.h"
+#include "content/common/notification_registrar.h"
#include "views/controls/menu/menu_delegate.h"
#include "views/controls/menu/view_menu_delegate.h"
+namespace base {
+struct SystemMemoryInfoKB;
+}
+
namespace views {
class MenuItemView;
}
@@ -23,7 +29,8 @@ class StatusAreaHost;
// Memory debugging display that lives in the status area.
class MemoryMenuButton : public StatusAreaButton,
public views::MenuDelegate,
- public views::ViewMenuDelegate {
+ public views::ViewMenuDelegate,
+ public NotificationObserver {
public:
explicit MemoryMenuButton(StatusAreaHost* host);
virtual ~MemoryMenuButton();
@@ -33,6 +40,14 @@ class MemoryMenuButton : public StatusAreaButton,
virtual bool IsCommandEnabled(int id) const OVERRIDE;
virtual void ExecuteCommand(int id) OVERRIDE;
+ // views::ViewMenuDelegate implementation.
+ virtual void RunMenu(views::View* source, const gfx::Point& pt) OVERRIDE;
+
+ // NotificationObserver overrides.
+ virtual void Observe(int type,
+ const NotificationSource& source,
+ const NotificationDetails& details) OVERRIDE;
+
// Updates the text on the menu button.
void UpdateText();
@@ -40,9 +55,6 @@ class MemoryMenuButton : public StatusAreaButton,
virtual int horizontal_padding() OVERRIDE;
private:
- // views::ViewMenuDelegate implementation.
- virtual void RunMenu(views::View* source, const gfx::Point& pt);
-
// Create and initialize menu if not already present.
void EnsureMenu();
@@ -55,11 +67,13 @@ class MemoryMenuButton : public StatusAreaButton,
// constructor.
scoped_ptr<views::MenuItemView> menu_;
- int mem_total_;
- int shmem_; // video driver memory, hidden from OS
- int mem_free_;
- int mem_buffers_;
- int mem_cache_;
+ // Raw data from /proc/meminfo
+ scoped_ptr<base::SystemMemoryInfoKB> meminfo_;
+
+ NotificationRegistrar registrar_;
+
+ // Number of renderer kills we have observed.
+ int renderer_kills_;
DISALLOW_COPY_AND_ASSIGN(MemoryMenuButton);
};