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

Side by Side Diff: net/disk_cache/eviction.cc

Issue 6967006: Disk cache: Make sure the list of unused entries is not (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Fix stupid gcc warning Created 9 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 | Annotate | Revision Log
« net/disk_cache/eviction.h ('K') | « net/disk_cache/eviction.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // The eviction policy is a very simple pure LRU, so the elements at the end of 5 // The eviction policy is a very simple pure LRU, so the elements at the end of
6 // the list are evicted until kCleanUpMargin free space is available. There is 6 // the list are evicted until kCleanUpMargin free space is available. There is
7 // only one list in use (Rankings::NO_USE), and elements are sent to the front 7 // only one list in use (Rankings::NO_USE), and elements are sent to the front
8 // of the list whenever they are accessed. 8 // of the list whenever they are accessed.
9 9
10 // The new (in-development) eviction policy adds re-use as a factor to evict 10 // The new (in-development) eviction policy adds re-use as a factor to evict
11 // an entry. The story so far: 11 // an entry. The story so far:
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 if (new_eviction_) 109 if (new_eviction_)
110 return TrimCacheV2(empty); 110 return TrimCacheV2(empty);
111 111
112 Trace("*** Trim Cache ***"); 112 Trace("*** Trim Cache ***");
113 trimming_ = true; 113 trimming_ = true;
114 TimeTicks start = TimeTicks::Now(); 114 TimeTicks start = TimeTicks::Now();
115 Rankings::ScopedRankingsBlock node(rankings_); 115 Rankings::ScopedRankingsBlock node(rankings_);
116 Rankings::ScopedRankingsBlock next(rankings_, 116 Rankings::ScopedRankingsBlock next(rankings_,
117 rankings_->GetPrev(node.get(), Rankings::NO_USE)); 117 rankings_->GetPrev(node.get(), Rankings::NO_USE));
118 int target_size = empty ? 0 : max_size_; 118 int target_size = empty ? 0 : max_size_;
119 while (header_->num_bytes > target_size && next.get()) { 119 while ((header_->num_bytes > target_size && next.get()) || test_mode_) {
120 // The iterator could be invalidated within EvictEntry(). 120 // The iterator could be invalidated within EvictEntry().
121 if (!next->HasData()) 121 if (!next->HasData())
122 break; 122 break;
123 node.reset(next.release()); 123 node.reset(next.release());
124 next.reset(rankings_->GetPrev(node.get(), Rankings::NO_USE)); 124 next.reset(rankings_->GetPrev(node.get(), Rankings::NO_USE));
125 if (node->Data()->dirty != backend_->GetCurrentEntryId() || empty) { 125 if (node->Data()->dirty != backend_->GetCurrentEntryId() || empty) {
126 // This entry is not being used by anybody. 126 // This entry is not being used by anybody.
127 // Do NOT use node as an iterator after this point. 127 // Do NOT use node as an iterator after this point.
128 rankings_->TrackRankingsBlock(node.get(), false); 128 rankings_->TrackRankingsBlock(node.get(), false);
129 if (!EvictEntry(node.get(), empty) && !test_mode_) 129 if (!EvictEntry(node.get(), empty) && !test_mode_)
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 if (done) 297 if (done)
298 continue; 298 continue;
299 next[i].reset(rankings_->GetPrev(NULL, static_cast<Rankings::List>(i))); 299 next[i].reset(rankings_->GetPrev(NULL, static_cast<Rankings::List>(i)));
300 if (!empty && NodeIsOldEnough(next[i].get(), i)) { 300 if (!empty && NodeIsOldEnough(next[i].get(), i)) {
301 list = static_cast<Rankings::List>(i); 301 list = static_cast<Rankings::List>(i);
302 done = true; 302 done = true;
303 } 303 }
304 } 304 }
305 305
306 // If we are not meeting the time targets lets move on to list length. 306 // If we are not meeting the time targets lets move on to list length.
307 if (!empty && Rankings::LAST_ELEMENT == list) { 307 if (!empty && Rankings::LAST_ELEMENT == list)
308 list = SelectListByLenght(); 308 list = SelectListByLenght(next);
309 // Make sure that frequently used items are kept for a minimum time; we know
310 // that this entry is not older than its current target, but it must be at
311 // least older than the target for list 0 (kTargetTime).
312 if ((Rankings::HIGH_USE == list || Rankings::LOW_USE == list) &&
313 !NodeIsOldEnough(next[list].get(), 0))
314 list = 0;
315 }
316 309
317 if (empty) 310 if (empty)
318 list = 0; 311 list = 0;
319 312
320 Rankings::ScopedRankingsBlock node(rankings_); 313 Rankings::ScopedRankingsBlock node(rankings_);
321 314
322 int target_size = empty ? 0 : max_size_; 315 int target_size = empty ? 0 : max_size_;
323 for (; list < kListsToSearch; list++) { 316 for (; list < kListsToSearch; list++) {
324 while (header_->num_bytes > target_size && next[list].get()) { 317 while ((header_->num_bytes > target_size && next[list].get()) ||
318 test_mode_) {
325 // The iterator could be invalidated within EvictEntry(). 319 // The iterator could be invalidated within EvictEntry().
326 if (!next[list]->HasData()) 320 if (!next[list]->HasData())
327 break; 321 break;
328 node.reset(next[list].release()); 322 node.reset(next[list].release());
329 next[list].reset(rankings_->GetPrev(node.get(), 323 next[list].reset(rankings_->GetPrev(node.get(),
330 static_cast<Rankings::List>(list))); 324 static_cast<Rankings::List>(list)));
331 if (node->Data()->dirty != backend_->GetCurrentEntryId() || empty) { 325 if (node->Data()->dirty != backend_->GetCurrentEntryId() || empty) {
332 // This entry is not being used by anybody. 326 // This entry is not being used by anybody.
333 // Do NOT use node as an iterator after this point. 327 // Do NOT use node as an iterator after this point.
334 rankings_->TrackRankingsBlock(node.get(), false); 328 rankings_->TrackRankingsBlock(node.get(), false);
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 return false; 501 return false;
508 502
509 // If possible, we want to keep entries on each list at least kTargetTime 503 // If possible, we want to keep entries on each list at least kTargetTime
510 // hours. Each successive list on the enumeration has 2x the target time of 504 // hours. Each successive list on the enumeration has 2x the target time of
511 // the previous list. 505 // the previous list.
512 Time used = Time::FromInternalValue(node->Data()->last_used); 506 Time used = Time::FromInternalValue(node->Data()->last_used);
513 int multiplier = 1 << list; 507 int multiplier = 1 << list;
514 return (Time::Now() - used).InHours() > kTargetTime * multiplier; 508 return (Time::Now() - used).InHours() > kTargetTime * multiplier;
515 } 509 }
516 510
517 int Eviction::SelectListByLenght() { 511 int Eviction::SelectListByLenght(Rankings::ScopedRankingsBlock* next) {
518 int data_entries = header_->num_entries - 512 int data_entries = header_->num_entries -
519 header_->lru.sizes[Rankings::DELETED]; 513 header_->lru.sizes[Rankings::DELETED];
520 // Start by having each list to be roughly the same size. 514 // Start by having each list to be roughly the same size.
521 if (header_->lru.sizes[0] > data_entries / 3) 515 if (header_->lru.sizes[0] > data_entries / 3)
522 return 0; 516 return 0;
523 if (header_->lru.sizes[1] > data_entries / 3) 517
524 return 1; 518 int list = (header_->lru.sizes[1] > data_entries / 3) ? 1 : 2;
525 return 2; 519
520 // Make sure that frequently used items are kept for a minimum time; we know
521 // that this entry is not older than its current target, but it must be at
522 // least older than the target for list 0 (kTargetTime), as long as we don't
523 // exhaust list 0.
524 if (!NodeIsOldEnough(next[list].get(), 0) &&
525 header_->lru.sizes[0] > data_entries / 10)
526 list = 0;
527
528 return list;
526 } 529 }
527 530
528 void Eviction::ReportListStats() { 531 void Eviction::ReportListStats() {
529 if (!new_eviction_) 532 if (!new_eviction_)
530 return; 533 return;
531 534
532 Rankings::ScopedRankingsBlock last1(rankings_, 535 Rankings::ScopedRankingsBlock last1(rankings_,
533 rankings_->GetPrev(NULL, Rankings::NO_USE)); 536 rankings_->GetPrev(NULL, Rankings::NO_USE));
534 Rankings::ScopedRankingsBlock last2(rankings_, 537 Rankings::ScopedRankingsBlock last2(rankings_,
535 rankings_->GetPrev(NULL, Rankings::LOW_USE)); 538 rankings_->GetPrev(NULL, Rankings::LOW_USE));
(...skipping 10 matching lines...) Expand all
546 Time::FromInternalValue(last2.get()->Data()->last_used)); 549 Time::FromInternalValue(last2.get()->Data()->last_used));
547 if (last3.get()) 550 if (last3.get())
548 CACHE_UMA(AGE, "HighUseAge", 0, 551 CACHE_UMA(AGE, "HighUseAge", 0,
549 Time::FromInternalValue(last3.get()->Data()->last_used)); 552 Time::FromInternalValue(last3.get()->Data()->last_used));
550 if (last4.get()) 553 if (last4.get())
551 CACHE_UMA(AGE, "DeletedAge", 0, 554 CACHE_UMA(AGE, "DeletedAge", 0,
552 Time::FromInternalValue(last4.get()->Data()->last_used)); 555 Time::FromInternalValue(last4.get()->Data()->last_used));
553 } 556 }
554 557
555 } // namespace disk_cache 558 } // namespace disk_cache
OLDNEW
« net/disk_cache/eviction.h ('K') | « net/disk_cache/eviction.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698