blob: 6e2c14ffc0dc1100725212f84ee3b26feba4083e [file] [log] [blame]
[email protected]6b4329a2012-01-25 10:51:281// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]0dd5dda02009-10-01 18:50:192// 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_purger.h"
6
[email protected]61a9b2d82010-02-26 00:31:087#include <set>
8
[email protected]24d69692011-10-21 18:26:519#include "base/bind.h"
[email protected]34b99632011-01-01 01:01:0610#include "base/threading/thread.h"
[email protected]3148c5d2009-11-18 19:32:5811#include "chrome/browser/browser_process.h"
12#include "chrome/browser/history/history.h"
[email protected]8ecad5e2010-12-02 21:18:3313#include "chrome/browser/profiles/profile_manager.h"
[email protected]1962a9c2012-02-21 21:56:1514#include "chrome/browser/safe_browsing/safe_browsing_service.h"
[email protected]71b73f02011-04-06 15:57:2915#include "chrome/browser/ui/browser_list.h"
[email protected]3148c5d2009-11-18 19:32:5816#include "chrome/browser/webdata/web_data_service.h"
17#include "chrome/common/render_messages.h"
[email protected]f3b1a082011-11-18 00:34:3018#include "content/public/browser/render_process_host.h"
[email protected]9c1662b2012-03-06 15:44:3319#include "content/public/browser/render_widget_host.h"
[email protected]1962a9c2012-02-21 21:56:1520#include "content/public/browser/resource_context.h"
[email protected]3148c5d2009-11-18 19:32:5821#include "net/proxy/proxy_resolver.h"
[email protected]6104ea5d2011-04-27 21:37:1222#include "net/proxy/proxy_service.h"
[email protected]3148c5d2009-11-18 19:32:5823#include "net/url_request/url_request_context.h"
[email protected]abe2c032011-03-31 18:49:3424#include "net/url_request/url_request_context_getter.h"
[email protected]451c89d62012-03-13 17:13:0025#include "third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h"
[email protected]3148c5d2009-11-18 19:32:5826
[email protected]55eb70e762012-02-20 17:38:3927using content::BrowserContext;
[email protected]631bb742011-11-02 11:29:3928using content::BrowserThread;
[email protected]1962a9c2012-02-21 21:56:1529using content::ResourceContext;
[email protected]631bb742011-11-02 11:29:3930
[email protected]3148c5d2009-11-18 19:32:5831// PurgeMemoryHelper -----------------------------------------------------------
32
33// This is a small helper class used to ensure that the objects we want to use
34// on multiple threads are properly refed, so they don't get deleted out from
35// under us.
36class PurgeMemoryIOHelper
37 : public base::RefCountedThreadSafe<PurgeMemoryIOHelper> {
38 public:
[email protected]b864a412011-07-07 10:51:4839 PurgeMemoryIOHelper() {
[email protected]1962a9c2012-02-21 21:56:1540 safe_browsing_service_ = g_browser_process->safe_browsing_service();
[email protected]3148c5d2009-11-18 19:32:5841 }
42
[email protected]00cd9c42010-11-02 20:15:5743 void AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3444 scoped_refptr<net::URLRequestContextGetter> request_context_getter);
[email protected]3148c5d2009-11-18 19:32:5845
46 void PurgeMemoryOnIOThread();
47
48 private:
[email protected]649d1c02012-04-27 02:56:2149 friend class base::RefCountedThreadSafe<PurgeMemoryIOHelper>;
[email protected]3148c5d2009-11-18 19:32:5850
[email protected]649d1c02012-04-27 02:56:2151 virtual ~PurgeMemoryIOHelper() {}
52
53 typedef scoped_refptr<net::URLRequestContextGetter> RequestContextGetter;
[email protected]1962a9c2012-02-21 21:56:1554 std::vector<RequestContextGetter> request_context_getters_;
[email protected]649d1c02012-04-27 02:56:2155
[email protected]1962a9c2012-02-21 21:56:1556 scoped_refptr<SafeBrowsingService> safe_browsing_service_;
[email protected]3148c5d2009-11-18 19:32:5857
58 DISALLOW_COPY_AND_ASSIGN(PurgeMemoryIOHelper);
59};
60
61void PurgeMemoryIOHelper::AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3462 scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
[email protected]1962a9c2012-02-21 21:56:1563 request_context_getters_.push_back(request_context_getter);
64}
65
[email protected]3148c5d2009-11-18 19:32:5866void PurgeMemoryIOHelper::PurgeMemoryOnIOThread() {
67 // Ask ProxyServices to purge any memory they can (generally garbage in the
68 // wrapped ProxyResolver's JS engine).
[email protected]1962a9c2012-02-21 21:56:1569 for (size_t i = 0; i < request_context_getters_.size(); ++i) {
70 request_context_getters_[i]->GetURLRequestContext()->proxy_service()->
71 PurgeMemory();
72 }
[email protected]3148c5d2009-11-18 19:32:5873
[email protected]69c87ac2012-03-28 19:38:3074#if defined(ENABLE_SAFE_BROWSING)
[email protected]1962a9c2012-02-21 21:56:1575 safe_browsing_service_->PurgeMemory();
[email protected]69c87ac2012-03-28 19:38:3076#endif
[email protected]3148c5d2009-11-18 19:32:5877}
78
79// -----------------------------------------------------------------------------
[email protected]0dd5dda02009-10-01 18:50:1980
81// static
[email protected]3148c5d2009-11-18 19:32:5882void MemoryPurger::PurgeAll() {
83 PurgeBrowser();
84 PurgeRenderers();
85
86 // TODO(pkasting):
87 // * Tell the plugin processes to release their free memory? Other stuff?
88 // * Enumerate what other processes exist and what to do for them.
[email protected]0dd5dda02009-10-01 18:50:1989}
90
[email protected]3148c5d2009-11-18 19:32:5891// static
92void MemoryPurger::PurgeBrowser() {
93 // Dump the backing stores.
[email protected]eaabba22012-03-07 15:02:1194 content::RenderWidgetHost::RemoveAllBackingStores();
[email protected]3148c5d2009-11-18 19:32:5895
96 // Per-profile cleanup.
97 scoped_refptr<PurgeMemoryIOHelper> purge_memory_io_helper(
[email protected]b864a412011-07-07 10:51:4898 new PurgeMemoryIOHelper());
[email protected]3148c5d2009-11-18 19:32:5899 ProfileManager* profile_manager = g_browser_process->profile_manager();
[email protected]844a1002011-04-19 11:37:21100 std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
101 for (size_t i = 0; i < profiles.size(); ++i) {
[email protected]3148c5d2009-11-18 19:32:58102 purge_memory_io_helper->AddRequestContextGetter(
[email protected]844a1002011-04-19 11:37:21103 make_scoped_refptr(profiles[i]->GetRequestContext()));
[email protected]3148c5d2009-11-18 19:32:58104
105 // NOTE: Some objects below may be duplicates across profiles. We could
106 // conceivably put all these in sets and then iterate over the sets.
107
108 // Unload all history backends (freeing memory used to cache sqlite).
109 // Spinning up the history service is expensive, so we avoid doing it if it
110 // hasn't been done already.
111 HistoryService* history_service =
[email protected]844a1002011-04-19 11:37:21112 profiles[i]->GetHistoryServiceWithoutCreating();
[email protected]3148c5d2009-11-18 19:32:58113 if (history_service)
114 history_service->UnloadBackend();
115
116 // Unload all web databases (freeing memory used to cache sqlite).
117 WebDataService* web_data_service =
[email protected]844a1002011-04-19 11:37:21118 profiles[i]->GetWebDataServiceWithoutCreating();
[email protected]3148c5d2009-11-18 19:32:58119 if (web_data_service)
120 web_data_service->UnloadDatabase();
121
[email protected]6e2d3d22012-02-24 18:10:36122 BrowserContext::PurgeMemory(profiles[i]);
[email protected]3148c5d2009-11-18 19:32:58123 }
124
[email protected]24d69692011-10-21 18:26:51125 BrowserThread::PostTask(
126 BrowserThread::IO, FROM_HERE,
127 base::Bind(&PurgeMemoryIOHelper::PurgeMemoryOnIOThread,
128 purge_memory_io_helper.get()));
[email protected]3148c5d2009-11-18 19:32:58129
130 // TODO(pkasting):
131 // * Purge AppCache memory. Not yet implemented sufficiently.
132 // * Browser-side DatabaseTracker. Not implemented sufficiently.
133
[email protected]1fd5302c2011-05-28 04:06:43134#if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
[email protected]3148c5d2009-11-18 19:32:58135 // Tell tcmalloc to release any free pages it's still holding.
[email protected]0dd5dda02009-10-01 18:50:19136 //
[email protected]3148c5d2009-11-18 19:32:58137 // TODO(pkasting): A lot of the above calls kick off actions on other threads.
138 // Maybe we should find a way to avoid calling this until those actions
139 // complete?
140 MallocExtension::instance()->ReleaseFreeMemory();
141#endif
[email protected]0dd5dda02009-10-01 18:50:19142}
143
[email protected]3148c5d2009-11-18 19:32:58144// static
145void MemoryPurger::PurgeRenderers() {
146 // Direct all renderers to free everything they can.
[email protected]0dd5dda02009-10-01 18:50:19147 //
[email protected]3148c5d2009-11-18 19:32:58148 // Concern: Telling a bunch of renderer processes to destroy their data may
149 // cause them to page everything in to do it, which could take a lot of time/
150 // cause jank.
[email protected]f3b1a082011-11-18 00:34:30151 for (content::RenderProcessHost::iterator i(
152 content::RenderProcessHost::AllHostsIterator());
[email protected]3148c5d2009-11-18 19:32:58153 !i.IsAtEnd(); i.Advance())
154 PurgeRendererForHost(i.GetCurrentValue());
[email protected]0dd5dda02009-10-01 18:50:19155}
156
[email protected]3148c5d2009-11-18 19:32:58157// static
[email protected]f3b1a082011-11-18 00:34:30158void MemoryPurger::PurgeRendererForHost(content::RenderProcessHost* host) {
[email protected]3148c5d2009-11-18 19:32:58159 // Direct the renderer to free everything it can.
[email protected]2ccf45c2011-08-19 23:35:50160 host->Send(new ChromeViewMsg_PurgeMemory());
[email protected]0dd5dda02009-10-01 18:50:19161}