OLD | NEW |
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 <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/process.h" | 10 #include "base/process.h" |
11 #include "base/process_util.h" | 11 #include "base/process_util.h" |
| 12 #include "base/string_number_conversions.h" |
12 #include "base/string16.h" | 13 #include "base/string16.h" |
13 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
14 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
15 #include "base/timer.h" | 16 #include "base/timer.h" |
| 17 #include "base/utf_string_conversions.h" |
16 #include "build/build_config.h" | 18 #include "build/build_config.h" |
17 #include "chrome/browser/tabs/tab_strip_model.h" | 19 #include "chrome/browser/tabs/tab_strip_model.h" |
18 #include "chrome/browser/ui/browser_list.h" | 20 #include "chrome/browser/ui/browser_list.h" |
19 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 21 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
20 #include "chrome/common/chrome_constants.h" | 22 #include "chrome/common/chrome_constants.h" |
21 #include "content/browser/browser_thread.h" | 23 #include "content/browser/browser_thread.h" |
22 #include "content/browser/renderer_host/render_process_host.h" | 24 #include "content/browser/renderer_host/render_process_host.h" |
23 #include "content/browser/renderer_host/render_widget_host.h" | 25 #include "content/browser/renderer_host/render_widget_host.h" |
24 #include "content/browser/tab_contents/tab_contents.h" | 26 #include "content/browser/tab_contents/tab_contents.h" |
25 #include "content/browser/zygote_host_linux.h" | 27 #include "content/browser/zygote_host_linux.h" |
| 28 #include "content/common/content_notification_types.h" |
26 #include "content/common/notification_service.h" | 29 #include "content/common/notification_service.h" |
27 | 30 |
28 #if !defined(OS_CHROMEOS) | 31 #if !defined(OS_CHROMEOS) |
29 #error This file only meant to be compiled on ChromeOS | 32 #error This file only meant to be compiled on ChromeOS |
30 #endif | 33 #endif |
31 | 34 |
32 using base::TimeDelta; | 35 using base::TimeDelta; |
33 using base::TimeTicks; | 36 using base::TimeTicks; |
34 using base::ProcessHandle; | 37 using base::ProcessHandle; |
35 using base::ProcessMetrics; | 38 using base::ProcessMetrics; |
36 | 39 |
| 40 namespace { |
| 41 |
| 42 // Returns a unique ID for a TabContents. Do not cast back to a pointer, as |
| 43 // the TabContents could be deleted if the user closed the tab. |
| 44 int64 IdFromTabContents(TabContents* tab_contents) { |
| 45 return reinterpret_cast<int64>(tab_contents); |
| 46 } |
| 47 |
| 48 } // namespace |
| 49 |
37 namespace browser { | 50 namespace browser { |
38 | 51 |
39 // The default interval in seconds after which to adjust the oom_score_adj | 52 // The default interval in seconds after which to adjust the oom_score_adj |
40 // value. | 53 // value. |
41 #define ADJUSTMENT_INTERVAL_SECONDS 10 | 54 #define ADJUSTMENT_INTERVAL_SECONDS 10 |
42 | 55 |
43 // The default interval in minutes for considering activation times | |
44 // "equal". | |
45 #define BUCKET_INTERVAL_MINUTES 10 | |
46 | |
47 // The default interval in milliseconds to wait before setting the score of | 56 // The default interval in milliseconds to wait before setting the score of |
48 // currently focused tab. | 57 // currently focused tab. |
49 #define FOCUSED_TAB_SCORE_ADJUST_INTERVAL_MS 500 | 58 #define FOCUSED_TAB_SCORE_ADJUST_INTERVAL_MS 500 |
50 | 59 |
51 OomPriorityManager::RendererStats::RendererStats() | 60 OomPriorityManager::TabStats::TabStats() |
52 : is_pinned(false), | 61 : is_pinned(false), |
53 is_selected(false), | 62 is_selected(false), |
54 memory_used(0), | 63 renderer_handle(0), |
55 renderer_handle(0) { | 64 tab_contents_id(0) { |
56 } | 65 } |
57 | 66 |
58 OomPriorityManager::RendererStats::~RendererStats() { | 67 OomPriorityManager::TabStats::~TabStats() { |
59 } | 68 } |
60 | 69 |
61 OomPriorityManager::OomPriorityManager() | 70 OomPriorityManager::OomPriorityManager() |
62 : focused_tab_pid_(0) { | 71 : focused_tab_pid_(0) { |
63 renderer_stats_.reserve(32); // 99% of users have < 30 tabs open | |
64 registrar_.Add(this, | 72 registrar_.Add(this, |
65 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 73 content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
66 NotificationService::AllSources()); | 74 NotificationService::AllSources()); |
67 registrar_.Add(this, | 75 registrar_.Add(this, |
68 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 76 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
69 NotificationService::AllSources()); | 77 NotificationService::AllSources()); |
70 registrar_.Add(this, | 78 registrar_.Add(this, |
71 content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, | 79 content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, |
72 NotificationService::AllSources()); | 80 NotificationService::AllSources()); |
73 } | 81 } |
74 | 82 |
75 OomPriorityManager::~OomPriorityManager() { | 83 OomPriorityManager::~OomPriorityManager() { |
76 Stop(); | 84 Stop(); |
77 } | 85 } |
78 | 86 |
79 void OomPriorityManager::Start() { | 87 void OomPriorityManager::Start() { |
80 if (!timer_.IsRunning()) { | 88 if (!timer_.IsRunning()) { |
81 timer_.Start(FROM_HERE, | 89 timer_.Start(FROM_HERE, |
82 TimeDelta::FromSeconds(ADJUSTMENT_INTERVAL_SECONDS), | 90 TimeDelta::FromSeconds(ADJUSTMENT_INTERVAL_SECONDS), |
83 this, | 91 this, |
84 &OomPriorityManager::AdjustOomPriorities); | 92 &OomPriorityManager::AdjustOomPriorities); |
85 } | 93 } |
86 } | 94 } |
87 | 95 |
88 void OomPriorityManager::Stop() { | 96 void OomPriorityManager::Stop() { |
89 timer_.Stop(); | 97 timer_.Stop(); |
90 } | 98 } |
91 | 99 |
92 std::vector<string16> OomPriorityManager::GetTabTitles() { | 100 std::vector<string16> OomPriorityManager::GetTabTitles() { |
93 base::AutoLock renderer_stats_autolock(renderer_stats_lock_); | 101 TabStatsList stats = GetTabStatsOnUIThread(); |
| 102 base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_); |
94 std::vector<string16> titles; | 103 std::vector<string16> titles; |
95 titles.reserve(renderer_stats_.size()); | 104 titles.reserve(stats.size()); |
96 StatsList::iterator it = renderer_stats_.begin(); | 105 TabStatsList::iterator it = stats.begin(); |
97 for ( ; it != renderer_stats_.end(); ++it) { | 106 for ( ; it != stats.end(); ++it) { |
98 titles.push_back(it->title); | 107 string16 str = it->title; |
| 108 str += ASCIIToUTF16(" ("); |
| 109 int score = pid_to_oom_score_[it->renderer_handle]; |
| 110 str += base::IntToString16(score); |
| 111 str += ASCIIToUTF16(")"); |
| 112 titles.push_back(str); |
99 } | 113 } |
100 return titles; | 114 return titles; |
101 } | 115 } |
102 | 116 |
| 117 void OomPriorityManager::DiscardTab() { |
| 118 TabStatsList stats = GetTabStatsOnUIThread(); |
| 119 if (stats.empty()) |
| 120 return; |
| 121 std::sort(stats.begin(), stats.end(), CompareTabStats); |
| 122 TabStatsList::const_reverse_iterator rit = stats.rbegin(); |
| 123 int64 least_important_tab_id = rit->tab_contents_id; |
| 124 for (BrowserList::const_iterator browser_iterator = BrowserList::begin(); |
| 125 browser_iterator != BrowserList::end(); ++browser_iterator) { |
| 126 Browser* browser = *browser_iterator; |
| 127 TabStripModel* model = browser->tabstrip_model(); |
| 128 for (int idx = 0; idx < model->count(); idx++) { |
| 129 TabContents* tab_contents = model->GetTabContentsAt(idx)->tab_contents(); |
| 130 int64 tab_contents_id = IdFromTabContents(tab_contents); |
| 131 if (tab_contents_id == least_important_tab_id) { |
| 132 model->CloseTabContentsAt(idx, |
| 133 TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); |
| 134 } |
| 135 } |
| 136 } |
| 137 } |
| 138 |
103 // Returns true if |first| is considered less desirable to be killed | 139 // Returns true if |first| is considered less desirable to be killed |
104 // than |second|. | 140 // than |second|. |
105 bool OomPriorityManager::CompareRendererStats(RendererStats first, | 141 bool OomPriorityManager::CompareTabStats(TabStats first, |
106 RendererStats second) { | 142 TabStats second) { |
107 // The size of the slop in comparing activation times. [This is | |
108 // allocated here to avoid static initialization at startup time.] | |
109 static const int64 kTimeBucketInterval = | |
110 TimeDelta::FromMinutes(BUCKET_INTERVAL_MINUTES).ToInternalValue(); | |
111 | |
112 // Being currently selected is most important. | 143 // Being currently selected is most important. |
113 if (first.is_selected != second.is_selected) | 144 if (first.is_selected != second.is_selected) |
114 return first.is_selected == true; | 145 return first.is_selected == true; |
115 | 146 |
116 // Being pinned is second most important. | 147 // Being pinned is second most important. |
117 if (first.is_pinned != second.is_pinned) | 148 if (first.is_pinned != second.is_pinned) |
118 return first.is_pinned == true; | 149 return first.is_pinned == true; |
119 | 150 |
120 // We want to be a little "fuzzy" when we compare these, because | 151 // Being more recently selected is more important. |
121 // it's not really possible for the times to be identical, but if | 152 return first.last_selected > second.last_selected; |
122 // the user selected two tabs at about the same time, we still want | |
123 // to take the one that uses more memory. | |
124 if (abs((first.last_selected - second.last_selected).ToInternalValue()) < | |
125 kTimeBucketInterval) | |
126 return first.last_selected > second.last_selected; | |
127 | |
128 return first.memory_used < second.memory_used; | |
129 } | 153 } |
130 | 154 |
131 void OomPriorityManager::AdjustFocusedTabScore() { | 155 void OomPriorityManager::AdjustFocusedTabScoreOnFileThread() { |
| 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
132 base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_); | 157 base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_); |
133 ZygoteHost::GetInstance()->AdjustRendererOOMScore( | 158 ZygoteHost::GetInstance()->AdjustRendererOOMScore( |
134 focused_tab_pid_, chrome::kLowestRendererOomScore); | 159 focused_tab_pid_, chrome::kLowestRendererOomScore); |
135 pid_to_oom_score_[focused_tab_pid_] = chrome::kLowestRendererOomScore; | 160 pid_to_oom_score_[focused_tab_pid_] = chrome::kLowestRendererOomScore; |
136 } | 161 } |
137 | 162 |
138 void OomPriorityManager::OnFocusTabScoreAdjustmentTimeout() { | 163 void OomPriorityManager::OnFocusTabScoreAdjustmentTimeout() { |
139 BrowserThread::PostTask( | 164 BrowserThread::PostTask( |
140 BrowserThread::FILE, FROM_HERE, | 165 BrowserThread::FILE, FROM_HERE, |
141 NewRunnableMethod(this, &OomPriorityManager::AdjustFocusedTabScore)); | 166 NewRunnableMethod( |
| 167 this, &OomPriorityManager::AdjustFocusedTabScoreOnFileThread)); |
142 } | 168 } |
143 | 169 |
144 void OomPriorityManager::Observe(int type, const NotificationSource& source, | 170 void OomPriorityManager::Observe(int type, const NotificationSource& source, |
145 const NotificationDetails& details) { | 171 const NotificationDetails& details) { |
146 base::ProcessHandle handle = 0; | 172 base::ProcessHandle handle = 0; |
147 base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_); | 173 base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_); |
148 switch (type) { | 174 switch (type) { |
149 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: | 175 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: |
150 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { | 176 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { |
151 handle = Source<RenderProcessHost>(source)->GetHandle(); | 177 handle = Source<RenderProcessHost>(source)->GetHandle(); |
152 pid_to_oom_score_.erase(handle); | 178 pid_to_oom_score_.erase(handle); |
153 break; | 179 break; |
154 } | 180 } |
155 case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: { | 181 case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: { |
(...skipping 30 matching lines...) Expand all Loading... |
186 | 212 |
187 // Here we collect most of the information we need to sort the | 213 // Here we collect most of the information we need to sort the |
188 // existing renderers in priority order, and hand out oom_score_adj | 214 // existing renderers in priority order, and hand out oom_score_adj |
189 // scores based on that sort order. | 215 // scores based on that sort order. |
190 // | 216 // |
191 // Things we need to collect on the browser thread (because | 217 // Things we need to collect on the browser thread (because |
192 // TabStripModel isn't thread safe): | 218 // TabStripModel isn't thread safe): |
193 // 1) whether or not a tab is pinned | 219 // 1) whether or not a tab is pinned |
194 // 2) last time a tab was selected | 220 // 2) last time a tab was selected |
195 // 3) is the tab currently selected | 221 // 3) is the tab currently selected |
196 // | |
197 // We also need to collect: | |
198 // 4) size in memory of a tab | |
199 // But we do that in DoAdjustOomPriorities on the FILE thread so that | |
200 // we avoid jank, because it accesses /proc. | |
201 void OomPriorityManager::AdjustOomPriorities() { | 222 void OomPriorityManager::AdjustOomPriorities() { |
202 if (BrowserList::size() == 0) | 223 if (BrowserList::size() == 0) |
203 return; | 224 return; |
| 225 TabStatsList stats_list = GetTabStatsOnUIThread(); |
| 226 BrowserThread::PostTask( |
| 227 BrowserThread::FILE, FROM_HERE, |
| 228 NewRunnableMethod(this, |
| 229 &OomPriorityManager::AdjustOomPrioritiesOnFileThread, |
| 230 stats_list)); |
| 231 } |
204 | 232 |
205 { | 233 OomPriorityManager::TabStatsList OomPriorityManager::GetTabStatsOnUIThread() { |
206 base::AutoLock renderer_stats_autolock(renderer_stats_lock_); | 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
207 renderer_stats_.clear(); | 235 TabStatsList stats_list; |
208 for (BrowserList::const_iterator browser_iterator = BrowserList::begin(); | 236 stats_list.reserve(32); // 99% of users have < 30 tabs open |
209 browser_iterator != BrowserList::end(); ++browser_iterator) { | 237 for (BrowserList::const_iterator browser_iterator = BrowserList::begin(); |
210 Browser* browser = *browser_iterator; | 238 browser_iterator != BrowserList::end(); ++browser_iterator) { |
211 const TabStripModel* model = browser->tabstrip_model(); | 239 Browser* browser = *browser_iterator; |
212 for (int i = 0; i < model->count(); i++) { | 240 const TabStripModel* model = browser->tabstrip_model(); |
213 TabContents* contents = model->GetTabContentsAt(i)->tab_contents(); | 241 for (int i = 0; i < model->count(); i++) { |
214 if (!contents->is_crashed()) { | 242 TabContents* contents = model->GetTabContentsAt(i)->tab_contents(); |
215 RendererStats stats; | 243 if (!contents->is_crashed()) { |
216 stats.last_selected = contents->last_selected_time(); | 244 TabStats stats; |
217 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle(); | 245 stats.last_selected = contents->last_selected_time(); |
218 stats.is_pinned = model->IsTabPinned(i); | 246 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle(); |
219 stats.memory_used = 0; // Calculated in DoAdjustOomPriorities. | 247 stats.is_pinned = model->IsTabPinned(i); |
220 stats.is_selected = model->IsTabSelected(i); | 248 stats.is_selected = model->IsTabSelected(i); |
221 stats.title = contents->GetTitle(); | 249 stats.title = contents->GetTitle(); |
222 renderer_stats_.push_back(stats); | 250 stats.tab_contents_id = IdFromTabContents(contents); |
223 } | 251 stats_list.push_back(stats); |
224 } | 252 } |
225 } | 253 } |
226 } | 254 } |
227 | 255 // Sort the data we collected so that least desirable to be |
228 BrowserThread::PostTask( | 256 // killed is first, most desirable is last. |
229 BrowserThread::FILE, FROM_HERE, | 257 std::sort(stats_list.begin(), stats_list.end(), CompareTabStats); |
230 NewRunnableMethod(this, &OomPriorityManager::DoAdjustOomPriorities)); | 258 return stats_list; |
231 } | 259 } |
232 | 260 |
233 void OomPriorityManager::DoAdjustOomPriorities() { | 261 void OomPriorityManager::AdjustOomPrioritiesOnFileThread( |
| 262 TabStatsList stats_list) { |
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
235 base::AutoLock renderer_stats_autolock(renderer_stats_lock_); | |
236 base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_); | 264 base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_); |
237 for (StatsList::iterator stats_iter = renderer_stats_.begin(); | |
238 stats_iter != renderer_stats_.end(); ++stats_iter) { | |
239 scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics( | |
240 stats_iter->renderer_handle)); | |
241 | |
242 base::WorkingSetKBytes working_set_kbytes; | |
243 if (metrics->GetWorkingSetKBytes(&working_set_kbytes)) { | |
244 // We use the proportional set size (PSS) to calculate memory | |
245 // usage "badness" on Linux. | |
246 stats_iter->memory_used = working_set_kbytes.shared * 1024; | |
247 } else { | |
248 // and if for some reason we can't get PSS, we revert to using | |
249 // resident set size (RSS). This will be zero if the process | |
250 // has already gone away, but we can live with that, since the | |
251 // process is gone anyhow. | |
252 stats_iter->memory_used = metrics->GetWorkingSetSize(); | |
253 } | |
254 } | |
255 | |
256 // Now we sort the data we collected so that least desirable to be | |
257 // killed is first, most desirable is last. | |
258 std::sort(renderer_stats_.begin(), | |
259 renderer_stats_.end(), | |
260 OomPriorityManager::CompareRendererStats); | |
261 | 265 |
262 // Now we assign priorities based on the sorted list. We're | 266 // Now we assign priorities based on the sorted list. We're |
263 // assigning priorities in the range of kLowestRendererOomScore to | 267 // assigning priorities in the range of kLowestRendererOomScore to |
264 // kHighestRendererOomScore (defined in chrome_constants.h). | 268 // kHighestRendererOomScore (defined in chrome_constants.h). |
265 // oom_score_adj takes values from -1000 to 1000. Negative values | 269 // oom_score_adj takes values from -1000 to 1000. Negative values |
266 // are reserved for system processes, and we want to give some room | 270 // are reserved for system processes, and we want to give some room |
267 // below the range we're using to allow for things that want to be | 271 // below the range we're using to allow for things that want to be |
268 // above the renderers in priority, so the defined range gives us | 272 // above the renderers in priority, so the defined range gives us |
269 // some variation in priority without taking up the whole range. In | 273 // some variation in priority without taking up the whole range. In |
270 // the end, however, it's a pretty arbitrary range to use. Higher | 274 // the end, however, it's a pretty arbitrary range to use. Higher |
271 // values are more likely to be killed by the OOM killer. | 275 // values are more likely to be killed by the OOM killer. |
272 // | 276 // |
273 // We also remove any duplicate PIDs, leaving the most important | 277 // We also remove any duplicate PIDs, leaving the most important |
274 // (least likely to be killed) of the duplicates, so that a | 278 // (least likely to be killed) of the duplicates, so that a |
275 // particular renderer process takes on the oom_score_adj of the | 279 // particular renderer process takes on the oom_score_adj of the |
276 // least likely tab to be killed. | 280 // least likely tab to be killed. |
277 const int kPriorityRange = chrome::kHighestRendererOomScore - | 281 const int kPriorityRange = chrome::kHighestRendererOomScore - |
278 chrome::kLowestRendererOomScore; | 282 chrome::kLowestRendererOomScore; |
279 float priority_increment = | 283 float priority_increment = |
280 static_cast<float>(kPriorityRange) / renderer_stats_.size(); | 284 static_cast<float>(kPriorityRange) / stats_list.size(); |
281 float priority = chrome::kLowestRendererOomScore; | 285 float priority = chrome::kLowestRendererOomScore; |
282 std::set<base::ProcessHandle> already_seen; | 286 std::set<base::ProcessHandle> already_seen; |
283 int score = 0; | 287 int score = 0; |
284 ProcessScoreMap::iterator it; | 288 ProcessScoreMap::iterator it; |
285 for (StatsList::iterator iterator = renderer_stats_.begin(); | 289 for (TabStatsList::iterator iterator = stats_list.begin(); |
286 iterator != renderer_stats_.end(); ++iterator) { | 290 iterator != stats_list.end(); ++iterator) { |
287 if (already_seen.find(iterator->renderer_handle) == already_seen.end()) { | 291 if (already_seen.find(iterator->renderer_handle) == already_seen.end()) { |
288 already_seen.insert(iterator->renderer_handle); | 292 already_seen.insert(iterator->renderer_handle); |
289 // If a process has the same score as the newly calculated value, | 293 // If a process has the same score as the newly calculated value, |
290 // do not set it. | 294 // do not set it. |
291 score = static_cast<int>(priority + 0.5f); | 295 score = static_cast<int>(priority + 0.5f); |
292 it = pid_to_oom_score_.find(iterator->renderer_handle); | 296 it = pid_to_oom_score_.find(iterator->renderer_handle); |
293 if (it == pid_to_oom_score_.end() || it->second != score) { | 297 if (it == pid_to_oom_score_.end() || it->second != score) { |
294 ZygoteHost::GetInstance()->AdjustRendererOOMScore( | 298 ZygoteHost::GetInstance()->AdjustRendererOOMScore( |
295 iterator->renderer_handle, score); | 299 iterator->renderer_handle, score); |
296 pid_to_oom_score_[iterator->renderer_handle] = score; | 300 pid_to_oom_score_[iterator->renderer_handle] = score; |
297 } | 301 } |
298 priority += priority_increment; | 302 priority += priority_increment; |
299 } | 303 } |
300 } | 304 } |
301 } | 305 } |
302 | 306 |
303 } // namespace browser | 307 } // namespace browser |
OLD | NEW |