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

Side by Side Diff: chrome/browser/oom_priority_manager.cc

Issue 7671033: Changing OOM range to 0, 1000 and tweaking OOM algorithm. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 4 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #include "chrome/browser/oom_priority_manager.h" 5 #include "chrome/browser/oom_priority_manager.h"
6 6
7 #include <list> 7 #include <list>
8 8
9 #include "base/process.h" 9 #include "base/process.h"
10 #include "base/process_util.h" 10 #include "base/process_util.h"
(...skipping 11 matching lines...) Expand all
22 #error This file only meant to be compiled on ChromeOS 22 #error This file only meant to be compiled on ChromeOS
23 #endif 23 #endif
24 24
25 using base::TimeDelta; 25 using base::TimeDelta;
26 using base::TimeTicks; 26 using base::TimeTicks;
27 using base::ProcessHandle; 27 using base::ProcessHandle;
28 using base::ProcessMetrics; 28 using base::ProcessMetrics;
29 29
30 namespace browser { 30 namespace browser {
31 31
32 // The default interval in seconds after which to adjust the oom_adj 32 // The default interval in seconds after which to adjust the oom_score_adj
33 // value. 33 // value.
34 #define ADJUSTMENT_INTERVAL_SECONDS 10 34 #define ADJUSTMENT_INTERVAL_SECONDS 10
35 35
36 // The default interval in minutes for considering activation times 36 // The default interval in minutes for considering activation times
37 // "equal". 37 // "equal".
38 #define BUCKET_INTERVAL_MINUTES 10 38 #define BUCKET_INTERVAL_MINUTES 10
39 39
40 OomPriorityManager::OomPriorityManager() { 40 OomPriorityManager::OomPriorityManager() {
41 StartTimer(); 41 StartTimer();
42 } 42 }
(...skipping 16 matching lines...) Expand all
59 59
60 // Returns true if |first| is considered less desirable to be killed 60 // Returns true if |first| is considered less desirable to be killed
61 // than |second|. 61 // than |second|.
62 bool OomPriorityManager::CompareRendererStats(RendererStats first, 62 bool OomPriorityManager::CompareRendererStats(RendererStats first,
63 RendererStats second) { 63 RendererStats second) {
64 // The size of the slop in comparing activation times. [This is 64 // The size of the slop in comparing activation times. [This is
65 // allocated here to avoid static initialization at startup time.] 65 // allocated here to avoid static initialization at startup time.]
66 static const int64 kTimeBucketInterval = 66 static const int64 kTimeBucketInterval =
67 TimeDelta::FromMinutes(BUCKET_INTERVAL_MINUTES).ToInternalValue(); 67 TimeDelta::FromMinutes(BUCKET_INTERVAL_MINUTES).ToInternalValue();
68 68
69 // Being pinned is most important. 69 // Being currently selected is most important.
70 if (first.is_selected != second.is_selected)
71 return first.is_selected == true;
72
73 // Being pinned is second most important.
70 if (first.is_pinned != second.is_pinned) 74 if (first.is_pinned != second.is_pinned)
71 return first.is_pinned == true; 75 return first.is_pinned == true;
72 76
73 // We want to be a little "fuzzy" when we compare these, because 77 // We want to be a little "fuzzy" when we compare these, because
74 // it's not really possible for the times to be identical, but if 78 // it's not really possible for the times to be identical, but if
75 // the user selected two tabs at about the same time, we still want 79 // the user selected two tabs at about the same time, we still want
76 // to take the one that uses more memory. 80 // to take the one that uses more memory.
77 if (abs((first.last_selected - second.last_selected).ToInternalValue()) < 81 if (abs((first.last_selected - second.last_selected).ToInternalValue()) <
78 kTimeBucketInterval) 82 kTimeBucketInterval)
79 return first.last_selected < second.last_selected; 83 return first.last_selected < second.last_selected;
80 84
81 return first.memory_used < second.memory_used; 85 return first.memory_used < second.memory_used;
82 } 86 }
83 87
84 // Here we collect most of the information we need to sort the 88 // Here we collect most of the information we need to sort the
85 // existing renderers in priority order, and hand out oom_adj scores 89 // existing renderers in priority order, and hand out oom_score_adj
86 // based on that sort order. 90 // scores based on that sort order.
87 // 91 //
88 // Things we need to collect on the browser thread (because 92 // Things we need to collect on the browser thread (because
89 // TabStripModel isn't thread safe): 93 // TabStripModel isn't thread safe):
90 // 1) whether or not a tab is pinned 94 // 1) whether or not a tab is pinned
91 // 2) last time a tab was selected 95 // 2) last time a tab was selected
96 // 3) is the tab currently selected
92 // 97 //
93 // We also need to collect: 98 // We also need to collect:
94 // 3) size in memory of a tab 99 // 4) size in memory of a tab
95 // But we do that in DoAdjustOomPriorities on the FILE thread so that 100 // But we do that in DoAdjustOomPriorities on the FILE thread so that
96 // we avoid jank, because it accesses /proc. 101 // we avoid jank, because it accesses /proc.
97 void OomPriorityManager::AdjustOomPriorities() { 102 void OomPriorityManager::AdjustOomPriorities() {
98 if (BrowserList::size() == 0) 103 if (BrowserList::size() == 0)
99 return; 104 return;
100 105
101 StatsList renderer_stats; 106 StatsList renderer_stats;
102 for (BrowserList::const_iterator browser_iterator = BrowserList::begin(); 107 for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
103 browser_iterator != BrowserList::end(); ++browser_iterator) { 108 browser_iterator != BrowserList::end(); ++browser_iterator) {
104 Browser* browser = *browser_iterator; 109 Browser* browser = *browser_iterator;
105 const TabStripModel* model = browser->tabstrip_model(); 110 const TabStripModel* model = browser->tabstrip_model();
106 for (int i = 0; i < model->count(); i++) { 111 for (int i = 0; i < model->count(); i++) {
107 TabContents* contents = model->GetTabContentsAt(i)->tab_contents(); 112 TabContents* contents = model->GetTabContentsAt(i)->tab_contents();
108 RendererStats stats; 113 RendererStats stats;
109 stats.last_selected = contents->last_selected_time(); 114 stats.last_selected = contents->last_selected_time();
110 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle(); 115 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
111 stats.is_pinned = model->IsTabPinned(i); 116 stats.is_pinned = model->IsTabPinned(i);
112 stats.memory_used = 0; // This gets calculated in DoAdjustOomPriorities. 117 stats.memory_used = 0; // This gets calculated in DoAdjustOomPriorities.
118 stats.is_selected = model->IsTabSelected(i);
113 renderer_stats.push_back(stats); 119 renderer_stats.push_back(stats);
114 } 120 }
115 } 121 }
116 122
117 BrowserThread::PostTask( 123 BrowserThread::PostTask(
118 BrowserThread::FILE, FROM_HERE, 124 BrowserThread::FILE, FROM_HERE,
119 NewRunnableMethod(this, &OomPriorityManager::DoAdjustOomPriorities, 125 NewRunnableMethod(this, &OomPriorityManager::DoAdjustOomPriorities,
120 renderer_stats)); 126 renderer_stats));
121 } 127 }
122 128
(...skipping 15 matching lines...) Expand all
138 // process is gone anyhow. 144 // process is gone anyhow.
139 stats_iter->memory_used = metrics->GetWorkingSetSize(); 145 stats_iter->memory_used = metrics->GetWorkingSetSize();
140 } 146 }
141 } 147 }
142 148
143 // Now we sort the data we collected so that least desirable to be 149 // Now we sort the data we collected so that least desirable to be
144 // killed is first, most desirable is last. 150 // killed is first, most desirable is last.
145 renderer_stats.sort(OomPriorityManager::CompareRendererStats); 151 renderer_stats.sort(OomPriorityManager::CompareRendererStats);
146 152
147 // Now we assign priorities based on the sorted list. We're 153 // Now we assign priorities based on the sorted list. We're
148 // assigning priorities in the range of 5 to 10. oom_adj takes 154 // assigning priorities in the range of 300 to 1000. oom_score_adj
149 // values from -17 to 15. Negative values are reserved for system 155 // takes values from -1000 to 1000. Negative values are reserved
150 // processes, and we want to give some room on either side of the 156 // for system processes, and we want to give some room below the
151 // range we're using to allow for things that want to be above or 157 // range we're using to allow for things that want to be above the
152 // below the renderers in priority, so 5 to 10 gives us some 158 // renderers in priority, so 300 to 1000 gives us some variation in
153 // variation in priority without taking up the whole range. In the 159 // priority without taking up the whole range. In the end, however,
154 // end, however, it's a pretty arbitrary range to use. Higher 160 // it's a pretty arbitrary range to use. Higher values are more
155 // values are more likely to be killed by the OOM killer. We also 161 // likely to be killed by the OOM killer.
156 // remove any duplicate PIDs, leaving the most important of the 162 //
157 // duplicates. 163 // We also remove any duplicate PIDs, leaving the most important
158 const int kMinPriority = 5; 164 // (least likely to be killed) of the duplicates, so that a
159 const int kMaxPriority = 10; 165 // particular renderer process takes on the oom_score_adj of the
166 // least likely tab to be killed.
167 const int kMinPriority = 300;
168 const int kMaxPriority = 1000;
stevenjb 2011/08/18 00:20:07 It would be good to avoid having these constants d
Greg Spencer (Chromium) 2011/08/18 23:10:50 OK, I added two constants to chrome/common/chrome_
160 const int kPriorityRange = kMaxPriority - kMinPriority; 169 const int kPriorityRange = kMaxPriority - kMinPriority;
161 float priority_increment = 170 float priority_increment =
162 static_cast<float>(kPriorityRange) / renderer_stats.size(); 171 static_cast<float>(kPriorityRange) / renderer_stats.size();
163 float priority = kMinPriority; 172 float priority = kMinPriority;
164 std::set<base::ProcessHandle> already_seen; 173 std::set<base::ProcessHandle> already_seen;
165 for (StatsList::iterator iterator = renderer_stats.begin(); 174 for (StatsList::iterator iterator = renderer_stats.begin();
166 iterator != renderer_stats.end(); ++iterator) { 175 iterator != renderer_stats.end(); ++iterator) {
167 if (already_seen.find(iterator->renderer_handle) == already_seen.end()) { 176 if (already_seen.find(iterator->renderer_handle) == already_seen.end()) {
168 already_seen.insert(iterator->renderer_handle); 177 already_seen.insert(iterator->renderer_handle);
169 ZygoteHost::GetInstance()->AdjustRendererOOMScore( 178 ZygoteHost::GetInstance()->AdjustRendererOOMScore(
170 iterator->renderer_handle, 179 iterator->renderer_handle,
171 static_cast<int>(priority + 0.5f)); 180 static_cast<int>(priority + 0.5f));
172 priority += priority_increment; 181 priority += priority_increment;
173 } 182 }
174 } 183 }
175 } 184 }
176 185
177 } // namespace browser 186 } // namespace browser
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698