summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/memory_details.cc5
-rw-r--r--chrome/browser/renderer_host/backing_store_manager.cc72
2 files changed, 50 insertions, 27 deletions
diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc
index df81bc3..124d33c 100644
--- a/chrome/browser/memory_details.cc
+++ b/chrome/browser/memory_details.cc
@@ -10,6 +10,7 @@
#include "base/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/renderer_host/backing_store_manager.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/tab_contents/navigation_entry.h"
#include "chrome/browser/tab_contents/tab_contents.h"
@@ -276,7 +277,7 @@ void MemoryDetails::CollectChildInfoOnUIThread() {
void MemoryDetails::UpdateHistograms() {
// Reports a set of memory metrics to UMA.
- // Memory is measured in units of 10KB.
+ // Memory is measured in KB.
ProcessData browser = process_data_[CHROME_BROWSER];
size_t aggregate_memory = 0;
@@ -302,6 +303,8 @@ void MemoryDetails::UpdateHistograms() {
break;
}
}
+ UMA_HISTOGRAM_MEMORY_KB("Memory.BackingStore",
+ BackingStoreManager::MemorySize() / 1024);
UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount",
static_cast<int>(browser.processes.size()));
diff --git a/chrome/browser/renderer_host/backing_store_manager.cc b/chrome/browser/renderer_host/backing_store_manager.cc
index 449f0d4..fd9dafe 100644
--- a/chrome/browser/renderer_host/backing_store_manager.cc
+++ b/chrome/browser/renderer_host/backing_store_manager.cc
@@ -22,31 +22,34 @@ typedef OwningMRUCache<RenderWidgetHost*, BackingStore*> BackingStoreCache;
static BackingStoreCache* large_cache = NULL;
static BackingStoreCache* small_cache = NULL;
-// Threshold is based on a large-monitor width toolstrip.
+// Threshold is based on a single large-monitor-width toolstrip.
+// (32bpp, 32 pixels high, 1920 pixels wide)
// TODO(erikkay) 32bpp assumption isn't great.
const size_t kSmallThreshold = 4 * 32 * 1920;
-// Previously, the backing store cache was based on a set number of backing
-// stores, regardless of their size. The numbers were chosen based on a user
-// with a maximized browser on a large monitor. Now that the cache is based on
-// total memory size of the backing stores, we'll keep an approximation of the
-// numbers from the previous algorithm by choosing a large monitor backing store
-// size as our multiplier.
+// Pick a large monitor size to use as a multiplier. This is multiplied by the
+// max number of large backing stores (usually tabs) to pick a ceiling on the
+// max memory to use.
// TODO(erikkay) Perhaps we should actually use monitor size? That way we
// could make an assertion like "worse case, there are two tabs in the cache".
// However, the small_cache might mess up these calculations a bit.
// TODO(erikkay) 32bpp assumption isn't great.
const size_t kMemoryMultiplier = 4 * 1920 * 1200; // ~9MB
-static size_t GetBackingStoreCacheMemorySize() {
+// The maximum number of large BackingStoreCache objects (tabs) to use.
+// Use a minimum of 2, and add one for each 256MB of physical memory you have.
+// Cap at 5, the thinking being that even if you have a gigantic amount of
+// RAM, there's a limit to how much caching helps beyond a certain number
+// of tabs.
+static size_t MaxNumberOfBackingStores() {
+ return std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256));
+}
+
+// The maximum about of memory to use for all BackingStoreCache object combined.
+// We use this
+static size_t MaxBackingStoreMemory() {
// Compute in terms of the number of large monitor's worth of backing-store.
- // Use a minimum of 2, and add one for each 256MB of physical memory you have.
- // Cap at 5, the thinking being that even if you have a gigantic amount of
- // RAM, there's a limit to how much caching helps beyond a certain number
- // of tabs.
- size_t mem_tier = std::min(5,
- 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256));
- return mem_tier * kMemoryMultiplier;
+ return MaxNumberOfBackingStores() * kMemoryMultiplier;
}
// Expires the given |backing_store| from |cache|.
@@ -61,6 +64,18 @@ void ExpireBackingStoreAt(BackingStoreCache* cache,
cache->Erase(backing_store);
}
+size_t ExpireLastBackingStore(BackingStoreCache* cache) {
+ if (cache->size() < 1)
+ return 0;
+
+ // Crazy C++ alert: rbegin.base() is a forward iterator pointing to end(),
+ // so we need to do -- to move one back to the actual last item.
+ BackingStoreCache::iterator entry = --cache->rbegin().base();
+ size_t entry_size = entry->second->MemorySize();
+ ExpireBackingStoreAt(cache, entry);
+ return entry_size;
+}
+
void CreateCacheSpace(size_t size) {
// Given a request for |size|, first free from the large cache (until there's
// only one item left) and then do the same from the small cache if we still
@@ -69,11 +84,7 @@ void CreateCacheSpace(size_t size) {
BackingStoreCache* cache =
(large_cache->size() > 1) ? large_cache : small_cache;
while (size > 0 && cache->size() > 1) {
- // Crazy C++ alert: rbegin.base() is a forward iterator pointing to end(),
- // so we need to do -- to move one back to the actual last item.
- BackingStoreCache::iterator entry = --cache->rbegin().base();
- size_t entry_size = entry->second->MemorySize();
- ExpireBackingStoreAt(cache, entry);
+ size_t entry_size = ExpireLastBackingStore(cache);
if (size > entry_size)
size -= entry_size;
else
@@ -98,23 +109,32 @@ BackingStore* CreateBackingStore(RenderWidgetHost* host,
// TODO(erikkay) 32bpp is not always accurate
size_t new_mem = backing_store_size.GetArea() * 4;
size_t current_mem = BackingStoreManager::MemorySize();
- size_t max_mem = GetBackingStoreCacheMemorySize();
+ size_t max_mem = MaxBackingStoreMemory();
DCHECK(new_mem < max_mem);
if (current_mem + new_mem > max_mem) {
// Need to remove old backing stores to make room for the new one. We
// don't want to do this when the backing store is being replace by a new
// one for the same tab, but this case won't get called then: we'll have
- // removed the onld one in the RemoveBackingStore above, and the cache
+ // removed the old one in the RemoveBackingStore above, and the cache
// won't be over-sized.
CreateCacheSpace((current_mem + new_mem) - max_mem);
}
DCHECK((BackingStoreManager::MemorySize() + new_mem) < max_mem);
+ BackingStoreCache* cache;
+ if (new_mem > kSmallThreshold) {
+ // Limit the number of large backing stores (tabs) to the memory tier number
+ // (between 2-5). While we allow a larger amount of memory for people who
+ // have large windows, this means that those who use small browser windows
+ // won't ever cache more than 5 tabs, so they pay a smaller memory cost.
+ if (large_cache->size() >= MaxNumberOfBackingStores())
+ ExpireLastBackingStore(large_cache);
+ cache = large_cache;
+ } else {
+ cache = small_cache;
+ }
BackingStore* backing_store = host->AllocBackingStore(backing_store_size);
- if (new_mem > kSmallThreshold)
- large_cache->Put(host, backing_store);
- else
- small_cache->Put(host, backing_store);
+ cache->Put(host, backing_store);
return backing_store;
}