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

Side by Side Diff: components/web_cache/browser/web_cache_manager.cc

Issue 2435603002: [WeakMemoryCache] Remove dead/live distinction of Resource outside core/fetch (Closed)
Patch Set: Rebase Created 4 years 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
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 "components/web_cache/browser/web_cache_manager.h" 5 #include "components/web_cache/browser/web_cache_manager.h"
6 6
7 #include <string.h> 7 #include <string.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 10
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 inactive_renderers_.erase(elmt); 128 inactive_renderers_.erase(elmt);
129 129
130 // A renderer that was inactive, just became active. We should make sure 130 // A renderer that was inactive, just became active. We should make sure
131 // it is given a fair cache allocation, but we defer this for a bit in 131 // it is given a fair cache allocation, but we defer this for a bit in
132 // order to make this function call cheap. 132 // order to make this function call cheap.
133 ReviseAllocationStrategyLater(); 133 ReviseAllocationStrategyLater();
134 } 134 }
135 } 135 }
136 136
137 void WebCacheManager::ObserveStats(int renderer_id, 137 void WebCacheManager::ObserveStats(int renderer_id,
138 uint64_t min_dead_capacity,
139 uint64_t max_dead_capacity,
140 uint64_t capacity, 138 uint64_t capacity,
141 uint64_t live_size, 139 uint64_t size) {
142 uint64_t dead_size) {
143 StatsMap::iterator entry = stats_.find(renderer_id); 140 StatsMap::iterator entry = stats_.find(renderer_id);
144 if (entry == stats_.end()) 141 if (entry == stats_.end())
145 return; // We might see stats for a renderer that has been destroyed. 142 return; // We might see stats for a renderer that has been destroyed.
146 143
147 // Record the updated stats. 144 // Record the updated stats.
148 entry->second.capacity = capacity; 145 entry->second.capacity = capacity;
149 entry->second.dead_size = dead_size; 146 entry->second.size = size;
150 entry->second.live_size = live_size;
151 entry->second.max_dead_capacity = max_dead_capacity;
152 entry->second.min_dead_capacity = min_dead_capacity;
153 } 147 }
154 148
155 void WebCacheManager::SetGlobalSizeLimit(uint64_t bytes) { 149 void WebCacheManager::SetGlobalSizeLimit(uint64_t bytes) {
156 global_size_limit_ = bytes; 150 global_size_limit_ = bytes;
157 ReviseAllocationStrategyLater(); 151 ReviseAllocationStrategyLater();
158 } 152 }
159 153
160 void WebCacheManager::ClearCache() { 154 void WebCacheManager::ClearCache() {
161 // Tell each renderer process to clear the cache. 155 // Tell each renderer process to clear the cache.
162 ClearRendererCache(active_renderers_, INSTANTLY); 156 ClearRendererCache(active_renderers_, INSTANTLY);
(...skipping 29 matching lines...) Expand all
192 } 186 }
193 } 187 }
194 188
195 // static 189 // static
196 uint64_t WebCacheManager::GetDefaultGlobalSizeLimit() { 190 uint64_t WebCacheManager::GetDefaultGlobalSizeLimit() {
197 return GetDefaultCacheSize(); 191 return GetDefaultCacheSize();
198 } 192 }
199 193
200 void WebCacheManager::GatherStats(const std::set<int>& renderers, 194 void WebCacheManager::GatherStats(const std::set<int>& renderers,
201 uint64_t* capacity, 195 uint64_t* capacity,
202 uint64_t* live_size, 196 uint64_t* size) {
203 uint64_t* dead_size) { 197 *capacity = *size = 0;
204 *capacity = *live_size = *dead_size = 0;
205 198
206 std::set<int>::const_iterator iter = renderers.begin(); 199 std::set<int>::const_iterator iter = renderers.begin();
207 while (iter != renderers.end()) { 200 while (iter != renderers.end()) {
208 StatsMap::iterator elmt = stats_.find(*iter); 201 StatsMap::iterator elmt = stats_.find(*iter);
209 if (elmt != stats_.end()) { 202 if (elmt != stats_.end()) {
210 *capacity += elmt->second.capacity; 203 *capacity += elmt->second.capacity;
211 *live_size += elmt->second.live_size; 204 *size += elmt->second.size;
212 *dead_size += elmt->second.dead_size;
213 } 205 }
214 ++iter; 206 ++iter;
215 } 207 }
216 } 208 }
217 209
218 // static 210 // static
219 uint64_t WebCacheManager::GetSize(AllocationTactic tactic, 211 uint64_t WebCacheManager::GetSize(AllocationTactic tactic, uint64_t size) {
220 uint64_t live_size,
221 uint64_t dead_size) {
222 switch (tactic) { 212 switch (tactic) {
223 case DIVIDE_EVENLY: 213 case DIVIDE_EVENLY:
224 // We aren't going to reserve any space for existing objects. 214 // We aren't going to reserve any space for existing objects.
225 return 0; 215 return 0;
226 case KEEP_CURRENT_WITH_HEADROOM: 216 case KEEP_CURRENT_WITH_HEADROOM:
227 // We need enough space for our current objects, plus some headroom. 217 // We need enough space for our current objects, plus some headroom.
228 return 3 * GetSize(KEEP_CURRENT, live_size, dead_size) / 2; 218 return 3 * GetSize(KEEP_CURRENT, size) / 2;
229 case KEEP_CURRENT: 219 case KEEP_CURRENT:
230 // We need enough space to keep our current objects. 220 // We need enough space to keep our current objects.
231 return live_size + dead_size; 221 return size;
232 case KEEP_LIVE_WITH_HEADROOM:
233 // We need enough space to keep out live resources, plus some headroom.
234 return 3 * GetSize(KEEP_LIVE, live_size, dead_size) / 2;
235 case KEEP_LIVE:
236 // We need enough space to keep our live resources.
237 return live_size;
238 default: 222 default:
239 NOTREACHED() << "Unknown cache allocation tactic"; 223 NOTREACHED() << "Unknown cache allocation tactic";
240 return 0; 224 return 0;
241 } 225 }
242 } 226 }
243 227
244 bool WebCacheManager::AttemptTactic( 228 bool WebCacheManager::AttemptTactic(AllocationTactic active_tactic,
245 AllocationTactic active_tactic, 229 uint64_t active_used_size,
246 uint64_t active_live_size, 230 AllocationTactic inactive_tactic,
247 uint64_t active_dead_size, 231 uint64_t inactive_used_size,
248 AllocationTactic inactive_tactic, 232 AllocationStrategy* strategy) {
249 uint64_t inactive_live_size,
250 uint64_t inactive_dead_size,
251 AllocationStrategy* strategy) {
252 DCHECK(strategy); 233 DCHECK(strategy);
253 234
254 uint64_t active_size = GetSize(active_tactic, active_live_size, 235 uint64_t active_size = GetSize(active_tactic, active_used_size);
255 active_dead_size); 236 uint64_t inactive_size = GetSize(inactive_tactic, inactive_used_size);
256 uint64_t inactive_size = GetSize(inactive_tactic, inactive_live_size,
257 inactive_dead_size);
258 237
259 // Give up if we don't have enough space to use this tactic. 238 // Give up if we don't have enough space to use this tactic.
260 if (global_size_limit_ < active_size + inactive_size) 239 if (global_size_limit_ < active_size + inactive_size)
261 return false; 240 return false;
262 241
263 // Compute the unreserved space available. 242 // Compute the unreserved space available.
264 uint64_t total_extra = global_size_limit_ - (active_size + inactive_size); 243 uint64_t total_extra = global_size_limit_ - (active_size + inactive_size);
265 244
266 // The plan for the extra space is to divide it evenly amoung the active 245 // The plan for the extra space is to divide it evenly amoung the active
267 // renderers. 246 // renderers.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
300 // Divide the extra memory evenly among the renderers. 279 // Divide the extra memory evenly among the renderers.
301 uint64_t extra_each = extra_bytes_to_allocate / renderers.size(); 280 uint64_t extra_each = extra_bytes_to_allocate / renderers.size();
302 281
303 std::set<int>::const_iterator iter = renderers.begin(); 282 std::set<int>::const_iterator iter = renderers.begin();
304 while (iter != renderers.end()) { 283 while (iter != renderers.end()) {
305 uint64_t cache_size = extra_each; 284 uint64_t cache_size = extra_each;
306 285
307 // Add in the space required to implement |tactic|. 286 // Add in the space required to implement |tactic|.
308 StatsMap::iterator elmt = stats_.find(*iter); 287 StatsMap::iterator elmt = stats_.find(*iter);
309 if (elmt != stats_.end()) { 288 if (elmt != stats_.end()) {
310 cache_size += GetSize(tactic, elmt->second.live_size, 289 cache_size += GetSize(tactic, elmt->second.size);
311 elmt->second.dead_size);
312 } 290 }
313 291
314 // Record the allocation in our strategy. 292 // Record the allocation in our strategy.
315 strategy->push_back(Allocation(*iter, cache_size)); 293 strategy->push_back(Allocation(*iter, cache_size));
316 ++iter; 294 ++iter;
317 } 295 }
318 } 296 }
319 297
320 void WebCacheManager::EnactStrategy(const AllocationStrategy& strategy) { 298 void WebCacheManager::EnactStrategy(const AllocationStrategy& strategy) {
321 // Inform each render process of its cache allocation. 299 // Inform each render process of its cache allocation.
322 AllocationStrategy::const_iterator allocation = strategy.begin(); 300 AllocationStrategy::const_iterator allocation = strategy.begin();
323 while (allocation != strategy.end()) { 301 while (allocation != strategy.end()) {
324 content::RenderProcessHost* host = 302 content::RenderProcessHost* host =
325 content::RenderProcessHost::FromID(allocation->first); 303 content::RenderProcessHost::FromID(allocation->first);
326 if (host) { 304 if (host) {
327 // This is the capacity this renderer has been allocated. 305 // This is the capacity this renderer has been allocated.
328 uint64_t capacity = allocation->second; 306 uint64_t capacity = allocation->second;
329 307
330 // We don't reserve any space for dead objects in the cache. Instead, we
331 // prefer to keep live objects around. There is probably some performance
332 // tuning to be done here.
333 uint64_t min_dead_capacity = 0;
334
335 // We allow the dead objects to consume up to half of the cache capacity.
336 uint64_t max_dead_capacity = capacity / 2;
337 if (base::SysInfo::IsLowEndDevice()) {
338 max_dead_capacity = std::min(static_cast<uint64_t>(512 * 1024u),
339 max_dead_capacity);
340 }
341
342 // Find the WebCachePtr by renderer process id. 308 // Find the WebCachePtr by renderer process id.
343 auto it = web_cache_services_.find(allocation->first); 309 auto it = web_cache_services_.find(allocation->first);
344 DCHECK(it != web_cache_services_.end()); 310 DCHECK(it != web_cache_services_.end());
345 const mojom::WebCachePtr& service = it->second; 311 const mojom::WebCachePtr& service = it->second;
346 DCHECK(service); 312 DCHECK(service);
347 service->SetCacheCapacities(min_dead_capacity, max_dead_capacity, 313 service->SetCacheCapacity(capacity);
348 capacity);
349 } 314 }
350 ++allocation; 315 ++allocation;
351 } 316 }
352 } 317 }
353 318
354 void WebCacheManager::ClearCacheForProcess(int render_process_id) { 319 void WebCacheManager::ClearCacheForProcess(int render_process_id) {
355 std::set<int> renderers; 320 std::set<int> renderers;
356 renderers.insert(render_process_id); 321 renderers.insert(render_process_id);
357 ClearRendererCache(renderers, INSTANTLY); 322 ClearRendererCache(renderers, INSTANTLY);
358 } 323 }
(...skipping 17 matching lines...) Expand all
376 } 341 }
377 342
378 void WebCacheManager::ReviseAllocationStrategy() { 343 void WebCacheManager::ReviseAllocationStrategy() {
379 DCHECK(stats_.size() <= 344 DCHECK(stats_.size() <=
380 active_renderers_.size() + inactive_renderers_.size()); 345 active_renderers_.size() + inactive_renderers_.size());
381 346
382 // Check if renderers have gone inactive. 347 // Check if renderers have gone inactive.
383 FindInactiveRenderers(); 348 FindInactiveRenderers();
384 349
385 // Gather statistics 350 // Gather statistics
386 uint64_t active_capacity, active_live_size, active_dead_size, 351 uint64_t active_capacity, active_size, inactive_capacity, inactive_size;
387 inactive_capacity, inactive_live_size, inactive_dead_size; 352 GatherStats(active_renderers_, &active_capacity, &active_size);
388 GatherStats(active_renderers_, &active_capacity, &active_live_size, 353 GatherStats(inactive_renderers_, &inactive_capacity, &inactive_size);
389 &active_dead_size);
390 GatherStats(inactive_renderers_, &inactive_capacity, &inactive_live_size,
391 &inactive_dead_size);
392 354
393 UMA_HISTOGRAM_COUNTS_100("Cache.ActiveTabs", active_renderers_.size()); 355 UMA_HISTOGRAM_COUNTS_100("Cache.ActiveTabs", active_renderers_.size());
394 UMA_HISTOGRAM_COUNTS_100("Cache.InactiveTabs", inactive_renderers_.size()); 356 UMA_HISTOGRAM_COUNTS_100("Cache.InactiveTabs", inactive_renderers_.size());
395 UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveCapacityMB", 357 UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveCapacityMB",
396 active_capacity / 1024 / 1024); 358 active_capacity / 1024 / 1024);
397 UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveDeadSizeMB", 359 UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveLiveSizeMB", active_size / 1024 / 1024);
398 active_dead_size / 1024 / 1024);
399 UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveLiveSizeMB",
400 active_live_size / 1024 / 1024);
401 UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveCapacityMB", 360 UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveCapacityMB",
402 inactive_capacity / 1024 / 1024); 361 inactive_capacity / 1024 / 1024);
403 UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveDeadSizeMB",
404 inactive_dead_size / 1024 / 1024);
405 UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveLiveSizeMB", 362 UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveLiveSizeMB",
406 inactive_live_size / 1024 / 1024); 363 inactive_size / 1024 / 1024);
407 364
408 // Compute an allocation strategy. 365 // Compute an allocation strategy.
409 // 366 //
410 // We attempt various tactics in order of preference. Our first preference 367 // We attempt various tactics in order of preference. Our first preference
411 // is not to evict any objects. If we don't have enough resources, we'll 368 // is not to evict any objects. If we don't have enough resources, we'll
412 // first try to evict dead data only. If that fails, we'll just divide the 369 // first try to evict dead data only. If that fails, we'll just divide the
413 // resources we have evenly. 370 // resources we have evenly.
414 // 371 //
415 // We always try to give the active renderers some head room in their 372 // We always try to give the active renderers some head room in their
416 // allocations so they can take memory away from an inactive renderer with 373 // allocations so they can take memory away from an inactive renderer with
417 // a large cache allocation. 374 // a large cache allocation.
418 // 375 //
419 // Notice the early exit will prevent attempting less desirable tactics once 376 // Notice the early exit will prevent attempting less desirable tactics once
420 // we've found a workable strategy. 377 // we've found a workable strategy.
421 AllocationStrategy strategy; 378 AllocationStrategy strategy;
422 if ( // Ideally, we'd like to give the active renderers some headroom and 379 if ( // Ideally, we'd like to give the active renderers some headroom and
423 // keep all our current objects. 380 // keep all our current objects.
424 AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active_live_size, 381 AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active_size, KEEP_CURRENT,
425 active_dead_size, KEEP_CURRENT, inactive_live_size, 382 inactive_size, &strategy) ||
426 inactive_dead_size, &strategy) || 383 // Next, we try to keep the current objects in the active renders (with
427 // If we can't have that, then we first try to evict the dead objects in 384 // some room for new objects) and give whatever is left to the inactive
428 // the caches of inactive renderers.
429 AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active_live_size,
430 active_dead_size, KEEP_LIVE, inactive_live_size,
431 inactive_dead_size, &strategy) ||
432 // Next, we try to keep the live objects in the active renders (with some
433 // room for new objects) and give whatever is left to the inactive
434 // renderers. 385 // renderers.
435 AttemptTactic(KEEP_LIVE_WITH_HEADROOM, active_live_size, 386 AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active_size, DIVIDE_EVENLY,
436 active_dead_size, DIVIDE_EVENLY, inactive_live_size, 387 inactive_size, &strategy) ||
437 inactive_dead_size, &strategy) ||
438 // If we've gotten this far, then we are very tight on memory. Let's try 388 // If we've gotten this far, then we are very tight on memory. Let's try
439 // to at least keep around the live objects for the active renderers. 389 // to at least keep around the live objects for the active renderers.
440 AttemptTactic(KEEP_LIVE, active_live_size, active_dead_size, 390 AttemptTactic(KEEP_CURRENT, active_size, DIVIDE_EVENLY, inactive_size,
441 DIVIDE_EVENLY, inactive_live_size, inactive_dead_size,
442 &strategy) || 391 &strategy) ||
443 // We're basically out of memory. The best we can do is just divide up 392 // We're basically out of memory. The best we can do is just divide up
444 // what we have and soldier on. 393 // what we have and soldier on.
445 AttemptTactic(DIVIDE_EVENLY, active_live_size, active_dead_size, 394 AttemptTactic(DIVIDE_EVENLY, active_size, DIVIDE_EVENLY, inactive_size,
446 DIVIDE_EVENLY, inactive_live_size, inactive_dead_size,
447 &strategy)) { 395 &strategy)) {
448 // Having found a workable strategy, we enact it. 396 // Having found a workable strategy, we enact it.
449 EnactStrategy(strategy); 397 EnactStrategy(strategy);
450 } else { 398 } else {
451 // DIVIDE_EVENLY / DIVIDE_EVENLY should always succeed. 399 // DIVIDE_EVENLY / DIVIDE_EVENLY should always succeed.
452 NOTREACHED() << "Unable to find a cache allocation"; 400 NOTREACHED() << "Unable to find a cache allocation";
453 } 401 }
454 } 402 }
455 403
456 void WebCacheManager::ReviseAllocationStrategyLater() { 404 void WebCacheManager::ReviseAllocationStrategyLater() {
(...skipping 16 matching lines...) Expand all
473 inactive_renderers_.insert(*iter); 421 inactive_renderers_.insert(*iter);
474 active_renderers_.erase(*iter); 422 active_renderers_.erase(*iter);
475 iter = active_renderers_.begin(); 423 iter = active_renderers_.begin();
476 continue; 424 continue;
477 } 425 }
478 ++iter; 426 ++iter;
479 } 427 }
480 } 428 }
481 429
482 } // namespace web_cache 430 } // namespace web_cache
OLDNEW
« no previous file with comments | « components/web_cache/browser/web_cache_manager.h ('k') | components/web_cache/browser/web_cache_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698