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

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

Issue 11879029: CrOS: Prefer discarding internal web UI pages when out of memory (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix nit, rebase Created 7 years, 11 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) 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 #include "chrome/browser/chromeos/memory/oom_priority_manager.h" 5 #include "chrome/browser/chromeos/memory/oom_priority_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <vector> 9 #include <vector>
10 10
(...skipping 13 matching lines...) Expand all
24 #include "base/utf_string_conversions.h" 24 #include "base/utf_string_conversions.h"
25 #include "build/build_config.h" 25 #include "build/build_config.h"
26 #include "chrome/browser/browser_process.h" 26 #include "chrome/browser/browser_process.h"
27 #include "chrome/browser/chromeos/memory/low_memory_observer.h" 27 #include "chrome/browser/chromeos/memory/low_memory_observer.h"
28 #include "chrome/browser/memory_details.h" 28 #include "chrome/browser/memory_details.h"
29 #include "chrome/browser/ui/browser.h" 29 #include "chrome/browser/ui/browser.h"
30 #include "chrome/browser/ui/browser_list.h" 30 #include "chrome/browser/ui/browser_list.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h" 31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/common/chrome_constants.h" 32 #include "chrome/common/chrome_constants.h"
33 #include "chrome/common/chrome_switches.h" 33 #include "chrome/common/chrome_switches.h"
34 #include "chrome/common/url_constants.h"
34 #include "content/public/browser/browser_thread.h" 35 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/notification_service.h" 36 #include "content/public/browser/notification_service.h"
36 #include "content/public/browser/notification_types.h" 37 #include "content/public/browser/notification_types.h"
37 #include "content/public/browser/render_process_host.h" 38 #include "content/public/browser/render_process_host.h"
38 #include "content/public/browser/render_widget_host.h" 39 #include "content/public/browser/render_widget_host.h"
39 #include "content/public/browser/web_contents.h" 40 #include "content/public/browser/web_contents.h"
40 #include "content/public/browser/zygote_host_linux.h" 41 #include "content/public/browser/zygote_host_linux.h"
41 #include "ui/base/text/bytes_formatting.h" 42 #include "ui/base/text/bytes_formatting.h"
42 43
43 using base::TimeDelta; 44 using base::TimeDelta;
(...skipping 25 matching lines...) Expand all
69 // value. 70 // value.
70 const int kAdjustmentIntervalSeconds = 10; 71 const int kAdjustmentIntervalSeconds = 10;
71 72
72 // If there has been no priority adjustment in this interval, we assume the 73 // If there has been no priority adjustment in this interval, we assume the
73 // machine was suspended and correct our timing statistics. 74 // machine was suspended and correct our timing statistics.
74 const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4; 75 const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4;
75 76
76 // The default interval in milliseconds to wait before setting the score of 77 // The default interval in milliseconds to wait before setting the score of
77 // currently focused tab. Must be be long enough that a user who is flipping 78 // currently focused tab. Must be be long enough that a user who is flipping
78 // through tabs with Ctrl-Tab does not mark each every tab as "focused". 79 // through tabs with Ctrl-Tab does not mark each every tab as "focused".
79 const int kFocusedTabScoreAdjustIntervalMs = 2000; 80 const int kFocusedTabScoreAdjustIntervalMs = 1500;
80 81
81 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as 82 // Returns a unique ID for a WebContents. Do not cast back to a pointer, as
82 // the WebContents could be deleted if the user closed the tab. 83 // the WebContents could be deleted if the user closed the tab.
83 int64 IdFromWebContents(WebContents* web_contents) { 84 int64 IdFromWebContents(WebContents* web_contents) {
84 return reinterpret_cast<int64>(web_contents); 85 return reinterpret_cast<int64>(web_contents);
85 } 86 }
86 87
87 //////////////////////////////////////////////////////////////////////////////// 88 ////////////////////////////////////////////////////////////////////////////////
88 // OomMemoryDetails logs details about all Chrome processes during an out-of- 89 // OomMemoryDetails logs details about all Chrome processes during an out-of-
89 // memory event in an attempt to identify the culprit, then discards a tab and 90 // memory event in an attempt to identify the culprit, then discards a tab and
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 Release(); 128 Release();
128 } 129 }
129 130
130 } // namespace 131 } // namespace
131 132
132 //////////////////////////////////////////////////////////////////////////////// 133 ////////////////////////////////////////////////////////////////////////////////
133 // OomPriorityManager 134 // OomPriorityManager
134 135
135 OomPriorityManager::TabStats::TabStats() 136 OomPriorityManager::TabStats::TabStats()
136 : is_app(false), 137 : is_app(false),
138 is_reloadable_ui(false),
137 is_pinned(false), 139 is_pinned(false),
138 is_selected(false), 140 is_selected(false),
139 is_discarded(false), 141 is_discarded(false),
140 renderer_handle(0), 142 renderer_handle(0),
141 tab_contents_id(0) { 143 tab_contents_id(0) {
142 } 144 }
143 145
144 OomPriorityManager::TabStats::~TabStats() { 146 OomPriorityManager::TabStats::~TabStats() {
145 } 147 }
146 148
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 TabStatsList::iterator it = stats.begin(); 194 TabStatsList::iterator it = stats.begin();
193 for ( ; it != stats.end(); ++it) { 195 for ( ; it != stats.end(); ++it) {
194 string16 str; 196 string16 str;
195 str.reserve(4096); 197 str.reserve(4096);
196 str += it->title; 198 str += it->title;
197 str += ASCIIToUTF16(" ("); 199 str += ASCIIToUTF16(" (");
198 int score = pid_to_oom_score_[it->renderer_handle]; 200 int score = pid_to_oom_score_[it->renderer_handle];
199 str += base::IntToString16(score); 201 str += base::IntToString16(score);
200 str += ASCIIToUTF16(")"); 202 str += ASCIIToUTF16(")");
201 str += ASCIIToUTF16(it->is_app ? " app" : ""); 203 str += ASCIIToUTF16(it->is_app ? " app" : "");
204 str += ASCIIToUTF16(it->is_reloadable_ui ? " reloadable_ui" : "");
202 str += ASCIIToUTF16(it->is_pinned ? " pinned" : ""); 205 str += ASCIIToUTF16(it->is_pinned ? " pinned" : "");
203 str += ASCIIToUTF16(it->is_discarded ? " discarded" : ""); 206 str += ASCIIToUTF16(it->is_discarded ? " discarded" : "");
204 titles.push_back(str); 207 titles.push_back(str);
205 } 208 }
206 return titles; 209 return titles;
207 } 210 }
208 211
209 // TODO(jamescook): This should consider tabs with references to other tabs, 212 // TODO(jamescook): This should consider tabs with references to other tabs,
210 // such as tabs created with JavaScript window.open(). We might want to 213 // such as tabs created with JavaScript window.open(). We might want to
211 // discard the entire set together, or use that in the priority computation. 214 // discard the entire set together, or use that in the priority computation.
(...skipping 13 matching lines...) Expand all
225 return false; 228 return false;
226 } 229 }
227 230
228 void OomPriorityManager::LogMemoryAndDiscardTab() { 231 void OomPriorityManager::LogMemoryAndDiscardTab() {
229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
230 // Deletes itself upon completion. 233 // Deletes itself upon completion.
231 OomMemoryDetails* details = new OomMemoryDetails(); 234 OomMemoryDetails* details = new OomMemoryDetails();
232 details->StartFetch(MemoryDetails::SKIP_USER_METRICS); 235 details->StartFetch(MemoryDetails::SKIP_USER_METRICS);
233 } 236 }
234 237
238 ///////////////////////////////////////////////////////////////////////////////
239 // OomPriorityManager, private:
240
241 // static
242 bool OomPriorityManager::IsReloadableUI(const GURL& url) {
243 // There are many chrome:// UI URLs, but only look for the ones that users
244 // are likely to have open. Most of the benefit is the from NTP URL.
245 const char* kReloadableUrlPrefixes[] = {
246 chrome::kChromeUIDownloadsURL,
247 chrome::kChromeUIHistoryURL,
248 chrome::kChromeUINewTabURL,
249 chrome::kChromeUISettingsURL,
Dan Beam 2016/06/01 17:30:36 why wouldn't we use WebUIControllerFactoryRegistry
250 };
251 // Prefix-match against the table above. Use strncmp to avoid allocating
252 // memory to convert the URL prefix constants into std::strings.
253 for (size_t i = 0; i < arraysize(kReloadableUrlPrefixes); ++i) {
254 if (!strncmp(url.spec().c_str(),
255 kReloadableUrlPrefixes[i],
256 strlen(kReloadableUrlPrefixes[i])))
257 return true;
258 }
259 return false;
260 }
261
235 bool OomPriorityManager::DiscardTabById(int64 target_web_contents_id) { 262 bool OomPriorityManager::DiscardTabById(int64 target_web_contents_id) {
236 for (BrowserList::const_iterator browser_iterator = BrowserList::begin(); 263 for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
237 browser_iterator != BrowserList::end(); ++browser_iterator) { 264 browser_iterator != BrowserList::end(); ++browser_iterator) {
238 Browser* browser = *browser_iterator; 265 Browser* browser = *browser_iterator;
239 TabStripModel* model = browser->tab_strip_model(); 266 TabStripModel* model = browser->tab_strip_model();
240 for (int idx = 0; idx < model->count(); idx++) { 267 for (int idx = 0; idx < model->count(); idx++) {
241 // Can't discard tabs that are already discarded or active. 268 // Can't discard tabs that are already discarded or active.
242 if (model->IsTabDiscarded(idx) || (model->active_index() == idx)) 269 if (model->IsTabDiscarded(idx) || (model->active_index() == idx))
243 continue; 270 continue;
244 WebContents* web_contents = model->GetWebContentsAt(idx); 271 WebContents* web_contents = model->GetWebContentsAt(idx);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 } 352 }
326 353
327 // Returns true if |first| is considered less desirable to be killed 354 // Returns true if |first| is considered less desirable to be killed
328 // than |second|. 355 // than |second|.
329 bool OomPriorityManager::CompareTabStats(TabStats first, 356 bool OomPriorityManager::CompareTabStats(TabStats first,
330 TabStats second) { 357 TabStats second) {
331 // Being currently selected is most important to protect. 358 // Being currently selected is most important to protect.
332 if (first.is_selected != second.is_selected) 359 if (first.is_selected != second.is_selected)
333 return first.is_selected; 360 return first.is_selected;
334 361
362 // Tab with internal web UI like NTP or Settings are good choices to discard,
363 // so protect non-Web UI and let the other conditionals finish the sort.
364 if (first.is_reloadable_ui != second.is_reloadable_ui)
365 return !first.is_reloadable_ui;
366
335 // Being pinned is important to protect. 367 // Being pinned is important to protect.
336 if (first.is_pinned != second.is_pinned) 368 if (first.is_pinned != second.is_pinned)
337 return first.is_pinned; 369 return first.is_pinned;
338 370
339 // Being an app is important too, as you're the only visible surface in the 371 // Being an app is important too, as you're the only visible surface in the
340 // window and we don't want to discard that. 372 // window and we don't want to discard that.
341 if (first.is_app != second.is_app) 373 if (first.is_app != second.is_app)
342 return first.is_app; 374 return first.is_app;
343 375
344 // TODO(jamescook): Incorporate sudden_termination_allowed into the sort 376 // TODO(jamescook): Incorporate sudden_termination_allowed into the sort
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
462 browser_iterator != BrowserList::end_last_active(); 494 browser_iterator != BrowserList::end_last_active();
463 ++browser_iterator) { 495 ++browser_iterator) {
464 Browser* browser = *browser_iterator; 496 Browser* browser = *browser_iterator;
465 bool is_browser_for_app = browser->is_app(); 497 bool is_browser_for_app = browser->is_app();
466 const TabStripModel* model = browser->tab_strip_model(); 498 const TabStripModel* model = browser->tab_strip_model();
467 for (int i = 0; i < model->count(); i++) { 499 for (int i = 0; i < model->count(); i++) {
468 WebContents* contents = model->GetWebContentsAt(i); 500 WebContents* contents = model->GetWebContentsAt(i);
469 if (!contents->IsCrashed()) { 501 if (!contents->IsCrashed()) {
470 TabStats stats; 502 TabStats stats;
471 stats.is_app = is_browser_for_app; 503 stats.is_app = is_browser_for_app;
504 stats.is_reloadable_ui = IsReloadableUI(contents->GetURL());
472 stats.is_pinned = model->IsTabPinned(i); 505 stats.is_pinned = model->IsTabPinned(i);
473 stats.is_selected = browser_active && model->IsTabSelected(i); 506 stats.is_selected = browser_active && model->IsTabSelected(i);
474 stats.is_discarded = model->IsTabDiscarded(i); 507 stats.is_discarded = model->IsTabDiscarded(i);
475 stats.last_selected = contents->GetLastSelectedTime(); 508 stats.last_selected = contents->GetLastSelectedTime();
476 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle(); 509 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
477 stats.title = contents->GetTitle(); 510 stats.title = contents->GetTitle();
478 stats.tab_contents_id = IdFromWebContents(contents); 511 stats.tab_contents_id = IdFromWebContents(contents);
479 stats_list.push_back(stats); 512 stats_list.push_back(stats);
480 } 513 }
481 } 514 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore( 565 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore(
533 iterator->renderer_handle, score); 566 iterator->renderer_handle, score);
534 pid_to_oom_score_[iterator->renderer_handle] = score; 567 pid_to_oom_score_[iterator->renderer_handle] = score;
535 } 568 }
536 priority += priority_increment; 569 priority += priority_increment;
537 } 570 }
538 } 571 }
539 } 572 }
540 573
541 } // namespace chromeos 574 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/memory/oom_priority_manager.h ('k') | chrome/browser/chromeos/memory/oom_priority_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698