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

Side by Side Diff: net/disk_cache/v3/eviction_v3.cc

Issue 14991008: Disk cache: Add base files for implementation of file format version 3. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: rebase Created 7 years, 6 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
« no previous file with comments | « net/disk_cache/v3/eviction_v3.h ('k') | net/disk_cache/v3/sparse_control_v3.h » ('j') | 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) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 } else { 154 } else {
155 CACHE_UMA(AGE_MS, "TotalTrimTimeV1", 0, start); 155 CACHE_UMA(AGE_MS, "TotalTrimTimeV1", 0, start);
156 } 156 }
157 CACHE_UMA(COUNTS, "TrimItemsV1", 0, deleted_entries); 157 CACHE_UMA(COUNTS, "TrimItemsV1", 0, deleted_entries);
158 158
159 trimming_ = false; 159 trimming_ = false;
160 Trace("*** Trim Cache end ***"); 160 Trace("*** Trim Cache end ***");
161 return; 161 return;
162 } 162 }
163 163
164 void Eviction::UpdateRank(EntryImpl* entry, bool modified) { 164 void Eviction::OnOpenEntryV2(EntryImpl* entry) {
165 if (new_eviction_) 165 EntryStore* info = entry->entry()->Data();
166 return UpdateRankV2(entry, modified); 166 DCHECK_EQ(ENTRY_NORMAL, info->state);
167 167
168 rankings_->UpdateRank(entry->rankings(), modified, GetListForEntry(entry)); 168 if (info->reuse_count < kint32max) {
169 info->reuse_count++;
170 entry->entry()->set_modified();
171
172 // We may need to move this to a new list.
173 if (1 == info->reuse_count) {
174 rankings_->Remove(entry->rankings(), Rankings::NO_USE, true);
175 rankings_->Insert(entry->rankings(), false, Rankings::LOW_USE);
176 entry->entry()->Store();
177 } else if (kHighUse == info->reuse_count) {
178 rankings_->Remove(entry->rankings(), Rankings::LOW_USE, true);
179 rankings_->Insert(entry->rankings(), false, Rankings::HIGH_USE);
180 entry->entry()->Store();
181 }
182 }
169 } 183 }
170 184
171 void Eviction::OnOpenEntry(EntryImpl* entry) { 185 void Eviction::OnCreateEntryV2(EntryImpl* entry) {
172 if (new_eviction_) 186 EntryStore* info = entry->entry()->Data();
173 return OnOpenEntryV2(entry); 187 switch (info->state) {
174 } 188 case ENTRY_NORMAL: {
189 DCHECK(!info->reuse_count);
190 DCHECK(!info->refetch_count);
191 break;
192 };
193 case ENTRY_EVICTED: {
194 if (info->refetch_count < kint32max)
195 info->refetch_count++;
175 196
176 void Eviction::OnCreateEntry(EntryImpl* entry) { 197 if (info->refetch_count > kHighUse && info->reuse_count < kHighUse) {
177 if (new_eviction_) 198 info->reuse_count = kHighUse;
178 return OnCreateEntryV2(entry); 199 } else {
200 info->reuse_count++;
201 }
202 info->state = ENTRY_NORMAL;
203 entry->entry()->Store();
204 rankings_->Remove(entry->rankings(), Rankings::DELETED, true);
205 break;
206 };
207 default:
208 NOTREACHED();
209 }
179 210
180 rankings_->Insert(entry->rankings(), true, GetListForEntry(entry)); 211 rankings_->Insert(entry->rankings(), true, GetListForEntryV2(entry));
181 }
182
183 void Eviction::OnDoomEntry(EntryImpl* entry) {
184 if (new_eviction_)
185 return OnDoomEntryV2(entry);
186
187 if (entry->LeaveRankingsBehind())
188 return;
189
190 rankings_->Remove(entry->rankings(), GetListForEntry(entry), true);
191 }
192
193 void Eviction::OnDestroyEntry(EntryImpl* entry) {
194 if (new_eviction_)
195 return OnDestroyEntryV2(entry);
196 } 212 }
197 213
198 void Eviction::SetTestMode() { 214 void Eviction::SetTestMode() {
199 test_mode_ = true; 215 test_mode_ = true;
200 } 216 }
201 217
202 void Eviction::TrimDeletedList(bool empty) { 218 void Eviction::TrimDeletedList(bool empty) {
203 DCHECK(test_mode_ && new_eviction_); 219 DCHECK(test_mode_ && new_eviction_);
204 TrimDeleted(empty); 220 TrimDeleted(empty);
205 } 221 }
206 222
223 // -----------------------------------------------------------------------
224
207 void Eviction::PostDelayedTrim() { 225 void Eviction::PostDelayedTrim() {
208 // Prevent posting multiple tasks. 226 // Prevent posting multiple tasks.
209 if (delay_trim_) 227 if (delay_trim_)
210 return; 228 return;
211 delay_trim_ = true; 229 delay_trim_ = true;
212 trim_delays_++; 230 trim_delays_++;
213 base::MessageLoop::current()->PostDelayedTask( 231 base::MessageLoop::current()->PostDelayedTask(
214 FROM_HERE, 232 FROM_HERE,
215 base::Bind(&Eviction::DelayedTrim, ptr_factory_.GetWeakPtr()), 233 base::Bind(&Eviction::DelayedTrim, ptr_factory_.GetWeakPtr()),
216 base::TimeDelta::FromMilliseconds(1000)); 234 base::TimeDelta::FromMilliseconds(1000));
(...skipping 22 matching lines...) Expand all
239 int index_load = header_->num_entries * 100 / index_size_; 257 int index_load = header_->num_entries * 100 / index_size_;
240 258
241 // If the index is not loaded, the deleted list will tend to double the size 259 // If the index is not loaded, the deleted list will tend to double the size
242 // of the other lists 3 lists (40% of the total). Otherwise, all lists will be 260 // of the other lists 3 lists (40% of the total). Otherwise, all lists will be
243 // about the same size. 261 // about the same size.
244 int max_length = (index_load < 25) ? header_->num_entries * 2 / 5 : 262 int max_length = (index_load < 25) ? header_->num_entries * 2 / 5 :
245 header_->num_entries / 4; 263 header_->num_entries / 4;
246 return (!test_mode_ && header_->lru.sizes[Rankings::DELETED] > max_length); 264 return (!test_mode_ && header_->lru.sizes[Rankings::DELETED] > max_length);
247 } 265 }
248 266
249 void Eviction::ReportTrimTimes(EntryImpl* entry) {
250 if (first_trim_) {
251 first_trim_ = false;
252 if (backend_->ShouldReportAgain()) {
253 CACHE_UMA(AGE, "TrimAge", 0, entry->GetLastUsed());
254 ReportListStats();
255 }
256
257 if (header_->lru.filled)
258 return;
259
260 header_->lru.filled = 1;
261
262 if (header_->create_time) {
263 // This is the first entry that we have to evict, generate some noise.
264 backend_->FirstEviction();
265 } else {
266 // This is an old file, but we may want more reports from this user so
267 // lets save some create_time.
268 Time::Exploded old = {0};
269 old.year = 2009;
270 old.month = 3;
271 old.day_of_month = 1;
272 header_->create_time = Time::FromLocalExploded(old).ToInternalValue();
273 }
274 }
275 }
276
277 Rankings::List Eviction::GetListForEntry(EntryImpl* entry) {
278 return Rankings::NO_USE;
279 }
280
281 bool Eviction::EvictEntry(CacheRankingsBlock* node, bool empty, 267 bool Eviction::EvictEntry(CacheRankingsBlock* node, bool empty,
282 Rankings::List list) { 268 Rankings::List list) {
283 EntryImpl* entry = backend_->GetEnumeratedEntry(node, list); 269 EntryImpl* entry = backend_->GetEnumeratedEntry(node, list);
284 if (!entry) { 270 if (!entry) {
285 Trace("NewEntry failed on Trim 0x%x", node->address().value()); 271 Trace("NewEntry failed on Trim 0x%x", node->address().value());
286 return false; 272 return false;
287 } 273 }
288 274
289 ReportTrimTimes(entry); 275 ReportTrimTimes(entry);
290 if (empty || !new_eviction_) { 276 if (empty || !new_eviction_) {
291 entry->DoomImpl(); 277 entry->DoomImpl();
292 } else { 278 } else {
293 entry->DeleteEntryData(false); 279 entry->DeleteEntryData(false);
294 EntryStore* info = entry->entry()->Data(); 280 EntryStore* info = entry->entry()->Data();
295 DCHECK_EQ(ENTRY_NORMAL, info->state); 281 DCHECK_EQ(ENTRY_NORMAL, info->state);
296 282
297 rankings_->Remove(entry->rankings(), GetListForEntryV2(entry), true); 283 rankings_->Remove(entry->rankings(), GetListForEntryV2(entry), true);
298 info->state = ENTRY_EVICTED; 284 info->state = ENTRY_EVICTED;
299 entry->entry()->Store(); 285 entry->entry()->Store();
300 rankings_->Insert(entry->rankings(), true, Rankings::DELETED); 286 rankings_->Insert(entry->rankings(), true, Rankings::DELETED);
301 } 287 }
302 if (!empty) 288 if (!empty)
303 backend_->OnEvent(Stats::TRIM_ENTRY); 289 backend_->OnEvent(Stats::TRIM_ENTRY);
304 290
305 entry->Release(); 291 entry->Release();
306 292
307 return true; 293 return true;
308 } 294 }
309 295
310 // -----------------------------------------------------------------------
311
312 void Eviction::TrimCacheV2(bool empty) { 296 void Eviction::TrimCacheV2(bool empty) {
313 Trace("*** Trim Cache ***"); 297 Trace("*** Trim Cache ***");
314 trimming_ = true; 298 trimming_ = true;
315 TimeTicks start = TimeTicks::Now(); 299 TimeTicks start = TimeTicks::Now();
316 300
317 const int kListsToSearch = 3; 301 const int kListsToSearch = 3;
318 Rankings::ScopedRankingsBlock next[kListsToSearch]; 302 Rankings::ScopedRankingsBlock next[kListsToSearch];
319 int list = Rankings::LAST_ELEMENT; 303 int list = Rankings::LAST_ELEMENT;
320 304
321 // Get a node from each list. 305 // Get a node from each list.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } else { 370 } else {
387 CACHE_UMA(AGE_MS, "TotalTrimTimeV2", 0, start); 371 CACHE_UMA(AGE_MS, "TotalTrimTimeV2", 0, start);
388 } 372 }
389 CACHE_UMA(COUNTS, "TrimItemsV2", 0, deleted_entries); 373 CACHE_UMA(COUNTS, "TrimItemsV2", 0, deleted_entries);
390 374
391 Trace("*** Trim Cache end ***"); 375 Trace("*** Trim Cache end ***");
392 trimming_ = false; 376 trimming_ = false;
393 return; 377 return;
394 } 378 }
395 379
396 void Eviction::UpdateRankV2(EntryImpl* entry, bool modified) {
397 rankings_->UpdateRank(entry->rankings(), modified, GetListForEntryV2(entry));
398 }
399
400 void Eviction::OnOpenEntryV2(EntryImpl* entry) {
401 EntryStore* info = entry->entry()->Data();
402 DCHECK_EQ(ENTRY_NORMAL, info->state);
403
404 if (info->reuse_count < kint32max) {
405 info->reuse_count++;
406 entry->entry()->set_modified();
407
408 // We may need to move this to a new list.
409 if (1 == info->reuse_count) {
410 rankings_->Remove(entry->rankings(), Rankings::NO_USE, true);
411 rankings_->Insert(entry->rankings(), false, Rankings::LOW_USE);
412 entry->entry()->Store();
413 } else if (kHighUse == info->reuse_count) {
414 rankings_->Remove(entry->rankings(), Rankings::LOW_USE, true);
415 rankings_->Insert(entry->rankings(), false, Rankings::HIGH_USE);
416 entry->entry()->Store();
417 }
418 }
419 }
420
421 void Eviction::OnCreateEntryV2(EntryImpl* entry) {
422 EntryStore* info = entry->entry()->Data();
423 switch (info->state) {
424 case ENTRY_NORMAL: {
425 DCHECK(!info->reuse_count);
426 DCHECK(!info->refetch_count);
427 break;
428 };
429 case ENTRY_EVICTED: {
430 if (info->refetch_count < kint32max)
431 info->refetch_count++;
432
433 if (info->refetch_count > kHighUse && info->reuse_count < kHighUse) {
434 info->reuse_count = kHighUse;
435 } else {
436 info->reuse_count++;
437 }
438 info->state = ENTRY_NORMAL;
439 entry->entry()->Store();
440 rankings_->Remove(entry->rankings(), Rankings::DELETED, true);
441 break;
442 };
443 default:
444 NOTREACHED();
445 }
446
447 rankings_->Insert(entry->rankings(), true, GetListForEntryV2(entry));
448 }
449
450 void Eviction::OnDoomEntryV2(EntryImpl* entry) {
451 EntryStore* info = entry->entry()->Data();
452 if (ENTRY_NORMAL != info->state)
453 return;
454
455 if (entry->LeaveRankingsBehind()) {
456 info->state = ENTRY_DOOMED;
457 entry->entry()->Store();
458 return;
459 }
460
461 rankings_->Remove(entry->rankings(), GetListForEntryV2(entry), true);
462
463 info->state = ENTRY_DOOMED;
464 entry->entry()->Store();
465 rankings_->Insert(entry->rankings(), true, Rankings::DELETED);
466 }
467
468 void Eviction::OnDestroyEntryV2(EntryImpl* entry) {
469 if (entry->LeaveRankingsBehind())
470 return;
471
472 rankings_->Remove(entry->rankings(), Rankings::DELETED, true);
473 }
474
475 Rankings::List Eviction::GetListForEntryV2(EntryImpl* entry) {
476 EntryStore* info = entry->entry()->Data();
477 DCHECK_EQ(ENTRY_NORMAL, info->state);
478
479 if (!info->reuse_count)
480 return Rankings::NO_USE;
481
482 if (info->reuse_count < kHighUse)
483 return Rankings::LOW_USE;
484
485 return Rankings::HIGH_USE;
486 }
487
488 // This is a minimal implementation that just discards the oldest nodes. 380 // This is a minimal implementation that just discards the oldest nodes.
489 // TODO(rvargas): Do something better here. 381 // TODO(rvargas): Do something better here.
490 void Eviction::TrimDeleted(bool empty) { 382 void Eviction::TrimDeleted(bool empty) {
491 Trace("*** Trim Deleted ***"); 383 Trace("*** Trim Deleted ***");
492 if (backend_->disabled_) 384 if (backend_->disabled_)
493 return; 385 return;
494 386
495 TimeTicks start = TimeTicks::Now(); 387 TimeTicks start = TimeTicks::Now();
496 Rankings::ScopedRankingsBlock node(rankings_); 388 Rankings::ScopedRankingsBlock node(rankings_);
497 Rankings::ScopedRankingsBlock next( 389 Rankings::ScopedRankingsBlock next(
(...skipping 15 matching lines...) Expand all
513 FROM_HERE, 405 FROM_HERE,
514 base::Bind(&Eviction::TrimDeleted, ptr_factory_.GetWeakPtr(), false)); 406 base::Bind(&Eviction::TrimDeleted, ptr_factory_.GetWeakPtr(), false));
515 } 407 }
516 408
517 CACHE_UMA(AGE_MS, "TotalTrimDeletedTime", 0, start); 409 CACHE_UMA(AGE_MS, "TotalTrimDeletedTime", 0, start);
518 CACHE_UMA(COUNTS, "TrimDeletedItems", 0, deleted_entries); 410 CACHE_UMA(COUNTS, "TrimDeletedItems", 0, deleted_entries);
519 Trace("*** Trim Deleted end ***"); 411 Trace("*** Trim Deleted end ***");
520 return; 412 return;
521 } 413 }
522 414
523 bool Eviction::RemoveDeletedNode(CacheRankingsBlock* node) { 415 void Eviction::ReportTrimTimes(EntryImpl* entry) {
524 EntryImpl* entry = backend_->GetEnumeratedEntry(node, Rankings::DELETED); 416 if (first_trim_) {
525 if (!entry) { 417 first_trim_ = false;
526 Trace("NewEntry failed on Trim 0x%x", node->address().value()); 418 if (backend_->ShouldReportAgain()) {
527 return false; 419 CACHE_UMA(AGE, "TrimAge", 0, entry->GetLastUsed());
420 ReportListStats();
421 }
422
423 if (header_->lru.filled)
424 return;
425
426 header_->lru.filled = 1;
427
428 if (header_->create_time) {
429 // This is the first entry that we have to evict, generate some noise.
430 backend_->FirstEviction();
431 } else {
432 // This is an old file, but we may want more reports from this user so
433 // lets save some create_time.
434 Time::Exploded old = {0};
435 old.year = 2009;
436 old.month = 3;
437 old.day_of_month = 1;
438 header_->create_time = Time::FromLocalExploded(old).ToInternalValue();
439 }
528 } 440 }
529
530 bool doomed = (entry->entry()->Data()->state == ENTRY_DOOMED);
531 entry->entry()->Data()->state = ENTRY_DOOMED;
532 entry->DoomImpl();
533 entry->Release();
534 return !doomed;
535 } 441 }
536 442
537 bool Eviction::NodeIsOldEnough(CacheRankingsBlock* node, int list) { 443 bool Eviction::NodeIsOldEnough(CacheRankingsBlock* node, int list) {
538 if (!node) 444 if (!node)
539 return false; 445 return false;
540 446
541 // If possible, we want to keep entries on each list at least kTargetTime 447 // If possible, we want to keep entries on each list at least kTargetTime
542 // hours. Each successive list on the enumeration has 2x the target time of 448 // hours. Each successive list on the enumeration has 2x the target time of
543 // the previous list. 449 // the previous list.
544 Time used = Time::FromInternalValue(node->Data()->last_used); 450 Time used = Time::FromInternalValue(node->Data()->last_used);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 Time::FromInternalValue(last2.get()->Data()->last_used)); 493 Time::FromInternalValue(last2.get()->Data()->last_used));
588 if (last3.get()) 494 if (last3.get())
589 CACHE_UMA(AGE, "HighUseAge", 0, 495 CACHE_UMA(AGE, "HighUseAge", 0,
590 Time::FromInternalValue(last3.get()->Data()->last_used)); 496 Time::FromInternalValue(last3.get()->Data()->last_used));
591 if (last4.get()) 497 if (last4.get())
592 CACHE_UMA(AGE, "DeletedAge", 0, 498 CACHE_UMA(AGE, "DeletedAge", 0,
593 Time::FromInternalValue(last4.get()->Data()->last_used)); 499 Time::FromInternalValue(last4.get()->Data()->last_used));
594 } 500 }
595 501
596 } // namespace disk_cache 502 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/v3/eviction_v3.h ('k') | net/disk_cache/v3/sparse_control_v3.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698