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
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_CHROMEOS_MEMORY_OOM_PRIORITY_MANAGER_H_
6 #define CHROME_BROWSER_CHROMEOS_MEMORY_OOM_PRIORITY_MANAGER_H_
10 #include "base/compiler_specific.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/gtest_prod_util.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/process/process.h"
15 #include "base/strings/string16.h"
16 #include "base/synchronization/lock.h"
17 #include "base/time/time.h"
18 #include "base/timer/timer.h"
19 #include "content/public/browser/notification_observer.h"
20 #include "content/public/browser/notification_registrar.h"
26 class LowMemoryObserver
;
28 // The OomPriorityManager periodically checks (see
29 // ADJUSTMENT_INTERVAL_SECONDS in the source) the status of renderers
30 // and adjusts the out of memory (OOM) adjustment value (in
31 // /proc/<pid>/oom_score_adj) of the renderers so that they match the
32 // algorithm embedded here for priority in being killed upon OOM
35 // The algorithm used favors killing tabs that are not selected, not pinned,
36 // and have been idle for longest, in that order of priority.
37 class OomPriorityManager
: public content::NotificationObserver
{
40 virtual ~OomPriorityManager();
42 // Number of discard events since Chrome started.
43 int discard_count() const { return discard_count_
; }
45 // See member comment.
46 bool recent_tab_discard() const { return recent_tab_discard_
; }
51 // Returns list of tab titles sorted from most interesting (don't kill)
52 // to least interesting (OK to kill).
53 std::vector
<base::string16
> GetTabTitles();
55 // Discards a tab to free the memory occupied by its renderer.
56 // Tab still exists in the tab-strip; clicking on it will reload it.
57 // Returns true if it successfully found a tab and discarded it.
60 // Log memory statistics for the running processes, then discards a tab.
61 // Tab discard happens sometime later, as collecting the statistics touches
62 // multiple threads and takes time.
63 void LogMemoryAndDiscardTab();
66 friend class OomMemoryDetails
;
67 FRIEND_TEST_ALL_PREFIXES(OomPriorityManagerTest
, Comparator
);
68 FRIEND_TEST_ALL_PREFIXES(OomPriorityManagerTest
, IsReloadableUI
);
69 FRIEND_TEST_ALL_PREFIXES(OomPriorityManagerTest
, GetProcessHandles
);
74 bool is_app
; // browser window is an app
75 bool is_reloadable_ui
; // Reloadable web UI page, like NTP or Settings.
76 bool is_playing_audio
;
78 bool is_selected
; // selected in the currently active browser window
80 base::TimeTicks last_active
;
81 base::ProcessHandle renderer_handle
;
83 int64 tab_contents_id
; // unique ID per WebContents
85 typedef std::vector
<TabStats
> TabStatsList
;
87 // Returns true if the |url| represents an internal Chrome web UI page that
88 // can be easily reloaded and hence makes a good choice to discard.
89 static bool IsReloadableUI(const GURL
& url
);
91 // Discards a tab with the given unique ID. Returns true if discard occurred.
92 bool DiscardTabById(int64 target_web_contents_id
);
94 // Records UMA histogram statistics for a tab discard. We record statistics
95 // for user triggered discards via chrome://discards/ because that allows us
96 // to manually test the system.
97 void RecordDiscardStatistics();
99 // Record whether we ran out of memory during a recent time interval.
100 // This allows us to normalize low memory statistics versus usage.
101 void RecordRecentTabDiscard();
103 // Purges data structures in the browser that can be easily recomputed.
104 void PurgeBrowserMemory();
106 // Returns the number of tabs open in all browser instances.
107 int GetTabCount() const;
109 TabStatsList
GetTabStatsOnUIThread();
111 // Called when the timer fires, sets oom_adjust_score for all renderers.
112 void AdjustOomPriorities();
114 // Returns a list of unique process handles from |stats_list|. If multiple
115 // tabs use the same process, returns the first process handle. This implies
116 // that the processes are selected based on their "most important" tab.
117 static std::vector
<base::ProcessHandle
> GetProcessHandles(
118 const TabStatsList
& stats_list
);
120 // Called by AdjustOomPriorities.
121 void AdjustOomPrioritiesOnFileThread(TabStatsList stats_list
);
123 // Posts AdjustFocusedTabScore task to the file thread.
124 void OnFocusTabScoreAdjustmentTimeout();
126 // Sets the score of the focused tab to the least value.
127 void AdjustFocusedTabScoreOnFileThread();
129 static bool CompareTabStats(TabStats first
, TabStats second
);
131 virtual void Observe(int type
,
132 const content::NotificationSource
& source
,
133 const content::NotificationDetails
& details
) OVERRIDE
;
135 base::RepeatingTimer
<OomPriorityManager
> timer_
;
136 base::OneShotTimer
<OomPriorityManager
> focus_tab_score_adjust_timer_
;
137 base::RepeatingTimer
<OomPriorityManager
> recent_tab_discard_timer_
;
138 content::NotificationRegistrar registrar_
;
140 // This lock is for pid_to_oom_score_ and focus_tab_pid_.
141 base::Lock pid_to_oom_score_lock_
;
142 // map maintaining the process - oom_score mapping.
143 typedef base::hash_map
<base::ProcessHandle
, int> ProcessScoreMap
;
144 ProcessScoreMap pid_to_oom_score_
;
145 base::ProcessHandle focused_tab_pid_
;
147 // Observer for the kernel low memory signal. NULL if tab discarding is
149 scoped_ptr
<LowMemoryObserver
> low_memory_observer_
;
151 // Wall-clock time when the priority manager started running.
152 base::TimeTicks start_time_
;
154 // Wall-clock time of last tab discard during this browsing session, or 0 if
155 // no discard has happened yet.
156 base::TimeTicks last_discard_time_
;
158 // Wall-clock time of last priority adjustment, used to correct the above
159 // times for discontinuities caused by suspend/resume.
160 base::TimeTicks last_adjust_time_
;
162 // Number of times we have discarded a tab, for statistics.
165 // Whether a tab discard event has occurred during the last time interval,
166 // used for statistics normalized by usage.
167 bool recent_tab_discard_
;
169 DISALLOW_COPY_AND_ASSIGN(OomPriorityManager
);
172 } // namespace chromeos
174 #endif // CHROME_BROWSER_CHROMEOS_MEMORY_OOM_PRIORITY_MANAGER_H_