diff options
author | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-01 18:50:19 +0000 |
---|---|---|
committer | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-01 18:50:19 +0000 |
commit | 0dd5dda0318cfbe06bc73f4a24a5e6b6b8e3fc30 (patch) | |
tree | 8bff32973fdd833232139ad6ac4bec54137b12a8 /chrome | |
parent | 83e214c531938502ad094e440f2dfd9a48fb007a (diff) | |
download | chromium_src-0dd5dda0318cfbe06bc73f4a24a5e6b6b8e3fc30.zip chromium_src-0dd5dda0318cfbe06bc73f4a24a5e6b6b8e3fc30.tar.gz chromium_src-0dd5dda0318cfbe06bc73f4a24a5e6b6b8e3fc30.tar.bz2 |
Add framework of MemoryPurger, a class to dump memory from everywhere possible. Currently does nothing.
This also adds a "Purge memory" button to the task manager when run with --purge-memory-button, which can be used to test the functionality.
BUG=23400
TEST=Run with --purge-memory-button, open the task manager and see a new button. Click it to toggle it to "Reset purge", and click again to toggle back.
Review URL: http://codereview.chromium.org/259003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@27751 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser_main.cc | 3 | ||||
-rw-r--r-- | chrome/browser/memory_purger.cc | 61 | ||||
-rw-r--r-- | chrome/browser/memory_purger.h | 36 | ||||
-rw-r--r-- | chrome/browser/views/task_manager_view.cc | 41 | ||||
-rwxr-xr-x | chrome/chrome.gyp | 2 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 7 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 |
7 files changed, 146 insertions, 5 deletions
diff --git a/chrome/browser/browser_main.cc b/chrome/browser/browser_main.cc index 1138ade..03ee3f9 100644 --- a/chrome/browser/browser_main.cc +++ b/chrome/browser/browser_main.cc @@ -35,6 +35,7 @@ #include "chrome/browser/dom_ui/chrome_url_data_manager.h" #include "chrome/browser/extensions/extension_protocols.h" #include "chrome/browser/first_run.h" +#include "chrome/browser/memory_purger.h" #include "chrome/browser/metrics/metrics_service.h" #include "chrome/browser/net/dns_global.h" #include "chrome/browser/net/metadata_url_request.h" @@ -268,6 +269,8 @@ int BrowserMain(const MainFunctionParams& parameters) { // timer settings. But it's necessary only on Windows. base::Time::StartSystemMonitorObserver(); #endif // defined(OS_WIN) + // Start the MemoryPurger, which observes the SystemMonitor as well. + MemoryPurger::GetSingleton(); // Initialize statistical testing infrastructure. FieldTrialList field_trial; diff --git a/chrome/browser/memory_purger.cc b/chrome/browser/memory_purger.cc new file mode 100644 index 0000000..2fc5b9e --- /dev/null +++ b/chrome/browser/memory_purger.cc @@ -0,0 +1,61 @@ +// Copyright (c) 2009 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_purger.h" + +#include "base/singleton.h" + +// static +MemoryPurger* MemoryPurger::GetSingleton() { + return Singleton<MemoryPurger>::get(); +} + +void MemoryPurger::OnSuspend() { + // TODO: + // + // * For the browser process: + // * Commit all the sqlite databases and unload them from memory; at the + // very least, do this with the history system, then use the prefetch trick to + // reload it on wake. + // * Repeatedly call the V8 idle notification until it returns true + // ("nothing more to free"). Note that it makes more sense to do this than to + // implement a new "delete everything" pass because object references make it + // difficult to free everything possible in just one pass. + // * Dump the backing stores. + // * Destroy the spellcheck object. + // * Tell tcmalloc to free everything it can. (This is vague since it's not + // clear to me what this means; Jim, Mike, and Anton will know more here. + // Also, do we need to do this in each renderer process too?) + // + // * For each renderer process: + // * Repeatedly call the V8 idle notification until it returns true. + // * Tell the WebCore cache manager to set its global limit to 0, which + // should flush the image/script/css/etc. caches. + // * Destroy the WebCore glyph caches. + // * Tell tcmalloc to free everything it can. + // + // Concern: If we tell a bunch of renderer processes to destroy their data, + // they may have to page everything in to do it, which could end up + // overflowing the amount of time we have to work with. +} + +void MemoryPurger::OnResume() { + // TODO: + // + // * For the browser process: + // * Reload the history system and any other needed sqlite databases. + // + // * For each renderer process: + // * Reset the WebCore cache manager global limit to the default. +} + +MemoryPurger::MemoryPurger() { + base::SystemMonitor::Get()->AddObserver(this); +} + +MemoryPurger::~MemoryPurger() { + base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); + if (system_monitor) + system_monitor->RemoveObserver(this); +} diff --git a/chrome/browser/memory_purger.h b/chrome/browser/memory_purger.h new file mode 100644 index 0000000..1403add --- /dev/null +++ b/chrome/browser/memory_purger.h @@ -0,0 +1,36 @@ +// Copyright (c) 2009 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. + +// MemoryPurger is designed to be used a singleton which listens for +// suspend/resume notifications and purges as much memory as possible before +// suspend. The hope is that it will be faster to recalculate or manually +// reload this data on resume than to let the OS page everything out and then +// fault it back in. + +#ifndef CHROME_BROWSER_MEMORY_PURGER_H_ +#define CHROME_BROWSER_MEMORY_PURGER_H_ + +#include "base/system_monitor.h" + +template<typename Type> +struct DefaultSingletonTraits; + +class MemoryPurger : public base::SystemMonitor::PowerObserver { +public: + static MemoryPurger* GetSingleton(); + + // PowerObserver + virtual void OnSuspend(); + virtual void OnResume(); + + private: + MemoryPurger(); + virtual ~MemoryPurger(); + + friend struct DefaultSingletonTraits<MemoryPurger>; + + DISALLOW_COPY_AND_ASSIGN(MemoryPurger); +}; + +#endif // CHROME_BROWSER_MEMORY_PURGER_H_ diff --git a/chrome/browser/views/task_manager_view.cc b/chrome/browser/views/task_manager_view.cc index 195a67e..d605b77 100644 --- a/chrome/browser/views/task_manager_view.cc +++ b/chrome/browser/views/task_manager_view.cc @@ -11,7 +11,9 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_window.h" +#include "chrome/browser/memory_purger.h" #include "chrome/browser/views/browser_dialogs.h" +#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/pref_service.h" #include "chrome/common/url_constants.h" @@ -242,6 +244,8 @@ class TaskManagerView : public views::View, // Restores saved always on top state from a previous session. bool GetSavedAlwaysOnTopState(bool* always_on_top) const; + views::NativeButton* purge_memory_button_; + bool purge_memory_button_in_purge_mode_; views::NativeButton* kill_button_; views::Link* about_memory_link_; views::GroupTableView* tab_table_; @@ -273,7 +277,9 @@ TaskManagerView* TaskManagerView::instance_ = NULL; TaskManagerView::TaskManagerView() - : task_manager_(TaskManager::GetInstance()), + : purge_memory_button_(NULL), + purge_memory_button_in_purge_mode_(true), + task_manager_(TaskManager::GetInstance()), model_(TaskManager::GetInstance()->model()), is_always_on_top_(false) { Init(); @@ -338,6 +344,10 @@ void TaskManagerView::Init() { UpdateStatsCounters(); tab_table_->SetObserver(this); SetContextMenuController(this); + // If we're running with --purge-memory-button, add a "Purge memory" button. + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kPurgeMemoryButton)) + purge_memory_button_ = new views::NativeButton(this, L"Purge memory"); kill_button_ = new views::NativeButton( this, l10n_util::GetString(IDS_TASK_MANAGER_KILL)); kill_button_->AddAccelerator(views::Accelerator(base::VKEY_E, @@ -384,10 +394,14 @@ void TaskManagerView::ViewHierarchyChanged(bool is_add, if (child == this) { if (is_add) { parent->AddChildView(about_memory_link_); + if (purge_memory_button_) + parent->AddChildView(purge_memory_button_); parent->AddChildView(kill_button_); AddChildView(tab_table_); } else { parent->RemoveChildView(kill_button_); + if (purge_memory_button_) + parent->RemoveChildView(purge_memory_button_); parent->RemoveChildView(about_memory_link_); } } @@ -415,6 +429,13 @@ void TaskManagerView::Layout() { prefered_width, prefered_height); + if (purge_memory_button_) { + size = purge_memory_button_->GetPreferredSize(); + purge_memory_button_->SetBounds( + kill_button_->x() - size.width() - kUnrelatedControlHorizontalSpacing, + y_buttons, size.width(), size.height()); + } + size = about_memory_link_->GetPreferredSize(); int link_prefered_width = size.width(); int link_prefered_height = size.height(); @@ -449,10 +470,20 @@ void TaskManagerView::Show() { // ButtonListener implementation. void TaskManagerView::ButtonPressed( views::Button* sender, const views::Event& event) { - DCHECK(sender == kill_button_); - for (views::TableSelectionIterator iter = tab_table_->SelectionBegin(); - iter != tab_table_->SelectionEnd(); ++iter) { - task_manager_->KillProcess(*iter); + if (purge_memory_button_ && (sender == purge_memory_button_)) { + if (purge_memory_button_in_purge_mode_) { + MemoryPurger::GetSingleton()->OnSuspend(); + purge_memory_button_->SetLabel(L"Reset purger"); + } else { + MemoryPurger::GetSingleton()->OnResume(); + purge_memory_button_->SetLabel(L"Purge Memory"); + } + purge_memory_button_in_purge_mode_ = !purge_memory_button_in_purge_mode_; + } else { + DCHECK_EQ(sender, kill_button_); + for (views::TableSelectionIterator iter = tab_table_->SelectionBegin(); + iter != tab_table_->SelectionEnd(); ++iter) + task_manager_->KillProcess(*iter); } } diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 5e7580c..d5c9b15 100755 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -1627,6 +1627,8 @@ 'browser/memory_details_linux.cc', 'browser/memory_details_win.cc', 'browser/memory_details.h', + 'browser/memory_purger.cc', + 'browser/memory_purger.h', 'browser/meta_table_helper.cc', 'browser/meta_table_helper.h', 'browser/metrics/metrics_log.cc', diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index b94177d..1bbbf81 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -292,6 +292,13 @@ const wchar_t kTabCountToLoadOnSessionRestore[]= // all memory allocations during the run. const wchar_t kMemoryProfiling[] = L"memory-profile"; +// Adds a "Purge memory" button to the Task Manager, which tries to dump as much +// memory as possible. This is mostly useful for testing how well the +// MemoryPurger functionality (which is normally triggered on Suspend) works. +// +// NOTE: This is only implemented for Views. +const wchar_t kPurgeMemoryButton[] = L"purge-memory-button"; + // By default, cookies are not allowed on file://. They are needed in for // testing, for example page cycler and layout tests. See bug 1157243. const wchar_t kEnableFileCookies[] = L"enable-file-cookies"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 8774a0f..19b9b06 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -100,6 +100,7 @@ extern const wchar_t kEnableExtensionTimelineApi[]; extern const wchar_t kTabCountToLoadOnSessionRestore[]; extern const wchar_t kMemoryProfiling[]; +extern const wchar_t kPurgeMemoryButton[]; extern const wchar_t kEnableFileCookies[]; |