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

Side by Side Diff: net/disk_cache/simple/simple_index.cc

Issue 14746019: net/disk_cache/simple: Reduce size of EntrySet nodes. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: remove comment Created 7 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "net/disk_cache/simple/simple_index.h" 5 #include "net/disk_cache/simple/simple_index.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 if (!file_util::GetFileInfo(path, &file_info)) 99 if (!file_util::GetFileInfo(path, &file_info))
100 return false; 100 return false;
101 *out_mtime = file_info.last_modified; 101 *out_mtime = file_info.last_modified;
102 return true; 102 return true;
103 } 103 }
104 104
105 } // namespace 105 } // namespace
106 106
107 namespace disk_cache { 107 namespace disk_cache {
108 108
109 EntryMetadata::EntryMetadata() : hash_key_(0), 109 EntryMetadata::EntryMetadata() : last_used_time_(0), entry_size_(0) {}
110 last_used_time_(0),
111 entry_size_(0) {
112 }
113 110
114 EntryMetadata::EntryMetadata(uint64 hash_key, 111 EntryMetadata::EntryMetadata(base::Time last_used_time, uint64 entry_size)
115 base::Time last_used_time, 112 : last_used_time_(last_used_time.ToInternalValue()),
116 uint64 entry_size) : 113 entry_size_(entry_size) {}
117 hash_key_(hash_key),
118 last_used_time_(last_used_time.ToInternalValue()),
119 entry_size_(entry_size) {
120 }
121 114
122 base::Time EntryMetadata::GetLastUsedTime() const { 115 base::Time EntryMetadata::GetLastUsedTime() const {
123 return base::Time::FromInternalValue(last_used_time_); 116 return base::Time::FromInternalValue(last_used_time_);
124 } 117 }
125 118
126 void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) { 119 void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) {
127 last_used_time_ = last_used_time.ToInternalValue(); 120 last_used_time_ = last_used_time.ToInternalValue();
128 } 121 }
129 122
130 void EntryMetadata::Serialize(Pickle* pickle) const { 123 void EntryMetadata::Serialize(Pickle* pickle) const {
131 DCHECK(pickle); 124 DCHECK(pickle);
132 COMPILE_ASSERT(sizeof(EntryMetadata) == 125 COMPILE_ASSERT(sizeof(EntryMetadata) == (sizeof(int64) + sizeof(uint64)),
133 (sizeof(uint64) + sizeof(int64) + sizeof(uint64)), 126 EntryMetadata_has_two_member_variables);
134 EntryMetadata_has_three_member_variables);
135 pickle->WriteUInt64(hash_key_);
136 pickle->WriteInt64(last_used_time_); 127 pickle->WriteInt64(last_used_time_);
137 pickle->WriteUInt64(entry_size_); 128 pickle->WriteUInt64(entry_size_);
138 } 129 }
139 130
140 bool EntryMetadata::Deserialize(PickleIterator* it) { 131 bool EntryMetadata::Deserialize(PickleIterator* it) {
141 DCHECK(it); 132 DCHECK(it);
142 return it->ReadUInt64(&hash_key_) && 133 return it->ReadInt64(&last_used_time_) && it->ReadUInt64(&entry_size_);
143 it->ReadInt64(&last_used_time_) &&
144 it->ReadUInt64(&entry_size_);
145 } 134 }
146 135
147 void EntryMetadata::MergeWith(const EntryMetadata& from) { 136 void EntryMetadata::MergeWith(const EntryMetadata& from) {
148 DCHECK_EQ(hash_key_, from.hash_key_);
149 if (last_used_time_ == 0) 137 if (last_used_time_ == 0)
150 last_used_time_ = from.last_used_time_; 138 last_used_time_ = from.last_used_time_;
151 if (entry_size_ == 0) 139 if (entry_size_ == 0)
152 entry_size_ = from.entry_size_; 140 entry_size_ = from.entry_size_;
153 } 141 }
154 142
155 SimpleIndex::SimpleIndex(base::SingleThreadTaskRunner* cache_thread, 143 SimpleIndex::SimpleIndex(base::SingleThreadTaskRunner* cache_thread,
156 base::SingleThreadTaskRunner* io_thread, 144 base::SingleThreadTaskRunner* io_thread,
157 const base::FilePath& path) 145 const base::FilePath& path)
158 : cache_size_(0), 146 : cache_size_(0),
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 208
221 scoped_ptr<std::vector<uint64> > SimpleIndex::RemoveEntriesBetween( 209 scoped_ptr<std::vector<uint64> > SimpleIndex::RemoveEntriesBetween(
222 const base::Time initial_time, const base::Time end_time) { 210 const base::Time initial_time, const base::Time end_time) {
223 DCHECK_EQ(true, initialized_); 211 DCHECK_EQ(true, initialized_);
224 const base::Time extended_end_time = 212 const base::Time extended_end_time =
225 end_time.is_null() ? base::Time::Max() : end_time; 213 end_time.is_null() ? base::Time::Max() : end_time;
226 DCHECK(extended_end_time >= initial_time); 214 DCHECK(extended_end_time >= initial_time);
227 scoped_ptr<std::vector<uint64> > ret_hashes(new std::vector<uint64>()); 215 scoped_ptr<std::vector<uint64> > ret_hashes(new std::vector<uint64>());
228 for (EntrySet::iterator it = entries_set_.begin(), end = entries_set_.end(); 216 for (EntrySet::iterator it = entries_set_.begin(), end = entries_set_.end();
229 it != end;) { 217 it != end;) {
230 EntryMetadata metadata = it->second; 218 EntryMetadata& metadata = it->second;
231 base::Time entry_time = metadata.GetLastUsedTime(); 219 base::Time entry_time = metadata.GetLastUsedTime();
232 if (initial_time <= entry_time && entry_time < extended_end_time) { 220 if (initial_time <= entry_time && entry_time < extended_end_time) {
233 ret_hashes->push_back(metadata.GetHashKey()); 221 ret_hashes->push_back(it->first);
222 cache_size_ -= metadata.GetEntrySize();
234 entries_set_.erase(it++); 223 entries_set_.erase(it++);
235 cache_size_ -= metadata.GetEntrySize();
236 } else { 224 } else {
237 it++; 225 it++;
238 } 226 }
239 } 227 }
240 return ret_hashes.Pass(); 228 return ret_hashes.Pass();
241 } 229 }
242 230
243 int32 SimpleIndex::GetEntryCount() const { 231 int32 SimpleIndex::GetEntryCount() const {
244 // TODO(pasko): return a meaningful initial estimate before initialized. 232 // TODO(pasko): return a meaningful initial estimate before initialized.
245 return entries_set_.size(); 233 return entries_set_.size();
246 } 234 }
247 235
248 void SimpleIndex::Insert(const std::string& key) { 236 void SimpleIndex::Insert(const std::string& key) {
249 DCHECK(io_thread_checker_.CalledOnValidThread()); 237 DCHECK(io_thread_checker_.CalledOnValidThread());
250 // Upon insert we don't know yet the size of the entry. 238 // Upon insert we don't know yet the size of the entry.
251 // It will be updated later when the SimpleEntryImpl finishes opening or 239 // It will be updated later when the SimpleEntryImpl finishes opening or
252 // creating the new entry, and then UpdateEntrySize will be called. 240 // creating the new entry, and then UpdateEntrySize will be called.
253 const uint64 hash_key = simple_util::GetEntryHashKey(key); 241 const uint64 hash_key = simple_util::GetEntryHashKey(key);
254 InsertInEntrySet(EntryMetadata(hash_key, base::Time::Now(), 0), 242 InsertInEntrySet(
255 &entries_set_); 243 hash_key, EntryMetadata(base::Time::Now(), 0), &entries_set_);
256 if (!initialized_) 244 if (!initialized_)
257 removed_entries_.erase(hash_key); 245 removed_entries_.erase(hash_key);
258 PostponeWritingToDisk(); 246 PostponeWritingToDisk();
259 } 247 }
260 248
261 void SimpleIndex::Remove(const std::string& key) { 249 void SimpleIndex::Remove(const std::string& key) {
262 DCHECK(io_thread_checker_.CalledOnValidThread()); 250 DCHECK(io_thread_checker_.CalledOnValidThread());
263 UpdateEntrySize(key, 0); 251 UpdateEntrySize(key, 0);
264 const uint64 hash_key = simple_util::GetEntryHashKey(key); 252 const uint64 hash_key = simple_util::GetEntryHashKey(key);
265 entries_set_.erase(hash_key); 253 entries_set_.erase(hash_key);
(...skipping 29 matching lines...) Expand all
295 return; 283 return;
296 284
297 // Take all live key hashes from the index and sort them by time. 285 // Take all live key hashes from the index and sort them by time.
298 eviction_in_progress_ = true; 286 eviction_in_progress_ = true;
299 eviction_start_time_ = base::TimeTicks::Now(); 287 eviction_start_time_ = base::TimeTicks::Now();
300 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.CacheSizeOnStart", cache_size_); 288 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.CacheSizeOnStart", cache_size_);
301 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.MaxCacheSizeOnStart", max_size_); 289 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.MaxCacheSizeOnStart", max_size_);
302 scoped_ptr<std::vector<uint64> > entry_hashes(new std::vector<uint64>()); 290 scoped_ptr<std::vector<uint64> > entry_hashes(new std::vector<uint64>());
303 for (EntrySet::const_iterator it = entries_set_.begin(), 291 for (EntrySet::const_iterator it = entries_set_.begin(),
304 end = entries_set_.end(); it != end; ++it) { 292 end = entries_set_.end(); it != end; ++it) {
305 entry_hashes->push_back(it->second.GetHashKey()); 293 entry_hashes->push_back(it->first);
306 } 294 }
307 std::sort(entry_hashes->begin(), entry_hashes->end(), 295 std::sort(entry_hashes->begin(), entry_hashes->end(),
308 CompareHashesForTimestamp(entries_set_)); 296 CompareHashesForTimestamp(entries_set_));
309 297
310 // Remove as many entries from the index to get below |low_watermark_|. 298 // Remove as many entries from the index to get below |low_watermark_|.
311 std::vector<uint64>::iterator it = entry_hashes->begin(); 299 std::vector<uint64>::iterator it = entry_hashes->begin();
312 uint64 evicted_so_far_size = 0; 300 uint64 evicted_so_far_size = 0;
313 while (evicted_so_far_size < cache_size_ - low_watermark_) { 301 while (evicted_so_far_size < cache_size_ - low_watermark_) {
314 DCHECK(it != entry_hashes->end()); 302 DCHECK(it != entry_hashes->end());
315 EntrySet::iterator found_meta = entries_set_.find(*it); 303 EntrySet::iterator found_meta = entries_set_.find(*it);
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 // Ignore the result of eviction. We did our best. 349 // Ignore the result of eviction. We did our best.
362 eviction_in_progress_ = false; 350 eviction_in_progress_ = false;
363 UMA_HISTOGRAM_BOOLEAN("SimpleCache.Eviction.Result", *result == net::OK); 351 UMA_HISTOGRAM_BOOLEAN("SimpleCache.Eviction.Result", *result == net::OK);
364 UMA_HISTOGRAM_TIMES("SimpleCache.Eviction.TimeToDone", 352 UMA_HISTOGRAM_TIMES("SimpleCache.Eviction.TimeToDone",
365 base::TimeTicks::Now() - eviction_start_time_); 353 base::TimeTicks::Now() - eviction_start_time_);
366 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.SizeWhenDone", cache_size_); 354 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.SizeWhenDone", cache_size_);
367 } 355 }
368 356
369 // static 357 // static
370 void SimpleIndex::InsertInEntrySet( 358 void SimpleIndex::InsertInEntrySet(
359 uint64 hash_key,
371 const disk_cache::EntryMetadata& entry_metadata, 360 const disk_cache::EntryMetadata& entry_metadata,
372 EntrySet* entry_set) { 361 EntrySet* entry_set) {
373 DCHECK(entry_set); 362 DCHECK(entry_set);
374 entry_set->insert( 363 entry_set->insert(std::make_pair(hash_key, entry_metadata));
375 std::make_pair(entry_metadata.GetHashKey(), entry_metadata));
376 } 364 }
377 365
378 void SimpleIndex::PostponeWritingToDisk() { 366 void SimpleIndex::PostponeWritingToDisk() {
379 if (!initialized_) 367 if (!initialized_)
380 return; 368 return;
381 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs 369 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs
382 : kWriteToDiskDelayMSecs; 370 : kWriteToDiskDelayMSecs;
383 // If the timer is already active, Start() will just Reset it, postponing it. 371 // If the timer is already active, Start() will just Reset it, postponing it.
384 write_to_disk_timer_.Start( 372 write_to_disk_timer_.Start(
385 FROM_HERE, 373 FROM_HERE,
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 base::Time last_used_time; 493 base::Time last_used_time;
506 #if defined(OS_POSIX) 494 #if defined(OS_POSIX)
507 // For POSIX systems, a last access time is available. However, it's not 495 // For POSIX systems, a last access time is available. However, it's not
508 // guaranteed to be more accurate than mtime. It is no worse though. 496 // guaranteed to be more accurate than mtime. It is no worse though.
509 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); 497 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime);
510 #endif 498 #endif
511 if (last_used_time.is_null()) 499 if (last_used_time.is_null())
512 last_used_time = FileEnumerator::GetLastModifiedTime(find_info); 500 last_used_time = FileEnumerator::GetLastModifiedTime(find_info);
513 501
514 int64 file_size = FileEnumerator::GetFilesize(find_info); 502 int64 file_size = FileEnumerator::GetFilesize(find_info);
515 EntrySet::iterator it = index_file_entries->find(hash_key); 503 std::pair<EntrySet::iterator, bool> ret = index_file_entries->insert(
516 if (it == index_file_entries->end()) { 504 std::make_pair(hash_key, EntryMetadata(last_used_time, file_size)));
517 InsertInEntrySet(EntryMetadata(hash_key, last_used_time, file_size), 505 if (ret.second == false) {
518 index_file_entries.get()); 506 EntryMetadata* current_entry = &ret.first->second;
519 } else { 507 current_entry->SetEntrySize(current_entry->GetEntrySize() + file_size);
520 // Summing up the total size of the entry through all the *_[0-2] files
521 it->second.SetEntrySize(it->second.GetEntrySize() + file_size);
522 } 508 }
523 } 509 }
524 return index_file_entries.Pass(); 510 return index_file_entries.Pass();
525 } 511 }
526 512
527 513
528 // static 514 // static
529 void SimpleIndex::WriteToDiskInternal(const base::FilePath& index_filename, 515 void SimpleIndex::WriteToDiskInternal(const base::FilePath& index_filename,
530 scoped_ptr<Pickle> pickle, 516 scoped_ptr<Pickle> pickle,
531 const base::TimeTicks& start_time, 517 const base::TimeTicks& start_time,
(...skipping 16 matching lines...) Expand all
548 // sets. 534 // sets.
549 for (base::hash_set<uint64>::const_iterator it = 535 for (base::hash_set<uint64>::const_iterator it =
550 removed_entries_.begin(); it != removed_entries_.end(); ++it) { 536 removed_entries_.begin(); it != removed_entries_.end(); ++it) {
551 entries_set_.erase(*it); 537 entries_set_.erase(*it);
552 index_file_entries->erase(*it); 538 index_file_entries->erase(*it);
553 } 539 }
554 540
555 // Recalculate the cache size while merging the two sets. 541 // Recalculate the cache size while merging the two sets.
556 for (EntrySet::const_iterator it = index_file_entries->begin(); 542 for (EntrySet::const_iterator it = index_file_entries->begin();
557 it != index_file_entries->end(); ++it) { 543 it != index_file_entries->end(); ++it) {
558 // If there is already an entry in the current entries_set_, we need to 544 std::pair<EntrySet::iterator, bool> ret = entries_set_.insert(*it);
559 // merge the new data there with the data loaded in the initialization. 545 EntryMetadata& current_entry = ret.first->second;
gavinp 2013/05/17 14:54:17 This is more a comment, and less a request. I woul
560 EntrySet::iterator current_entry = entries_set_.find(it->first); 546 if (ret.second == false) {
561 if (current_entry != entries_set_.end()) {
562 // When Merging, existing valid data in the |current_entry| will prevail. 547 // When Merging, existing valid data in the |current_entry| will prevail.
563 cache_size_ -= current_entry->second.GetEntrySize(); 548 cache_size_ -= current_entry.GetEntrySize();
564 current_entry->second.MergeWith(it->second); 549 current_entry.MergeWith(it->second);
565 cache_size_ += current_entry->second.GetEntrySize();
566 } else {
567 InsertInEntrySet(it->second, &entries_set_);
568 cache_size_ += it->second.GetEntrySize();
569 } 550 }
551 cache_size_ += current_entry.GetEntrySize();
570 } 552 }
571 initialized_ = true; 553 initialized_ = true;
572 removed_entries_.clear(); 554 removed_entries_.clear();
573 555
574 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down 556 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down
575 // much the merge. 557 // much the merge.
576 if (force_index_flush) 558 if (force_index_flush)
577 WriteToDisk(); 559 WriteToDisk();
578 560
579 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters", 561 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters",
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 entries_set_); 608 entries_set_);
627 cache_thread_->PostTask(FROM_HERE, base::Bind( 609 cache_thread_->PostTask(FROM_HERE, base::Bind(
628 &SimpleIndex::WriteToDiskInternal, 610 &SimpleIndex::WriteToDiskInternal,
629 index_filename_, 611 index_filename_,
630 base::Passed(&pickle), 612 base::Passed(&pickle),
631 start, 613 start,
632 app_on_background_)); 614 app_on_background_));
633 } 615 }
634 616
635 } // namespace disk_cache 617 } // namespace disk_cache
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698