summaryrefslogtreecommitdiffstats
path: root/chrome/browser/oom_priority_manager.h
blob: 866ec4de572f64dd4d53e6822dc5c5bfd89bec7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_OOM_PRIORITY_MANAGER_H_
#define CHROME_BROWSER_OOM_PRIORITY_MANAGER_H_

#include <vector>

#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "base/process.h"
#include "base/string16.h"
#include "base/synchronization/lock.h"
#include "base/time.h"
#include "base/timer.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"

namespace browser {

class LowMemoryObserver;

// The OomPriorityManager periodically checks (see
// ADJUSTMENT_INTERVAL_SECONDS in the source) the status of renderers
// and adjusts the out of memory (OOM) adjustment value (in
// /proc/<pid>/oom_score_adj) of the renderers so that they match the
// algorithm embedded here for priority in being killed upon OOM
// conditions.
//
// The algorithm used favors killing tabs that are not selected, not pinned,
// and have been idle for longest, in that order of priority.
class OomPriorityManager : public content::NotificationObserver {
 public:
  OomPriorityManager();
  virtual ~OomPriorityManager();

  void Start();
  void Stop();

  // Returns list of tab titles sorted from most interesting (don't kill)
  // to least interesting (OK to kill).
  std::vector<string16> GetTabTitles();

  // Discards a tab to free the memory occupied by its renderer.
  // Tab still exists in the tab-strip; clicking on it will reload it.
  // Returns true if it successfully found a tab and discarded it.
  bool DiscardTab();

 private:
  FRIEND_TEST_ALL_PREFIXES(OomPriorityManagerTest, Comparator);

  struct TabStats {
    TabStats();
    ~TabStats();
    bool is_pinned;
    bool is_selected;
    base::TimeTicks last_selected;
    base::ProcessHandle renderer_handle;
    bool sudden_termination_allowed;
    string16 title;
    int64 tab_contents_id;  // unique ID per WebContents
  };
  typedef std::vector<TabStats> TabStatsList;

  // Discards a tab with the given unique ID.  Returns true if discard occurred.
  bool DiscardTabById(int64 target_web_contents_id);

  // Records UMA histogram statistics for a tab discard. We record statistics
  // for user triggered discards via chrome://discards/ because that allows us
  // to manually test the system.
  void RecordDiscardStatistics();

  // Returns the number of tabs open in all browser instances.
  int GetTabCount() const;

  TabStatsList GetTabStatsOnUIThread();

  // Called when the timer fires, sets oom_adjust_score for all renderers.
  void AdjustOomPriorities();

  // Called by AdjustOomPriorities.
  void AdjustOomPrioritiesOnFileThread(TabStatsList stats_list);

  // Posts AdjustFocusedTabScore task to the file thread.
  void OnFocusTabScoreAdjustmentTimeout();

  // Sets the score of the focused tab to the least value.
  void AdjustFocusedTabScoreOnFileThread();

  static bool CompareTabStats(TabStats first, TabStats second);

  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  base::RepeatingTimer<OomPriorityManager> timer_;
  base::OneShotTimer<OomPriorityManager> focus_tab_score_adjust_timer_;
  content::NotificationRegistrar registrar_;

  // This lock is for pid_to_oom_score_ and focus_tab_pid_.
  base::Lock pid_to_oom_score_lock_;
  // map maintaining the process - oom_score mapping.
  typedef base::hash_map<base::ProcessHandle, int> ProcessScoreMap;
  ProcessScoreMap pid_to_oom_score_;
  base::ProcessHandle focused_tab_pid_;

  scoped_ptr<LowMemoryObserver> low_memory_observer_;

  // Wall-clock time when the priority manager started running.
  base::TimeTicks start_time_;

  // Wall-clock time of last tab discard during this browsing session, or 0 if
  // no discard has happened yet.
  base::TimeTicks last_discard_time_;

  // Wall-clock time of last priority adjustment, used to correct the above
  // times for discontinuities caused by suspend/resume.
  base::TimeTicks last_adjust_time_;

  // Number of times we have discarded a tab, for statistics.
  int discard_count_;

  DISALLOW_COPY_AND_ASSIGN(OomPriorityManager);
};

}  // namespace browser

#endif  // CHROME_BROWSER_OOM_PRIORITY_MANAGER_H_