blob: 291aa4d0f1a8e8deccffa2d95b133958914d2aba [file] [log] [blame]
[email protected]b3841c502011-03-09 01:21:311// Copyright (c) 2011 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]34b99632011-01-01 01:01:069#include "base/threading/thread.h"
[email protected]3148c5d2009-11-18 19:32:5810#include "chrome/browser/browser_list.h"
11#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]3148c5d2009-11-18 19:32:5814#include "chrome/browser/safe_browsing/safe_browsing_service.h"
15#include "chrome/browser/webdata/web_data_service.h"
[email protected]3148c5d2009-11-18 19:32:5816#include "chrome/common/render_messages.h"
[email protected]567812d2011-02-24 17:40:5017#include "content/browser/in_process_webkit/webkit_context.h"
18#include "content/browser/renderer_host/backing_store_manager.h"
19#include "content/browser/renderer_host/render_process_host.h"
20#include "content/browser/renderer_host/resource_dispatcher_host.h"
[email protected]b3841c502011-03-09 01:21:3121#include "content/common/notification_service.h"
[email protected]3148c5d2009-11-18 19:32:5822#include "net/proxy/proxy_resolver.h"
23#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]1b1f3eb2009-12-01 13:48:0425#include "third_party/tcmalloc/chromium/src/google/malloc_extension.h"
[email protected]3148c5d2009-11-18 19:32:5826#include "v8/include/v8.h"
27
28// PurgeMemoryHelper -----------------------------------------------------------
29
30// This is a small helper class used to ensure that the objects we want to use
31// on multiple threads are properly refed, so they don't get deleted out from
32// under us.
33class PurgeMemoryIOHelper
34 : public base::RefCountedThreadSafe<PurgeMemoryIOHelper> {
35 public:
36 explicit PurgeMemoryIOHelper(SafeBrowsingService* safe_browsing_service)
37 : safe_browsing_service_(safe_browsing_service) {
38 }
39
[email protected]00cd9c42010-11-02 20:15:5740 void AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3441 scoped_refptr<net::URLRequestContextGetter> request_context_getter);
[email protected]3148c5d2009-11-18 19:32:5842
43 void PurgeMemoryOnIOThread();
44
45 private:
[email protected]abe2c032011-03-31 18:49:3446 typedef scoped_refptr<net::URLRequestContextGetter> RequestContextGetter;
[email protected]3148c5d2009-11-18 19:32:5847 typedef std::set<RequestContextGetter> RequestContextGetters;
48
49 RequestContextGetters request_context_getters_;
50 scoped_refptr<SafeBrowsingService> safe_browsing_service_;
51
52 DISALLOW_COPY_AND_ASSIGN(PurgeMemoryIOHelper);
53};
54
55void PurgeMemoryIOHelper::AddRequestContextGetter(
[email protected]abe2c032011-03-31 18:49:3456 scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
[email protected]00cd9c42010-11-02 20:15:5757 request_context_getters_.insert(request_context_getter);
[email protected]3148c5d2009-11-18 19:32:5858}
59
60void PurgeMemoryIOHelper::PurgeMemoryOnIOThread() {
61 // Ask ProxyServices to purge any memory they can (generally garbage in the
62 // wrapped ProxyResolver's JS engine).
63 for (RequestContextGetters::const_iterator i(
64 request_context_getters_.begin());
65 i != request_context_getters_.end(); ++i)
66 (*i)->GetURLRequestContext()->proxy_service()->PurgeMemory();
67
68 // Close the Safe Browsing database, freeing memory used to cache sqlite as
69 // well as a number of in-memory structures.
70 safe_browsing_service_->CloseDatabase();
[email protected]520cdd72010-01-13 22:14:4671
72 // The appcache service listens for this notification.
73 NotificationService::current()->Notify(
74 NotificationType::PURGE_MEMORY,
75 Source<void>(NULL),
76 NotificationService::NoDetails());
[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.
94 BackingStoreManager::RemoveAllBackingStores();
95
96 // Per-profile cleanup.
97 scoped_refptr<PurgeMemoryIOHelper> purge_memory_io_helper(
98 new PurgeMemoryIOHelper(g_browser_process->resource_dispatcher_host()->
99 safe_browsing_service()));
100 ProfileManager* profile_manager = g_browser_process->profile_manager();
101 for (ProfileManager::iterator i(profile_manager->begin());
102 i != profile_manager->end(); ++i) {
103 Profile* profile = *i;
104 purge_memory_io_helper->AddRequestContextGetter(
[email protected]00cd9c42010-11-02 20:15:57105 make_scoped_refptr(profile->GetRequestContext()));
[email protected]3148c5d2009-11-18 19:32:58106
107 // NOTE: Some objects below may be duplicates across profiles. We could
108 // conceivably put all these in sets and then iterate over the sets.
109
110 // Unload all history backends (freeing memory used to cache sqlite).
111 // Spinning up the history service is expensive, so we avoid doing it if it
112 // hasn't been done already.
113 HistoryService* history_service =
114 profile->GetHistoryServiceWithoutCreating();
115 if (history_service)
116 history_service->UnloadBackend();
117
118 // Unload all web databases (freeing memory used to cache sqlite).
119 WebDataService* web_data_service =
120 profile->GetWebDataServiceWithoutCreating();
121 if (web_data_service)
122 web_data_service->UnloadDatabase();
123
124 // Ask all WebKitContexts to purge memory (freeing memory used to cache
125 // the LocalStorage sqlite DB). WebKitContext creation is basically free so
126 // we don't bother with a "...WithoutCreating()" function.
127 profile->GetWebKitContext()->PurgeMemory();
128 }
129
[email protected]f8b3ef82010-10-11 02:45:52130 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
[email protected]3148c5d2009-11-18 19:32:58131 NewRunnableMethod(purge_memory_io_helper.get(),
132 &PurgeMemoryIOHelper::PurgeMemoryOnIOThread));
133
134 // TODO(pkasting):
135 // * Purge AppCache memory. Not yet implemented sufficiently.
136 // * Browser-side DatabaseTracker. Not implemented sufficiently.
137
[email protected]61a9b2d82010-02-26 00:31:08138#if (defined(OS_WIN) || defined(OS_LINUX)) && defined(USE_TCMALLOC)
[email protected]3148c5d2009-11-18 19:32:58139 // Tell tcmalloc to release any free pages it's still holding.
[email protected]0dd5dda02009-10-01 18:50:19140 //
[email protected]3148c5d2009-11-18 19:32:58141 // TODO(pkasting): A lot of the above calls kick off actions on other threads.
142 // Maybe we should find a way to avoid calling this until those actions
143 // complete?
144 MallocExtension::instance()->ReleaseFreeMemory();
145#endif
[email protected]0dd5dda02009-10-01 18:50:19146}
147
[email protected]3148c5d2009-11-18 19:32:58148// static
149void MemoryPurger::PurgeRenderers() {
150 // Direct all renderers to free everything they can.
[email protected]0dd5dda02009-10-01 18:50:19151 //
[email protected]3148c5d2009-11-18 19:32:58152 // Concern: Telling a bunch of renderer processes to destroy their data may
153 // cause them to page everything in to do it, which could take a lot of time/
154 // cause jank.
155 for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
156 !i.IsAtEnd(); i.Advance())
157 PurgeRendererForHost(i.GetCurrentValue());
[email protected]0dd5dda02009-10-01 18:50:19158}
159
[email protected]3148c5d2009-11-18 19:32:58160// static
161void MemoryPurger::PurgeRendererForHost(RenderProcessHost* host) {
162 // Direct the renderer to free everything it can.
163 host->Send(new ViewMsg_PurgeMemory());
[email protected]0dd5dda02009-10-01 18:50:19164}