summaryrefslogtreecommitdiffstats
path: root/components/web_cache/browser/web_cache_manager.h
blob: 2d6d3001e719af6bf17903346d42f0e2baa3673d (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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
// Copyright (c) 2011 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.

// This is the browser side of the cache manager, it tracks the activity of the
// render processes and allocates available memory cache resources.

#ifndef COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_
#define COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_

#include <stddef.h>

#include <list>
#include <map>
#include <set>

#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "third_party/WebKit/public/web/WebCache.h"

namespace base {
template<typename Type>
struct DefaultSingletonTraits;
}  // namespace base

class PrefRegistrySimple;

namespace web_cache {

class WebCacheManager : public content::NotificationObserver {
  friend class WebCacheManagerTest;
  FRIEND_TEST_ALL_PREFIXES(
      WebCacheManagerTest,
      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_1);
  FRIEND_TEST_ALL_PREFIXES(
      WebCacheManagerTest,
      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_2);
  FRIEND_TEST_ALL_PREFIXES(
      WebCacheManagerTest,
      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_3);
  FRIEND_TEST_ALL_PREFIXES(
      WebCacheManagerTest,
      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_4);
  FRIEND_TEST_ALL_PREFIXES(
      WebCacheManagerTest,
      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_5);
  FRIEND_TEST_ALL_PREFIXES(
      WebCacheManagerTest,
      CallRemoveRendererAndObserveActivityInAnyOrderShouldNotCrashTest_6);

 public:
  // Gets the singleton WebCacheManager object.  The first time this method
  // is called, a WebCacheManager object is constructed and returned.
  // Subsequent calls will return the same object.
  static WebCacheManager* GetInstance();

  // When a render process is created, it registers itself with the cache
  // manager host, causing the renderer to be allocated cache resources.
  void Add(int renderer_id);

  // When a render process ends, it removes itself from the cache manager host,
  // freeing the manager to assign its cache resources to other renderers.
  void Remove(int renderer_id);

  // The cache manager assigns more cache resources to active renderer.  When a
  // renderer is active, it should inform the cache manager to receive more
  // cache resources.
  //
  // When a renderer moves from being inactive to being active, the cache
  // manager may decide to adjust its resource allocation, but it will delay
  // the recalculation, allowing ObserveActivity to return quickly.
  void ObserveActivity(int renderer_id);

  // Periodically, renderers should inform the cache manager of their current
  // statistics.  The more up-to-date the cache manager's statistics, the
  // better it can allocate cache resources.
  void ObserveStats(
      int renderer_id, const blink::WebCache::UsageStats& stats);

  // The global limit on the number of bytes in all the in-memory caches.
  size_t global_size_limit() const { return global_size_limit_; }

  // Sets the global size limit, forcing a recalculation of cache allocations.
  void SetGlobalSizeLimit(size_t bytes);

  // Clears all in-memory caches.
  void ClearCache();

  // Instantly clears renderer cache for a process.
  void ClearCacheForProcess(int process_id);

  // Clears all in-memory caches when a tab is reloaded or the user navigates
  // to a different website.
  void ClearCacheOnNavigation();

  // content::NotificationObserver implementation:
  void Observe(int type,
               const content::NotificationSource& source,
               const content::NotificationDetails& details) override;

  // Gets the default global size limit.  This interrogates system metrics to
  // tune the default size to the current system.
  static size_t GetDefaultGlobalSizeLimit();

 protected:
  // The amount of idle time before we consider a tab to be "inactive"
  static const int kRendererInactiveThresholdMinutes = 5;

  // Keep track of some renderer information.
  struct RendererInfo : blink::WebCache::UsageStats {
    // The access time for this renderer.
    base::Time access;
  };

  typedef std::map<int, RendererInfo> StatsMap;

  // An allocation is the number of bytes a specific renderer should use for
  // its cache.
  typedef std::pair<int,size_t> Allocation;

  // An allocation strategy is a list of allocations specifying the resources
  // each renderer is permitted to consume for its cache.
  typedef std::list<Allocation> AllocationStrategy;

  // This class is a singleton.  Do not instantiate directly.
  WebCacheManager();
  friend struct base::DefaultSingletonTraits<WebCacheManager>;

  ~WebCacheManager() override;

  // Recomputes the allocation of cache resources among the renderers.  Also
  // informs the renderers of their new allocation.
  void ReviseAllocationStrategy();

  // Schedules a call to ReviseAllocationStrategy after a short delay.
  void ReviseAllocationStrategyLater();

  // The various tactics used as part of an allocation strategy.  To decide
  // how many resources a given renderer should be allocated, we consider its
  // usage statistics.  Each tactic specifies the function that maps usage
  // statistics to resource allocations.
  //
  // Determining a resource allocation strategy amounts to picking a tactic
  // for each renderer and checking that the total memory required fits within
  // our |global_size_limit_|.
  enum AllocationTactic {
    // Ignore cache statistics and divide resources equally among the given
    // set of caches.
    DIVIDE_EVENLY,

    // Allow each renderer to keep its current set of cached resources, with
    // some extra allocation to store new objects.
    KEEP_CURRENT_WITH_HEADROOM,

    // Allow each renderer to keep its current set of cached resources.
    KEEP_CURRENT,

    // Allow each renderer to keep cache resources it believes are currently
    // being used, with some extra allocation to store new objects.
    KEEP_LIVE_WITH_HEADROOM,

    // Allow each renderer to keep cache resources it believes are currently
    // being used, but instruct the renderer to discard all other data.
    KEEP_LIVE,
  };

  // Helper functions for devising an allocation strategy

  // Add up all the stats from the given set of renderers and place the result
  // in |stats|.
  void GatherStats(const std::set<int>& renderers,
                   blink::WebCache::UsageStats* stats);

  // Get the amount of memory that would be required to implement |tactic|
  // using the specified allocation tactic.  This function defines the
  // semantics for each of the tactics.
  static size_t GetSize(AllocationTactic tactic,
                        const blink::WebCache::UsageStats& stats);

  // Attempt to use the specified tactics to compute an allocation strategy
  // and place the result in |strategy|.  |active_stats| and |inactive_stats|
  // are the aggregate statistics for |active_renderers_| and
  // |inactive_renderers_|, respectively.
  //
  // Returns |true| on success and |false| on failure.  Does not modify
  // |strategy| on failure.
  bool AttemptTactic(AllocationTactic active_tactic,
                     const blink::WebCache::UsageStats& active_stats,
                     AllocationTactic inactive_tactic,
                     const blink::WebCache::UsageStats& inactive_stats,
                     AllocationStrategy* strategy);

  // For each renderer in |renderers|, computes its allocation according to
  // |tactic| and add the result to |strategy|.  Any |extra_bytes_to_allocate|
  // is divided evenly among the renderers.
  void AddToStrategy(const std::set<int>& renderers,
                     AllocationTactic tactic,
                     size_t extra_bytes_to_allocate,
                     AllocationStrategy* strategy);

  // Enact an allocation strategy by informing the renderers of their
  // allocations according to |strategy|.
  void EnactStrategy(const AllocationStrategy& strategy);

  enum ClearCacheOccasion {
    // Instructs to clear the cache instantly.
    INSTANTLY,
    // Instructs to clear the cache when a navigation takes place (this
    // includes reloading a tab).
    ON_NAVIGATION
  };

  // Inform all |renderers| to clear their cache.
  void ClearRendererCache(const std::set<int>& renderers,
                          ClearCacheOccasion occation);

  // Check to see if any active renderers have fallen inactive.
  void FindInactiveRenderers();

  // The global size limit for all in-memory caches.
  size_t global_size_limit_;

  // Maps every renderer_id our most recent copy of its statistics.
  StatsMap stats_;

  // Every renderer we think is still around is in one of these two sets.
  //
  // Active renderers are those renderers that have been active more recently
  // than they have been inactive.
  std::set<int> active_renderers_;
  // Inactive renderers are those renderers that have been inactive more
  // recently than they have been active.
  std::set<int> inactive_renderers_;

  content::NotificationRegistrar registrar_;

  base::WeakPtrFactory<WebCacheManager> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(WebCacheManager);
};

}  // namespace web_cache

#endif  // COMPONENTS_WEB_CACHE_BROWSER_WEB_CACHE_MANAGER_H_