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

Unified Diff: net/disk_cache/memory/mem_backend_impl.cc

Issue 1715833002: Reland: Refactor and shorten in-memory cache. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix typo in comment Created 4 years, 10 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: net/disk_cache/memory/mem_backend_impl.cc
diff --git a/net/disk_cache/memory/mem_backend_impl.cc b/net/disk_cache/memory/mem_backend_impl.cc
index 5b37ca92bfc75dae4bd92c14f9a0a3ad78707555..028c022f035a16c0622b6bcd57fb08376b76bb40 100644
--- a/net/disk_cache/memory/mem_backend_impl.cc
+++ b/net/disk_cache/memory/mem_backend_impl.cc
@@ -4,6 +4,8 @@
#include "net/disk_cache/memory/mem_backend_impl.h"
+#include <algorithm>
+#include <functional>
#include <utility>
#include "base/logging.h"
@@ -14,36 +16,39 @@
using base::Time;
+namespace disk_cache {
+
namespace {
const int kDefaultInMemoryCacheSize = 10 * 1024 * 1024;
-const int kCleanUpMargin = 1024 * 1024;
-
-int LowWaterAdjust(int high_water) {
- if (high_water < kCleanUpMargin)
- return 0;
-
- return high_water - kCleanUpMargin;
+const int kDefaultEvictionSize = kDefaultInMemoryCacheSize / 10;
+
+bool CheckLRUListOrder(const base::LinkedList<MemEntryImpl>& lru_list) {
+ // TODO(gavinp): Check MemBackendImpl::current_size_ here as well.
+ base::Time previous_last_use_time;
+ for (base::LinkNode<MemEntryImpl>* node = lru_list.head();
+ node != lru_list.end(); node = node->next()) {
+ if (node->value()->GetLastUsed() < previous_last_use_time)
+ return false;
+ previous_last_use_time = node->value()->GetLastUsed();
+ }
+ return true;
}
} // namespace
-namespace disk_cache {
-
MemBackendImpl::MemBackendImpl(net::NetLog* net_log)
: max_size_(0), current_size_(0), net_log_(net_log), weak_factory_(this) {
}
MemBackendImpl::~MemBackendImpl() {
- EntryMap::iterator it = entries_.begin();
- while (it != entries_.end()) {
- it->second->Doom();
- it = entries_.begin();
- }
+ DCHECK(CheckLRUListOrder(lru_list_));
+ while (!entries_.empty())
+ entries_.begin()->second->Doom();
DCHECK(!current_size_);
}
-// Static.
+// static
scoped_ptr<Backend> MemBackendImpl::CreateBackend(int max_bytes,
net::NetLog* net_log) {
scoped_ptr<MemBackendImpl> cache(new MemBackendImpl(net_log));
@@ -67,7 +72,7 @@ bool MemBackendImpl::Init() {
}
// We want to use up to 2% of the computer's memory, with a limit of 50 MB,
- // reached on systemd with more than 2.5 GB of RAM.
+ // reached on system with more than 2.5 GB of RAM.
total_memory = total_memory * 2 / 100;
if (total_memory > kDefaultInMemoryCacheSize * 5)
max_size_ = kDefaultInMemoryCacheSize * 5;
@@ -91,41 +96,33 @@ bool MemBackendImpl::SetMaxSize(int max_bytes) {
return true;
}
-void MemBackendImpl::InternalDoomEntry(MemEntryImpl* entry) {
- // Only parent entries can be passed into this method.
- DCHECK(entry->type() == MemEntryImpl::kParentEntry);
-
- rankings_.Remove(entry);
- EntryMap::iterator it = entries_.find(entry->GetKey());
- if (it != entries_.end())
- entries_.erase(it);
- else
- NOTREACHED();
-
- entry->InternalDoom();
-}
-
-void MemBackendImpl::UpdateRank(MemEntryImpl* node) {
- rankings_.UpdateRank(node);
+int MemBackendImpl::MaxFileSize() const {
+ return max_size_ / 8;
}
-void MemBackendImpl::ModifyStorageSize(int32_t old_size, int32_t new_size) {
- if (old_size >= new_size)
- SubstractStorageSize(old_size - new_size);
- else
- AddStorageSize(new_size - old_size);
+void MemBackendImpl::OnEntryInserted(MemEntryImpl* entry) {
+ lru_list_.Append(entry);
}
-int MemBackendImpl::MaxFileSize() const {
- return max_size_ / 8;
+void MemBackendImpl::OnEntryUpdated(MemEntryImpl* entry) {
+ DCHECK(CheckLRUListOrder(lru_list_));
+ // LinkedList<>::RemoveFromList() removes |entry| from |lru_list_|.
+ entry->RemoveFromList();
+ lru_list_.Append(entry);
}
-void MemBackendImpl::InsertIntoRankingList(MemEntryImpl* entry) {
- rankings_.Insert(entry);
+void MemBackendImpl::OnEntryDoomed(MemEntryImpl* entry) {
+ DCHECK(CheckLRUListOrder(lru_list_));
+ if (entry->type() == MemEntryImpl::PARENT_ENTRY)
+ entries_.erase(entry->key());
+ // LinkedList<>::RemoveFromList() removes |entry| from |lru_list_|.
+ entry->RemoveFromList();
}
-void MemBackendImpl::RemoveFromRankingList(MemEntryImpl* entry) {
- rankings_.Remove(entry);
+void MemBackendImpl::ModifyStorageSize(int32_t delta) {
+ current_size_ += delta;
+ if (delta > 0)
+ EvictIfNeeded();
}
net::CacheType MemBackendImpl::GetCacheType() const {
@@ -136,52 +133,71 @@ int32_t MemBackendImpl::GetEntryCount() const {
return static_cast<int32_t>(entries_.size());
}
-int MemBackendImpl::OpenEntry(const std::string& key, Entry** entry,
+int MemBackendImpl::OpenEntry(const std::string& key,
+ Entry** entry,
const CompletionCallback& callback) {
- if (OpenEntry(key, entry))
- return net::OK;
+ EntryMap::iterator it = entries_.find(key);
+ if (it == entries_.end())
+ return net::ERR_FAILED;
- return net::ERR_FAILED;
+ it->second->Open();
+
+ *entry = it->second;
+ return net::OK;
}
-int MemBackendImpl::CreateEntry(const std::string& key, Entry** entry,
+int MemBackendImpl::CreateEntry(const std::string& key,
+ Entry** entry,
const CompletionCallback& callback) {
- if (CreateEntry(key, entry))
- return net::OK;
+ std::pair<EntryMap::iterator, bool> create_result =
+ entries_.insert(EntryMap::value_type(key, nullptr));
+ const bool did_insert = create_result.second;
+ if (!did_insert)
+ return net::ERR_FAILED;
- return net::ERR_FAILED;
+ MemEntryImpl* cache_entry = new MemEntryImpl(this, key, net_log_);
+ create_result.first->second = cache_entry;
+ *entry = cache_entry;
+ return net::OK;
}
int MemBackendImpl::DoomEntry(const std::string& key,
const CompletionCallback& callback) {
- if (DoomEntry(key))
- return net::OK;
+ EntryMap::iterator it = entries_.find(key);
+ if (it == entries_.end())
+ return net::ERR_FAILED;
- return net::ERR_FAILED;
+ it->second->Doom();
+ return net::OK;
}
int MemBackendImpl::DoomAllEntries(const CompletionCallback& callback) {
- if (DoomAllEntries())
- return net::OK;
-
- return net::ERR_FAILED;
+ return DoomEntriesBetween(Time(), Time(), callback);
}
-int MemBackendImpl::DoomEntriesBetween(const base::Time initial_time,
- const base::Time end_time,
+int MemBackendImpl::DoomEntriesBetween(Time initial_time,
+ Time end_time,
const CompletionCallback& callback) {
- if (DoomEntriesBetween(initial_time, end_time))
- return net::OK;
+ if (end_time.is_null())
+ end_time = Time::Max();
+
+ DCHECK_GE(end_time, initial_time);
+
+ base::LinkNode<MemEntryImpl>* node = lru_list_.head();
+ while (node != lru_list_.end() && node->value()->GetLastUsed() < initial_time)
+ node = node->next();
+ while (node != lru_list_.end() && node->value()->GetLastUsed() < end_time) {
+ MemEntryImpl* to_doom = node->value();
+ node = node->next();
+ to_doom->Doom();
+ }
- return net::ERR_FAILED;
+ return net::OK;
}
-int MemBackendImpl::DoomEntriesSince(const base::Time initial_time,
+int MemBackendImpl::DoomEntriesSince(Time initial_time,
const CompletionCallback& callback) {
- if (DoomEntriesSince(initial_time))
- return net::OK;
-
- return net::ERR_FAILED;
+ return DoomEntriesBetween(initial_time, Time::Max(), callback);
}
int MemBackendImpl::CalculateSizeOfAllEntries(
@@ -189,35 +205,41 @@ int MemBackendImpl::CalculateSizeOfAllEntries(
return current_size_;
}
-class MemBackendImpl::MemIterator : public Backend::Iterator {
+class MemBackendImpl::MemIterator final : public Backend::Iterator {
public:
explicit MemIterator(base::WeakPtr<MemBackendImpl> backend)
- : backend_(backend), current_(NULL) {
- }
+ : backend_(backend), current_(nullptr) {}
int OpenNextEntry(Entry** next_entry,
const CompletionCallback& callback) override {
if (!backend_)
return net::ERR_FAILED;
- MemEntryImpl* node = backend_->rankings_.GetNext(current_);
+ // Iterate using |lru_list_|, from most recently used to least recently
+ // used, for compatibility with the unit tests that assume this behaviour.
+ // Consider the last element if we are beginning an iteration, otherwise
+ // progressively move earlier in the LRU list.
+ current_ = current_ ? current_->previous() : backend_->lru_list_.tail();
+
// We should never return a child entry so iterate until we hit a parent
// entry.
- while (node && node->type() != MemEntryImpl::kParentEntry)
- node = backend_->rankings_.GetNext(node);
- *next_entry = node;
- current_ = node;
-
- if (node) {
- node->Open();
- return net::OK;
+ while (current_ != backend_->lru_list_.end() &&
+ current_->value()->type() != MemEntryImpl::PARENT_ENTRY) {
+ current_ = current_->previous();
}
- return net::ERR_FAILED;
+ if (current_ == backend_->lru_list_.end()) {
+ *next_entry = nullptr;
+ return net::ERR_FAILED;
+ }
+
+ current_->value()->Open();
+ *next_entry = current_->value();
+ return net::OK;
}
private:
base::WeakPtr<MemBackendImpl> backend_;
- MemEntryImpl* current_;
+ base::LinkNode<MemEntryImpl>* current_;
};
scoped_ptr<Backend::Iterator> MemBackendImpl::CreateIterator() {
@@ -227,127 +249,23 @@ scoped_ptr<Backend::Iterator> MemBackendImpl::CreateIterator() {
void MemBackendImpl::OnExternalCacheHit(const std::string& key) {
EntryMap::iterator it = entries_.find(key);
- if (it != entries_.end()) {
- UpdateRank(it->second);
- }
-}
-
-bool MemBackendImpl::OpenEntry(const std::string& key, Entry** entry) {
- EntryMap::iterator it = entries_.find(key);
- if (it == entries_.end())
- return false;
-
- it->second->Open();
-
- *entry = it->second;
- return true;
-}
-
-bool MemBackendImpl::CreateEntry(const std::string& key, Entry** entry) {
- EntryMap::iterator it = entries_.find(key);
if (it != entries_.end())
- return false;
-
- MemEntryImpl* cache_entry = new MemEntryImpl(this);
- if (!cache_entry->CreateEntry(key, net_log_)) {
- delete entry;
- return false;
- }
-
- rankings_.Insert(cache_entry);
- entries_[key] = cache_entry;
-
- *entry = cache_entry;
- return true;
+ it->second->UpdateStateOnUse(MemEntryImpl::ENTRY_WAS_NOT_MODIFIED);
}
-bool MemBackendImpl::DoomEntry(const std::string& key) {
- Entry* entry;
- if (!OpenEntry(key, &entry))
- return false;
-
- entry->Doom();
- entry->Close();
- return true;
-}
-
-bool MemBackendImpl::DoomAllEntries() {
- TrimCache(true);
- return true;
-}
-
-bool MemBackendImpl::DoomEntriesBetween(const Time initial_time,
- const Time end_time) {
- if (end_time.is_null())
- return DoomEntriesSince(initial_time);
-
- DCHECK(end_time >= initial_time);
-
- MemEntryImpl* node = rankings_.GetNext(NULL);
- // Last valid entry before |node|.
- // Note, that entries after |node| may become invalid during |node| doom in
- // case when they are child entries of it. It is guaranteed that
- // parent node will go prior to it childs in ranking list (see
- // InternalReadSparseData and InternalWriteSparseData).
- MemEntryImpl* last_valid = NULL;
-
- // rankings_ is ordered by last used, this will descend through the cache
- // and start dooming items before the end_time, and will stop once it reaches
- // an item used before the initial time.
- while (node) {
- if (node->GetLastUsed() < initial_time)
- break;
-
- if (node->GetLastUsed() < end_time)
- node->Doom();
- else
- last_valid = node;
- node = rankings_.GetNext(last_valid);
- }
-
- return true;
-}
-
-bool MemBackendImpl::DoomEntriesSince(const Time initial_time) {
- for (;;) {
- // Get the entry in the front.
- Entry* entry = rankings_.GetNext(NULL);
-
- // Break the loop when there are no more entries or the entry is too old.
- if (!entry || entry->GetLastUsed() < initial_time)
- return true;
- entry->Doom();
- }
-}
-
-void MemBackendImpl::TrimCache(bool empty) {
- MemEntryImpl* next = rankings_.GetPrev(NULL);
- if (!next)
+void MemBackendImpl::EvictIfNeeded() {
+ if (current_size_ <= max_size_)
return;
- int target_size = empty ? 0 : LowWaterAdjust(max_size_);
- while (current_size_ > target_size && next) {
- MemEntryImpl* node = next;
- next = rankings_.GetPrev(next);
- if (!node->InUse() || empty) {
- node->Doom();
- }
- }
-
- return;
-}
-
-void MemBackendImpl::AddStorageSize(int32_t bytes) {
- current_size_ += bytes;
- DCHECK_GE(current_size_, 0);
+ int target_size = std::max(0, max_size_ - kDefaultEvictionSize);
- if (current_size_ > max_size_)
- TrimCache(false);
-}
-
-void MemBackendImpl::SubstractStorageSize(int32_t bytes) {
- current_size_ -= bytes;
- DCHECK_GE(current_size_, 0);
+ base::LinkNode<MemEntryImpl>* entry = lru_list_.head();
+ while (current_size_ > target_size && entry != lru_list_.end()) {
+ MemEntryImpl* to_doom = entry->value();
+ entry = entry->next();
+ if (!to_doom->InUse())
+ to_doom->Doom();
+ }
}
} // namespace disk_cache

Powered by Google App Engine
This is Rietveld 408576698