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

Unified Diff: chrome/browser/renderer_host/web_cache_manager.cc

Issue 528363002: Move webCacheManager to //components. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/renderer_host/web_cache_manager.cc
diff --git a/chrome/browser/renderer_host/web_cache_manager.cc b/chrome/browser/renderer_host/web_cache_manager.cc
deleted file mode 100644
index a61a2c3eaaafc35043c5d938b1e5057d895b1fe5..0000000000000000000000000000000000000000
--- a/chrome/browser/renderer_host/web_cache_manager.cc
+++ /dev/null
@@ -1,444 +0,0 @@
-// 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.
-
-#include "chrome/browser/renderer_host/web_cache_manager.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/memory/singleton.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/histogram.h"
-#include "base/prefs/pref_registry_simple.h"
-#include "base/prefs/pref_service.h"
-#include "base/sys_info.h"
-#include "base/time/time.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/render_messages.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_process_host.h"
-
-using base::Time;
-using base::TimeDelta;
-using blink::WebCache;
-
-static const int kReviseAllocationDelayMS = 200;
-
-// The default size limit of the in-memory cache is 8 MB
-static const int kDefaultMemoryCacheSize = 8 * 1024 * 1024;
-
-namespace {
-
-int GetDefaultCacheSize() {
- // Start off with a modest default
- int default_cache_size = kDefaultMemoryCacheSize;
-
- // Check how much physical memory the OS has
- int mem_size_mb = base::SysInfo::AmountOfPhysicalMemoryMB();
- if (mem_size_mb >= 1000) // If we have a GB of memory, set a larger default.
- default_cache_size *= 4;
- else if (mem_size_mb >= 512) // With 512 MB, set a slightly larger default.
- default_cache_size *= 2;
-
- UMA_HISTOGRAM_MEMORY_MB("Cache.MaxCacheSizeMB",
- default_cache_size / 1024 / 1024);
-
- return default_cache_size;
-}
-
-} // anonymous namespace
-
-// static
-void WebCacheManager::RegisterPrefs(PrefRegistrySimple* registry) {
- registry->RegisterIntegerPref(prefs::kMemoryCacheSize, GetDefaultCacheSize());
-}
-
-// static
-WebCacheManager* WebCacheManager::GetInstance() {
- return Singleton<WebCacheManager>::get();
-}
-
-WebCacheManager::WebCacheManager()
- : global_size_limit_(GetDefaultGlobalSizeLimit()),
- weak_factory_(this) {
- registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
- content::NotificationService::AllBrowserContextsAndSources());
- registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
- content::NotificationService::AllBrowserContextsAndSources());
-}
-
-WebCacheManager::~WebCacheManager() {
-}
-
-void WebCacheManager::Add(int renderer_id) {
- DCHECK(inactive_renderers_.count(renderer_id) == 0);
-
- // It is tempting to make the following DCHECK here, but it fails when a new
- // tab is created as we observe activity from that tab because the
- // RenderProcessHost is recreated and adds itself.
- //
- // DCHECK(active_renderers_.count(renderer_id) == 0);
- //
- // However, there doesn't seem to be much harm in receiving the calls in this
- // order.
-
- active_renderers_.insert(renderer_id);
-
- RendererInfo* stats = &(stats_[renderer_id]);
- memset(stats, 0, sizeof(*stats));
- stats->access = Time::Now();
-
- // Revise our allocation strategy to account for this new renderer.
- ReviseAllocationStrategyLater();
-}
-
-void WebCacheManager::Remove(int renderer_id) {
- // Erase all knowledge of this renderer
- active_renderers_.erase(renderer_id);
- inactive_renderers_.erase(renderer_id);
- stats_.erase(renderer_id);
-
- // Reallocate the resources used by this renderer
- ReviseAllocationStrategyLater();
-}
-
-void WebCacheManager::ObserveActivity(int renderer_id) {
- StatsMap::iterator item = stats_.find(renderer_id);
- if (item == stats_.end())
- return; // We might see stats for a renderer that has been destroyed.
-
- // Record activity.
- active_renderers_.insert(renderer_id);
- item->second.access = Time::Now();
-
- std::set<int>::iterator elmt = inactive_renderers_.find(renderer_id);
- if (elmt != inactive_renderers_.end()) {
- inactive_renderers_.erase(elmt);
-
- // A renderer that was inactive, just became active. We should make sure
- // it is given a fair cache allocation, but we defer this for a bit in
- // order to make this function call cheap.
- ReviseAllocationStrategyLater();
- }
-}
-
-void WebCacheManager::ObserveStats(int renderer_id,
- const WebCache::UsageStats& stats) {
- StatsMap::iterator entry = stats_.find(renderer_id);
- if (entry == stats_.end())
- return; // We might see stats for a renderer that has been destroyed.
-
- // Record the updated stats.
- entry->second.capacity = stats.capacity;
- entry->second.deadSize = stats.deadSize;
- entry->second.liveSize = stats.liveSize;
- entry->second.maxDeadCapacity = stats.maxDeadCapacity;
- entry->second.minDeadCapacity = stats.minDeadCapacity;
-}
-
-void WebCacheManager::SetGlobalSizeLimit(size_t bytes) {
- global_size_limit_ = bytes;
- ReviseAllocationStrategyLater();
-}
-
-void WebCacheManager::ClearCache() {
- // Tell each renderer process to clear the cache.
- ClearRendererCache(active_renderers_, INSTANTLY);
- ClearRendererCache(inactive_renderers_, INSTANTLY);
-}
-
-void WebCacheManager::ClearCacheOnNavigation() {
- // Tell each renderer process to clear the cache when a tab is reloaded or
- // the user navigates to a new website.
- ClearRendererCache(active_renderers_, ON_NAVIGATION);
- ClearRendererCache(inactive_renderers_, ON_NAVIGATION);
-}
-
-void WebCacheManager::Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- switch (type) {
- case content::NOTIFICATION_RENDERER_PROCESS_CREATED: {
- content::RenderProcessHost* process =
- content::Source<content::RenderProcessHost>(source).ptr();
- Add(process->GetID());
- break;
- }
- case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: {
- content::RenderProcessHost* process =
- content::Source<content::RenderProcessHost>(source).ptr();
- Remove(process->GetID());
- break;
- }
- default:
- NOTREACHED();
- break;
- }
-}
-
-// static
-size_t WebCacheManager::GetDefaultGlobalSizeLimit() {
- PrefService* perf_service = g_browser_process->local_state();
- if (perf_service)
- return perf_service->GetInteger(prefs::kMemoryCacheSize);
-
- return GetDefaultCacheSize();
-}
-
-void WebCacheManager::GatherStats(const std::set<int>& renderers,
- WebCache::UsageStats* stats) {
- DCHECK(stats);
-
- memset(stats, 0, sizeof(WebCache::UsageStats));
-
- std::set<int>::const_iterator iter = renderers.begin();
- while (iter != renderers.end()) {
- StatsMap::iterator elmt = stats_.find(*iter);
- if (elmt != stats_.end()) {
- stats->minDeadCapacity += elmt->second.minDeadCapacity;
- stats->maxDeadCapacity += elmt->second.maxDeadCapacity;
- stats->capacity += elmt->second.capacity;
- stats->liveSize += elmt->second.liveSize;
- stats->deadSize += elmt->second.deadSize;
- }
- ++iter;
- }
-}
-
-// static
-size_t WebCacheManager::GetSize(AllocationTactic tactic,
- const WebCache::UsageStats& stats) {
- switch (tactic) {
- case DIVIDE_EVENLY:
- // We aren't going to reserve any space for existing objects.
- return 0;
- case KEEP_CURRENT_WITH_HEADROOM:
- // We need enough space for our current objects, plus some headroom.
- return 3 * GetSize(KEEP_CURRENT, stats) / 2;
- case KEEP_CURRENT:
- // We need enough space to keep our current objects.
- return stats.liveSize + stats.deadSize;
- case KEEP_LIVE_WITH_HEADROOM:
- // We need enough space to keep out live resources, plus some headroom.
- return 3 * GetSize(KEEP_LIVE, stats) / 2;
- case KEEP_LIVE:
- // We need enough space to keep our live resources.
- return stats.liveSize;
- default:
- NOTREACHED() << "Unknown cache allocation tactic";
- return 0;
- }
-}
-
-bool WebCacheManager::AttemptTactic(
- AllocationTactic active_tactic,
- const WebCache::UsageStats& active_stats,
- AllocationTactic inactive_tactic,
- const WebCache::UsageStats& inactive_stats,
- AllocationStrategy* strategy) {
- DCHECK(strategy);
-
- size_t active_size = GetSize(active_tactic, active_stats);
- size_t inactive_size = GetSize(inactive_tactic, inactive_stats);
-
- // Give up if we don't have enough space to use this tactic.
- if (global_size_limit_ < active_size + inactive_size)
- return false;
-
- // Compute the unreserved space available.
- size_t total_extra = global_size_limit_ - (active_size + inactive_size);
-
- // The plan for the extra space is to divide it evenly amoung the active
- // renderers.
- size_t shares = active_renderers_.size();
-
- // The inactive renderers get one share of the extra memory to be divided
- // among themselves.
- size_t inactive_extra = 0;
- if (!inactive_renderers_.empty()) {
- ++shares;
- inactive_extra = total_extra / shares;
- }
-
- // The remaining memory is allocated to the active renderers.
- size_t active_extra = total_extra - inactive_extra;
-
- // Actually compute the allocations for each renderer.
- AddToStrategy(active_renderers_, active_tactic, active_extra, strategy);
- AddToStrategy(inactive_renderers_, inactive_tactic, inactive_extra, strategy);
-
- // We succeeded in computing an allocation strategy.
- return true;
-}
-
-void WebCacheManager::AddToStrategy(const std::set<int>& renderers,
- AllocationTactic tactic,
- size_t extra_bytes_to_allocate,
- AllocationStrategy* strategy) {
- DCHECK(strategy);
-
- // Nothing to do if there are no renderers. It is common for there to be no
- // inactive renderers if there is a single active tab.
- if (renderers.empty())
- return;
-
- // Divide the extra memory evenly among the renderers.
- size_t extra_each = extra_bytes_to_allocate / renderers.size();
-
- std::set<int>::const_iterator iter = renderers.begin();
- while (iter != renderers.end()) {
- size_t cache_size = extra_each;
-
- // Add in the space required to implement |tactic|.
- StatsMap::iterator elmt = stats_.find(*iter);
- if (elmt != stats_.end())
- cache_size += GetSize(tactic, elmt->second);
-
- // Record the allocation in our strategy.
- strategy->push_back(Allocation(*iter, cache_size));
- ++iter;
- }
-}
-
-void WebCacheManager::EnactStrategy(const AllocationStrategy& strategy) {
- // Inform each render process of its cache allocation.
- AllocationStrategy::const_iterator allocation = strategy.begin();
- while (allocation != strategy.end()) {
- content::RenderProcessHost* host =
- content::RenderProcessHost::FromID(allocation->first);
- if (host) {
- // This is the capacity this renderer has been allocated.
- size_t capacity = allocation->second;
-
- // We don't reserve any space for dead objects in the cache. Instead, we
- // prefer to keep live objects around. There is probably some performance
- // tuning to be done here.
- size_t min_dead_capacity = 0;
-
- // We allow the dead objects to consume up to half of the cache capacity.
- size_t max_dead_capacity = capacity / 2;
- if (base::SysInfo::IsLowEndDevice()) {
- max_dead_capacity = std::min(static_cast<size_t>(512 * 1024),
- max_dead_capacity);
- }
- host->Send(new ChromeViewMsg_SetCacheCapacities(min_dead_capacity,
- max_dead_capacity,
- capacity));
- }
- ++allocation;
- }
-}
-
-void WebCacheManager::ClearRendererCache(
- const std::set<int>& renderers,
- WebCacheManager::ClearCacheOccasion occasion) {
- std::set<int>::const_iterator iter = renderers.begin();
- for (; iter != renderers.end(); ++iter) {
- content::RenderProcessHost* host =
- content::RenderProcessHost::FromID(*iter);
- if (host)
- host->Send(new ChromeViewMsg_ClearCache(occasion == ON_NAVIGATION));
- }
-}
-
-void WebCacheManager::ReviseAllocationStrategy() {
- DCHECK(stats_.size() <=
- active_renderers_.size() + inactive_renderers_.size());
-
- // Check if renderers have gone inactive.
- FindInactiveRenderers();
-
- // Gather statistics
- WebCache::UsageStats active;
- WebCache::UsageStats inactive;
- GatherStats(active_renderers_, &active);
- GatherStats(inactive_renderers_, &inactive);
-
- UMA_HISTOGRAM_COUNTS_100("Cache.ActiveTabs", active_renderers_.size());
- UMA_HISTOGRAM_COUNTS_100("Cache.InactiveTabs", inactive_renderers_.size());
- UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveCapacityMB",
- active.capacity / 1024 / 1024);
- UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveDeadSizeMB",
- active.deadSize / 1024 / 1024);
- UMA_HISTOGRAM_MEMORY_MB("Cache.ActiveLiveSizeMB",
- active.liveSize / 1024 / 1024);
- UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveCapacityMB",
- inactive.capacity / 1024 / 1024);
- UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveDeadSizeMB",
- inactive.deadSize / 1024 / 1024);
- UMA_HISTOGRAM_MEMORY_MB("Cache.InactiveLiveSizeMB",
- inactive.liveSize / 1024 / 1024);
-
- // Compute an allocation strategy.
- //
- // We attempt various tactics in order of preference. Our first preference
- // is not to evict any objects. If we don't have enough resources, we'll
- // first try to evict dead data only. If that fails, we'll just divide the
- // resources we have evenly.
- //
- // We always try to give the active renderers some head room in their
- // allocations so they can take memory away from an inactive renderer with
- // a large cache allocation.
- //
- // Notice the early exit will prevent attempting less desirable tactics once
- // we've found a workable strategy.
- AllocationStrategy strategy;
- if ( // Ideally, we'd like to give the active renderers some headroom and
- // keep all our current objects.
- AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active,
- KEEP_CURRENT, inactive, &strategy) ||
- // If we can't have that, then we first try to evict the dead objects in
- // the caches of inactive renderers.
- AttemptTactic(KEEP_CURRENT_WITH_HEADROOM, active,
- KEEP_LIVE, inactive, &strategy) ||
- // Next, we try to keep the live objects in the active renders (with some
- // room for new objects) and give whatever is left to the inactive
- // renderers.
- AttemptTactic(KEEP_LIVE_WITH_HEADROOM, active,
- DIVIDE_EVENLY, inactive, &strategy) ||
- // If we've gotten this far, then we are very tight on memory. Let's try
- // to at least keep around the live objects for the active renderers.
- AttemptTactic(KEEP_LIVE, active, DIVIDE_EVENLY, inactive, &strategy) ||
- // We're basically out of memory. The best we can do is just divide up
- // what we have and soldier on.
- AttemptTactic(DIVIDE_EVENLY, active, DIVIDE_EVENLY, inactive,
- &strategy)) {
- // Having found a workable strategy, we enact it.
- EnactStrategy(strategy);
- } else {
- // DIVIDE_EVENLY / DIVIDE_EVENLY should always succeed.
- NOTREACHED() << "Unable to find a cache allocation";
- }
-}
-
-void WebCacheManager::ReviseAllocationStrategyLater() {
- // Ask to be called back in a few milliseconds to actually recompute our
- // allocation.
- base::MessageLoop::current()->PostDelayedTask(FROM_HERE,
- base::Bind(
- &WebCacheManager::ReviseAllocationStrategy,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kReviseAllocationDelayMS));
-}
-
-void WebCacheManager::FindInactiveRenderers() {
- std::set<int>::const_iterator iter = active_renderers_.begin();
- while (iter != active_renderers_.end()) {
- StatsMap::iterator elmt = stats_.find(*iter);
- DCHECK(elmt != stats_.end());
- TimeDelta idle = Time::Now() - elmt->second.access;
- if (idle >= TimeDelta::FromMinutes(kRendererInactiveThresholdMinutes)) {
- // Moved to inactive status. This invalidates our iterator.
- inactive_renderers_.insert(*iter);
- active_renderers_.erase(*iter);
- iter = active_renderers_.begin();
- continue;
- }
- ++iter;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698