Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1052)

Side by Side Diff: chrome/browser/memory/tab_manager.h

Issue 1641813002: Provide renderers with memory pressure signals. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@contentapi
Patch Set: Addressed creis' comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/memory/tab_manager.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ 5 #ifndef CHROME_BROWSER_MEMORY_TAB_MANAGER_H_
6 #define CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ 6 #define CHROME_BROWSER_MEMORY_TAB_MANAGER_H_
7 7
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <set>
10 #include <utility> 11 #include <utility>
11 #include <vector> 12 #include <vector>
12 13
14 #include "base/callback.h"
13 #include "base/compiler_specific.h" 15 #include "base/compiler_specific.h"
14 #include "base/gtest_prod_util.h" 16 #include "base/gtest_prod_util.h"
15 #include "base/macros.h" 17 #include "base/macros.h"
16 #include "base/memory/memory_pressure_listener.h" 18 #include "base/memory/memory_pressure_listener.h"
17 #include "base/memory/scoped_ptr.h" 19 #include "base/memory/scoped_ptr.h"
20 #include "base/memory/weak_ptr.h"
18 #include "base/strings/string16.h" 21 #include "base/strings/string16.h"
22 #include "base/task_runner.h"
19 #include "base/timer/timer.h" 23 #include "base/timer/timer.h"
20 #include "build/build_config.h" 24 #include "build/build_config.h"
21 #include "chrome/browser/memory/tab_stats.h" 25 #include "chrome/browser/memory/tab_stats.h"
22 #include "chrome/browser/ui/browser_tab_strip_tracker.h" 26 #include "chrome/browser/ui/browser_tab_strip_tracker.h"
23 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h" 27 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
24 28
25 class BrowserList; 29 class BrowserList;
26 class GURL; 30 class GURL;
31 class TabStripModel;
27 32
28 namespace base { 33 namespace base {
29 class TickClock; 34 class TickClock;
30 } 35 }
31 36
32 namespace content { 37 namespace content {
38 class RenderProcessHost;
33 class WebContents; 39 class WebContents;
34 } 40 }
35 41
36 namespace memory { 42 namespace memory {
37 43
38 #if defined(OS_CHROMEOS) 44 #if defined(OS_CHROMEOS)
39 class TabManagerDelegate; 45 class TabManagerDelegate;
40 #endif 46 #endif
41 47
42 // The TabManager periodically updates (see 48 // The TabManager periodically updates (see
(...skipping 28 matching lines...) Expand all
71 bool recent_tab_discard() const { return recent_tab_discard_; } 77 bool recent_tab_discard() const { return recent_tab_discard_; }
72 78
73 // Start/Stop the Tab Manager. 79 // Start/Stop the Tab Manager.
74 void Start(); 80 void Start();
75 void Stop(); 81 void Stop();
76 82
77 // Returns the list of the stats for all renderers. Must be called on the UI 83 // Returns the list of the stats for all renderers. Must be called on the UI
78 // thread. 84 // thread.
79 TabStatsList GetTabStats(); 85 TabStatsList GetTabStats();
80 86
87 // Returns a sorted list of renderers, from most important to least important.
88 std::vector<content::RenderProcessHost*> GetOrderedRenderers();
89
81 // Returns true if |contents| is currently discarded. 90 // Returns true if |contents| is currently discarded.
82 bool IsTabDiscarded(content::WebContents* contents) const; 91 bool IsTabDiscarded(content::WebContents* contents) const;
83 92
84 // Discards a tab to free the memory occupied by its renderer. The tab still 93 // Discards a tab to free the memory occupied by its renderer. The tab still
85 // exists in the tab-strip; clicking on it will reload it. Returns true if it 94 // exists in the tab-strip; clicking on it will reload it. Returns true if it
86 // successfully found a tab and discarded it. 95 // successfully found a tab and discarded it.
87 bool DiscardTab(); 96 bool DiscardTab();
88 97
89 // Discards a tab with the given unique ID. The tab still exists in the 98 // Discards a tab with the given unique ID. The tab still exists in the
90 // tab-strip; clicking on it will reload it. Returns true if it successfully 99 // tab-strip; clicking on it will reload it. Returns true if it successfully
91 // found a tab and discarded it. 100 // found a tab and discarded it.
92 content::WebContents* DiscardTabById(int64_t target_web_contents_id); 101 content::WebContents* DiscardTabById(int64_t target_web_contents_id);
93 102
94 // Log memory statistics for the running processes, then discards a tab. 103 // Log memory statistics for the running processes, then discards a tab.
95 // Tab discard happens sometime later, as collecting the statistics touches 104 // Tab discard happens sometime later, as collecting the statistics touches
96 // multiple threads and takes time. 105 // multiple threads and takes time.
97 void LogMemoryAndDiscardTab(); 106 void LogMemoryAndDiscardTab();
98 107
99 // Log memory statistics for the running processes, then call the callback. 108 // Log memory statistics for the running processes, then call the callback.
100 void LogMemory(const std::string& title, const base::Closure& callback); 109 void LogMemory(const std::string& title, const base::Closure& callback);
101 110
102 // Used to set the test TickClock, which then gets used by NowTicks(). See 111 // Used to set the test TickClock, which then gets used by NowTicks(). See
103 // |test_tick_clock_| for more details. 112 // |test_tick_clock_| for more details.
104 void set_test_tick_clock(base::TickClock* test_tick_clock); 113 void set_test_tick_clock(base::TickClock* test_tick_clock);
105 114
106 private: 115 private:
116 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ChildProcessNotifications);
107 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator); 117 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, Comparator);
108 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime); 118 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardedTabKeepsLastActiveTime);
109 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardWebContentsAt); 119 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, DiscardWebContentsAt);
110 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInternalPage); 120 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, IsInternalPage);
111 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectRecentlyUsedTabs); 121 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ProtectRecentlyUsedTabs);
112 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ReloadDiscardedTabContextMenu); 122 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, ReloadDiscardedTabContextMenu);
113 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics); 123 FRIEND_TEST_ALL_PREFIXES(TabManagerTest, TabManagerBasics);
114 124
125 // The time that a renderer is given to react to a memory pressure
126 // notification before another renderer is also notified. This prevents all
127 // renderers from receiving and acting upon notifications simultaneously,
128 // which can quickly overload a system. Exposed for unittesting.
129 // NOTE: This value needs to be big enough to allow a process to get over the
130 // hump in responding to memory pressure, so there aren't multiple processes
131 // fighting for CPU and worse, temporary memory, while trying to free things
132 // up. Similarly, it shouldn't be too large otherwise it will take too long
133 // for the entire system to respond. Ideally, there would be a callback from a
134 // child process indicating that the message has been handled. In the meantime
135 // this is chosen to be sufficient to allow a worst-case V8+Oilpan GC to run,
136 // with a little slop.
137 enum : int { kRendererNotificationDelayInSeconds = 2 };
138
139 using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
140
141 // A callback that returns the current memory pressure level.
142 using MemoryPressureLevelCallback = base::Callback<MemoryPressureLevel()>;
143
144 // Callback that notifies a |renderer| of the memory pressure at a given
145 // |level|. Provides a testing seam.
146 using RendererNotificationCallback = base::Callback<
147 void(const content::RenderProcessHost* /* renderer */,
148 MemoryPressureLevel /* level */)>;
149
115 static void PurgeMemoryAndDiscardTab(); 150 static void PurgeMemoryAndDiscardTab();
116 151
117 // Returns true if the |url| represents an internal Chrome web UI page that 152 // Returns true if the |url| represents an internal Chrome web UI page that
118 // can be easily reloaded and hence makes a good choice to discard. 153 // can be easily reloaded and hence makes a good choice to discard.
119 static bool IsInternalPage(const GURL& url); 154 static bool IsInternalPage(const GURL& url);
120 155
121 // Records UMA histogram statistics for a tab discard. Record statistics for 156 // Records UMA histogram statistics for a tab discard. Record statistics for
122 // user triggered discards via chrome://discards/ because that allows to 157 // user triggered discards via chrome://discards/ because that allows to
123 // manually test the system. 158 // manually test the system.
124 void RecordDiscardStatistics(); 159 void RecordDiscardStatistics();
125 160
126 // Record whether an out of memory occured during a recent time interval. This 161 // Record whether an out of memory occured during a recent time interval. This
127 // allows the normalization of low memory statistics versus usage. 162 // allows the normalization of low memory statistics versus usage.
128 void RecordRecentTabDiscard(); 163 void RecordRecentTabDiscard();
129 164
130 // Purges data structures in the browser that can be easily recomputed. 165 // Purges data structures in the browser that can be easily recomputed.
131 void PurgeBrowserMemory(); 166 void PurgeBrowserMemory();
132 167
133 // Returns the number of tabs open in all browser instances. 168 // Returns the number of tabs open in all browser instances.
134 int GetTabCount() const; 169 int GetTabCount() const;
135 170
136 // Adds all the stats of the tabs to |stats_list|. 171 // Adds all the stats of the tabs to |stats_list|.
137 void AddTabStats(TabStatsList* stats_list); 172 void AddTabStats(TabStatsList* stats_list);
138 173
174 // Adds all the stats of the tabs in |tab_strip_model| into |stats_list|.
175 // If |active_model| is true, consider its first tab as being active.
176 void AddTabStats(const TabStripModel* model,
177 bool is_app,
178 bool active_model,
179 TabStatsList* stats_list);
180
139 // Callback for when |update_timer_| fires. Takes care of executing the tasks 181 // Callback for when |update_timer_| fires. Takes care of executing the tasks
140 // that need to be run periodically (see comment in implementation). 182 // that need to be run periodically (see comment in implementation).
141 void UpdateTimerCallback(); 183 void UpdateTimerCallback();
142 184
143 // Goes through a list of checks to see if a tab is allowed to be discarded by 185 // Goes through a list of checks to see if a tab is allowed to be discarded by
144 // the automatic tab discarding mechanism. Note that this is not used when 186 // the automatic tab discarding mechanism. Note that this is not used when
145 // discarding a particular tab from about:discards. 187 // discarding a particular tab from about:discards.
146 bool CanDiscardTab(int64_t target_web_contents_id) const; 188 bool CanDiscardTab(int64_t target_web_contents_id) const;
147 189
148 // Does the actual discard by destroying the WebContents in |model| at |index| 190 // Does the actual discard by destroying the WebContents in |model| at |index|
(...skipping 24 matching lines...) Expand all
173 WebContentsData* GetWebContentsData(content::WebContents* contents) const; 215 WebContentsData* GetWebContentsData(content::WebContents* contents) const;
174 216
175 // Returns true if |first| is considered less desirable to be killed than 217 // Returns true if |first| is considered less desirable to be killed than
176 // |second|. 218 // |second|.
177 static bool CompareTabStats(TabStats first, TabStats second); 219 static bool CompareTabStats(TabStats first, TabStats second);
178 220
179 // Returns either the system's clock or the test clock. See |test_tick_clock_| 221 // Returns either the system's clock or the test clock. See |test_tick_clock_|
180 // for more details. 222 // for more details.
181 base::TimeTicks NowTicks() const; 223 base::TimeTicks NowTicks() const;
182 224
225 // Dispatches a memory pressure message to a single child process, and
226 // schedules another call to itself as long as memory pressure continues.
227 void DoChildProcessDispatch();
228
183 // Timer to periodically update the stats of the renderers. 229 // Timer to periodically update the stats of the renderers.
184 base::RepeatingTimer update_timer_; 230 base::RepeatingTimer update_timer_;
185 231
186 // Timer to periodically report whether a tab has been discarded since the 232 // Timer to periodically report whether a tab has been discarded since the
187 // last time the timer has fired. 233 // last time the timer has fired.
188 base::RepeatingTimer recent_tab_discard_timer_; 234 base::RepeatingTimer recent_tab_discard_timer_;
189 235
190 // A listener to global memory pressure events. 236 // A listener to global memory pressure events.
191 scoped_ptr<base::MemoryPressureListener> memory_pressure_listener_; 237 scoped_ptr<base::MemoryPressureListener> memory_pressure_listener_;
192 238
(...skipping 19 matching lines...) Expand all
212 bool discard_once_; 258 bool discard_once_;
213 259
214 // This allows protecting tabs for a certain amount of time after being 260 // This allows protecting tabs for a certain amount of time after being
215 // backgrounded. 261 // backgrounded.
216 base::TimeDelta minimum_protection_time_; 262 base::TimeDelta minimum_protection_time_;
217 263
218 #if defined(OS_CHROMEOS) 264 #if defined(OS_CHROMEOS)
219 scoped_ptr<TabManagerDelegate> delegate_; 265 scoped_ptr<TabManagerDelegate> delegate_;
220 #endif 266 #endif
221 267
268 // Responsible for automatically registering this class as an observer of all
269 // TabStripModels. Automatically tracks browsers as they come and go.
222 BrowserTabStripTracker browser_tab_strip_tracker_; 270 BrowserTabStripTracker browser_tab_strip_tracker_;
223 271
224 // Pointer to a test clock. If this is set, NowTicks() returns the value of 272 // Pointer to a test clock. If this is set, NowTicks() returns the value of
225 // this test clock. Otherwise it returns the system clock's value. 273 // this test clock. Otherwise it returns the system clock's value.
226 base::TickClock* test_tick_clock_; 274 base::TickClock* test_tick_clock_;
227 275
276 // The task runner used for child process notifications. Defaults to the
277 // thread task runner handle that is used by the memory pressure subsystem,
278 // but may be explicitly set for unittesting.
279 scoped_refptr<base::TaskRunner> task_runner_;
280
281 // Indicates that the system is currently experiencing memory pressure. Used
282 // to determine whether a new round of child-process memory pressure
283 // dispatches is starting, or whether an existing one is continuing.
284 bool under_memory_pressure_;
285
286 // The set of child renderers that have received memory pressure notifications
287 // during the current bout of memory pressure. This is emptied when all
288 // children have been notified (restarting another round of notification) and
289 // when a bout of memory pressure ends.
290 std::set<const content::RenderProcessHost*> notified_renderers_;
291
292 // The callback that returns the current memory pressure level. Defaults to
293 // querying base::MemoryPressureMonitor, but can be overridden for testing.
294 MemoryPressureLevelCallback get_current_pressure_level_;
295
296 // The callback to be invoked to notify renderers. Defaults to calling
297 // content::SendPressureNotification, but can be overridden for testing.
298 RendererNotificationCallback notify_renderer_process_;
299
300 // Injected tab strip models. Allows this to be tested end-to-end without
301 // requiring a full browser environment. If specified these tab strips will be
302 // crawled as the authoritative source of tabs, otherwise the BrowserList and
303 // associated Browser objects are crawled. The first of these is considered to
304 // be the 'active' tab strip model.
305 // TODO(chrisha): Factor out tab-strip model enumeration to a helper class,
306 // and make a delegate that centralizes all testing seams.
307 using TestTabStripModel = std::pair<const TabStripModel*, bool>;
308 std::vector<TestTabStripModel> test_tab_strip_models_;
309
310 // Weak pointer factory used for posting delayed tasks to task_runner_.
311 base::WeakPtrFactory<TabManager> weak_ptr_factory_;
312
228 DISALLOW_COPY_AND_ASSIGN(TabManager); 313 DISALLOW_COPY_AND_ASSIGN(TabManager);
229 }; 314 };
230 315
231 } // namespace memory 316 } // namespace memory
232 317
233 #endif // CHROME_BROWSER_MEMORY_TAB_MANAGER_H_ 318 #endif // CHROME_BROWSER_MEMORY_TAB_MANAGER_H_
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/memory/tab_manager.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698