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

Side by Side Diff: third_party/WebKit/Source/core/fetch/MemoryCache.cpp

Issue 1915113005: [WeakMemoryCache] Field-Trial: Make Reference from MemoryCache to Resource weak (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@MemoryCache_1b0
Patch Set: Rebase. Created 4 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
OLDNEW
1 /* 1 /*
2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
5 Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 5 Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
6 6
7 This library is free software; you can redistribute it and/or 7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public 8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either 9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version. 10 version 2 of the License, or (at your option) any later version.
11 11
12 This library is distributed in the hope that it will be useful, 12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details. 15 Library General Public License for more details.
16 16
17 You should have received a copy of the GNU Library General Public License 17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to 18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. 20 Boston, MA 02110-1301, USA.
21 */ 21 */
22 22
23 #include "core/fetch/MemoryCache.h" 23 #include "core/fetch/MemoryCache.h"
24 24
25 #include "platform/Logging.h" 25 #include "platform/Logging.h"
26 #include "platform/RuntimeEnabledFeatures.h"
26 #include "platform/TraceEvent.h" 27 #include "platform/TraceEvent.h"
27 #include "platform/weborigin/SecurityOrigin.h" 28 #include "platform/weborigin/SecurityOrigin.h"
28 #include "platform/weborigin/SecurityOriginHash.h" 29 #include "platform/weborigin/SecurityOriginHash.h"
29 #include "public/platform/Platform.h" 30 #include "public/platform/Platform.h"
30 #include "wtf/Assertions.h" 31 #include "wtf/Assertions.h"
31 #include "wtf/CurrentTime.h" 32 #include "wtf/CurrentTime.h"
32 #include "wtf/MathExtras.h" 33 #include "wtf/MathExtras.h"
33 #include "wtf/TemporaryChange.h" 34 #include "wtf/TemporaryChange.h"
34 #include "wtf/text/CString.h" 35 #include "wtf/text/CString.h"
35 36
(...skipping 17 matching lines...) Expand all
53 54
54 MemoryCache* replaceMemoryCacheForTesting(MemoryCache* cache) 55 MemoryCache* replaceMemoryCacheForTesting(MemoryCache* cache)
55 { 56 {
56 memoryCache(); 57 memoryCache();
57 MemoryCache* oldCache = gMemoryCache->release(); 58 MemoryCache* oldCache = gMemoryCache->release();
58 *gMemoryCache = cache; 59 *gMemoryCache = cache;
59 MemoryCacheDumpProvider::instance()->setMemoryCache(cache); 60 MemoryCacheDumpProvider::instance()->setMemoryCache(cache);
60 return oldCache; 61 return oldCache;
61 } 62 }
62 63
64 MemoryCacheEntry::MemoryCacheEntry(Resource* resource)
65 : m_inLiveDecodedResourcesList(false)
66 , m_accessCount(0)
67 , m_lastDecodedAccessTime(0.0)
68 , m_previousInLiveResourcesList(nullptr)
69 , m_nextInLiveResourcesList(nullptr)
70 , m_previousInAllResourcesList(nullptr)
71 , m_nextInAllResourcesList(nullptr)
72 {
73 if (RuntimeEnabledFeatures::weakMemoryCacheEnabled())
74 m_resourceWeak = resource;
75 else
76 m_resource = resource;
77 }
78
63 DEFINE_TRACE(MemoryCacheEntry) 79 DEFINE_TRACE(MemoryCacheEntry)
64 { 80 {
65 visitor->trace(m_resource); 81 visitor->trace(m_resource);
82 visitor->trace(m_resourceWeak);
66 visitor->trace(m_previousInLiveResourcesList); 83 visitor->trace(m_previousInLiveResourcesList);
67 visitor->trace(m_nextInLiveResourcesList); 84 visitor->trace(m_nextInLiveResourcesList);
68 visitor->trace(m_previousInAllResourcesList); 85 visitor->trace(m_previousInAllResourcesList);
69 visitor->trace(m_nextInAllResourcesList); 86 visitor->trace(m_nextInAllResourcesList);
70 } 87 }
71 88
72 void MemoryCacheEntry::dispose() 89 void MemoryCacheEntry::dispose()
73 { 90 {
74 m_resource.clear(); 91 m_resource.clear();
92 m_resourceWeak.clear();
75 } 93 }
76 94
77 Resource* MemoryCacheEntry::resource() 95 Resource* MemoryCacheEntry::resource()
78 { 96 {
97 if (RuntimeEnabledFeatures::weakMemoryCacheEnabled())
98 return m_resourceWeak.get();
79 return m_resource.get(); 99 return m_resource.get();
80 } 100 }
81 101
82 DEFINE_TRACE(MemoryCacheLRUList) 102 DEFINE_TRACE(MemoryCacheLRUList)
83 { 103 {
84 visitor->trace(m_head); 104 visitor->trace(m_head);
85 visitor->trace(m_tail); 105 visitor->trace(m_tail);
86 } 106 }
87 107
88 inline MemoryCache::MemoryCache() 108 inline MemoryCache::MemoryCache()
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 } 176 }
157 return m_resourceMaps.get(cacheIdentifier); 177 return m_resourceMaps.get(cacheIdentifier);
158 } 178 }
159 179
160 void MemoryCache::add(Resource* resource) 180 void MemoryCache::add(Resource* resource)
161 { 181 {
162 ASSERT(WTF::isMainThread()); 182 ASSERT(WTF::isMainThread());
163 ASSERT(resource->url().isValid()); 183 ASSERT(resource->url().isValid());
164 ResourceMap* resources = ensureResourceMap(resource->cacheIdentifier()); 184 ResourceMap* resources = ensureResourceMap(resource->cacheIdentifier());
165 KURL url = removeFragmentIdentifierIfNeeded(resource->url()); 185 KURL url = removeFragmentIdentifierIfNeeded(resource->url());
166 RELEASE_ASSERT(!resources->contains(url)); 186 RELEASE_ASSERT(!contains(resource));
167 resources->set(url, MemoryCacheEntry::create(resource)); 187 resources->set(url, MemoryCacheEntry::create(resource));
168 update(resource, 0, resource->size(), true); 188 update(resource, 0, resource->size(), true);
169 189
170 WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resou rce->url().getString().latin1().data(), resource); 190 WTF_LOG(ResourceLoading, "MemoryCache::add Added '%s', resource %p\n", resou rce->url().getString().latin1().data(), resource);
171 } 191 }
172 192
173 void MemoryCache::remove(Resource* resource) 193 void MemoryCache::remove(Resource* resource)
174 { 194 {
175 // The resource may have already been removed by someone other than our call er, 195 // The resource may have already been removed by someone other than our call er,
176 // who needed a fresh copy for a reload. 196 // who needed a fresh copy for a reload.
(...skipping 29 matching lines...) Expand all
206 return nullptr; 226 return nullptr;
207 return resource; 227 return resource;
208 } 228 }
209 229
210 HeapVector<Member<Resource>> MemoryCache::resourcesForURL(const KURL& resourceUR L) 230 HeapVector<Member<Resource>> MemoryCache::resourcesForURL(const KURL& resourceUR L)
211 { 231 {
212 ASSERT(WTF::isMainThread()); 232 ASSERT(WTF::isMainThread());
213 KURL url = removeFragmentIdentifierIfNeeded(resourceURL); 233 KURL url = removeFragmentIdentifierIfNeeded(resourceURL);
214 HeapVector<Member<Resource>> results; 234 HeapVector<Member<Resource>> results;
215 for (const auto& resourceMapIter : m_resourceMaps) { 235 for (const auto& resourceMapIter : m_resourceMaps) {
216 if (MemoryCacheEntry* entry = resourceMapIter.value->get(url)) 236 if (MemoryCacheEntry* entry = resourceMapIter.value->get(url)) {
217 results.append(entry->resource()); 237 Resource* resource = entry->resource();
238 if (resource)
239 results.append(resource);
240 }
218 } 241 }
219 return results; 242 return results;
220 } 243 }
221 244
222 size_t MemoryCache::deadCapacity() const 245 size_t MemoryCache::deadCapacity() const
223 { 246 {
224 // Dead resource capacity is whatever space is not occupied by live resource s, bounded by an independent minimum and maximum. 247 // Dead resource capacity is whatever space is not occupied by live resource s, bounded by an independent minimum and maximum.
225 size_t capacity = m_capacity - std::min(m_liveSize, m_capacity); // Start wi th available capacity. 248 size_t capacity = m_capacity - std::min(m_liveSize, m_capacity); // Start wi th available capacity.
226 capacity = std::max(capacity, m_minDeadCapacity); // Make sure it's above th e minimum. 249 capacity = std::max(capacity, m_minDeadCapacity); // Make sure it's above th e minimum.
227 capacity = std::min(capacity, m_maxDeadCapacity); // Make sure it's below th e maximum. 250 capacity = std::min(capacity, m_maxDeadCapacity); // Make sure it's below th e maximum.
(...skipping 24 matching lines...) Expand all
252 // The list might not be sorted by the m_lastDecodedFrameTimeStamp. The impa ct 275 // The list might not be sorted by the m_lastDecodedFrameTimeStamp. The impa ct
253 // of this weaker invariant is minor as the below if statement to check the 276 // of this weaker invariant is minor as the below if statement to check the
254 // elapsedTime will evaluate to false as the current time will be a lot 277 // elapsedTime will evaluate to false as the current time will be a lot
255 // greater than the current->m_lastDecodedFrameTimeStamp. 278 // greater than the current->m_lastDecodedFrameTimeStamp.
256 // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209 279 // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209
257 280
258 MemoryCacheEntry* current = m_liveDecodedResources.m_tail; 281 MemoryCacheEntry* current = m_liveDecodedResources.m_tail;
259 while (current) { 282 while (current) {
260 Resource* resource = current->resource(); 283 Resource* resource = current->resource();
261 MemoryCacheEntry* previous = current->m_previousInLiveResourcesList; 284 MemoryCacheEntry* previous = current->m_previousInLiveResourcesList;
285 if (!resource) {
286 current = previous;
287 continue;
288 }
262 ASSERT(resource->hasClientsOrObservers()); 289 ASSERT(resource->hasClientsOrObservers());
263 290
264 if (resource->isLoaded() && resource->decodedSize()) { 291 if (resource->isLoaded() && resource->decodedSize()) {
265 // Check to see if the remaining resources are too new to prune. 292 // Check to see if the remaining resources are too new to prune.
266 double elapsedTime = m_pruneFrameTimeStamp - current->m_lastDecodedA ccessTime; 293 double elapsedTime = m_pruneFrameTimeStamp - current->m_lastDecodedA ccessTime;
267 if (strategy == AutomaticPrune && elapsedTime < m_delayBeforeLiveDec odedPrune) 294 if (strategy == AutomaticPrune && elapsedTime < m_delayBeforeLiveDec odedPrune)
268 return; 295 return;
269 296
270 // Destroy our decoded data if possible. This will remove us 297 // Destroy our decoded data if possible. This will remove us
271 // from m_liveDecodedResources, and possibly move us to a 298 // from m_liveDecodedResources, and possibly move us to a
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 m_maxDeferredPruneDeadCapacity = cDeferredPruneDeadCapacityFactor * maxDeadB ytes; 385 m_maxDeferredPruneDeadCapacity = cDeferredPruneDeadCapacityFactor * maxDeadB ytes;
359 m_capacity = totalBytes; 386 m_capacity = totalBytes;
360 prune(); 387 prune();
361 } 388 }
362 389
363 void MemoryCache::evict(MemoryCacheEntry* entry) 390 void MemoryCache::evict(MemoryCacheEntry* entry)
364 { 391 {
365 ASSERT(WTF::isMainThread()); 392 ASSERT(WTF::isMainThread());
366 393
367 Resource* resource = entry->resource(); 394 Resource* resource = entry->resource();
395 DCHECK(resource);
368 WTF_LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resourc e, resource->url().getString().latin1().data()); 396 WTF_LOG(ResourceLoading, "Evicting resource %p for '%s' from cache", resourc e, resource->url().getString().latin1().data());
369 // The resource may have already been removed by someone other than our call er, 397 // The resource may have already been removed by someone other than our call er,
370 // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bu g.cgi?id=12479#c6>. 398 // who needed a fresh copy for a reload. See <http://bugs.webkit.org/show_bu g.cgi?id=12479#c6>.
371 update(resource, resource->size(), 0, false); 399 update(resource, resource->size(), 0, false);
372 removeFromLiveDecodedResourcesList(entry); 400 removeFromLiveDecodedResourcesList(entry);
373 401
374 ResourceMap* resources = m_resourceMaps.get(resource->cacheIdentifier()); 402 ResourceMap* resources = m_resourceMaps.get(resource->cacheIdentifier());
375 ASSERT(resources); 403 ASSERT(resources);
376 KURL url = removeFragmentIdentifierIfNeeded(resource->url()); 404 KURL url = removeFragmentIdentifierIfNeeded(resource->url());
377 ResourceMap::iterator it = resources->find(url); 405 ResourceMap::iterator it = resources->find(url);
378 ASSERT(it != resources->end()); 406 ASSERT(it != resources->end());
379 407
380 MemoryCacheEntry* entryPtr = it->value; 408 MemoryCacheEntry* entryPtr = it->value;
381 resources->remove(it); 409 resources->remove(it);
382 if (entryPtr) 410 if (entryPtr)
383 entryPtr->dispose(); 411 entryPtr->dispose();
384 } 412 }
385 413
386 MemoryCacheEntry* MemoryCache::getEntryForResource(const Resource* resource) con st 414 MemoryCacheEntry* MemoryCache::getEntryForResource(const Resource* resource) con st
387 { 415 {
388 if (resource->url().isNull() || resource->url().isEmpty()) 416 if (!resource || resource->url().isNull() || resource->url().isEmpty())
389 return nullptr; 417 return nullptr;
390 ResourceMap* resources = m_resourceMaps.get(resource->cacheIdentifier()); 418 ResourceMap* resources = m_resourceMaps.get(resource->cacheIdentifier());
391 if (!resources) 419 if (!resources)
392 return nullptr; 420 return nullptr;
393 KURL url = removeFragmentIdentifierIfNeeded(resource->url()); 421 KURL url = removeFragmentIdentifierIfNeeded(resource->url());
394 MemoryCacheEntry* entry = resources->get(url); 422 MemoryCacheEntry* entry = resources->get(url);
395 if (!entry || entry->resource() != resource) 423 if (!entry || entry->resource() != resource)
396 return nullptr; 424 return nullptr;
397 return entry; 425 return entry;
398 } 426 }
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 encodedSizeDuplicatedInDataURLs += o->url().protocolIsData() ? o->encodedSiz e() : 0; 619 encodedSizeDuplicatedInDataURLs += o->url().protocolIsData() ? o->encodedSiz e() : 0;
592 purgeableSize += purgeable ? pageSize : 0; 620 purgeableSize += purgeable ? pageSize : 0;
593 } 621 }
594 622
595 MemoryCache::Statistics MemoryCache::getStatistics() 623 MemoryCache::Statistics MemoryCache::getStatistics()
596 { 624 {
597 Statistics stats; 625 Statistics stats;
598 for (const auto& resourceMapIter : m_resourceMaps) { 626 for (const auto& resourceMapIter : m_resourceMaps) {
599 for (const auto& resourceIter : *resourceMapIter.value) { 627 for (const auto& resourceIter : *resourceMapIter.value) {
600 Resource* resource = resourceIter.value->resource(); 628 Resource* resource = resourceIter.value->resource();
629 if (!resource)
630 continue;
601 switch (resource->getType()) { 631 switch (resource->getType()) {
602 case Resource::Image: 632 case Resource::Image:
603 stats.images.addResource(resource); 633 stats.images.addResource(resource);
604 break; 634 break;
605 case Resource::CSSStyleSheet: 635 case Resource::CSSStyleSheet:
606 stats.cssStyleSheets.addResource(resource); 636 stats.cssStyleSheets.addResource(resource);
607 break; 637 break;
608 case Resource::Script: 638 case Resource::Script:
609 stats.scripts.addResource(resource); 639 stats.scripts.addResource(resource);
610 break; 640 break;
(...skipping 16 matching lines...) Expand all
627 { 657 {
628 while (true) { 658 while (true) {
629 ResourceMapIndex::iterator resourceMapIter = m_resourceMaps.begin(); 659 ResourceMapIndex::iterator resourceMapIter = m_resourceMaps.begin();
630 if (resourceMapIter == m_resourceMaps.end()) 660 if (resourceMapIter == m_resourceMaps.end())
631 break; 661 break;
632 ResourceMap* resources = resourceMapIter->value.get(); 662 ResourceMap* resources = resourceMapIter->value.get();
633 while (true) { 663 while (true) {
634 ResourceMap::iterator resourceIter = resources->begin(); 664 ResourceMap::iterator resourceIter = resources->begin();
635 if (resourceIter == resources->end()) 665 if (resourceIter == resources->end())
636 break; 666 break;
637 evict(resourceIter->value.get()); 667 if (resourceIter->value->resource())
668 evict(resourceIter->value.get());
669 else
670 resources->remove(resourceIter);
638 } 671 }
639 m_resourceMaps.remove(resourceMapIter); 672 m_resourceMaps.remove(resourceMapIter);
640 } 673 }
641 } 674 }
642 675
643 void MemoryCache::prune(Resource* justReleasedResource) 676 void MemoryCache::prune(Resource* justReleasedResource)
644 { 677 {
645 TRACE_EVENT0("renderer", "MemoryCache::prune()"); 678 TRACE_EVENT0("renderer", "MemoryCache::prune()");
646 679
647 if (m_inPruneResources) 680 if (m_inPruneResources)
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 void MemoryCache::updateFramePaintTimestamp() 754 void MemoryCache::updateFramePaintTimestamp()
722 { 755 {
723 m_lastFramePaintTimeStamp = currentTime(); 756 m_lastFramePaintTimeStamp = currentTime();
724 } 757 }
725 758
726 bool MemoryCache::onMemoryDump(WebMemoryDumpLevelOfDetail levelOfDetail, WebProc essMemoryDump* memoryDump) 759 bool MemoryCache::onMemoryDump(WebMemoryDumpLevelOfDetail levelOfDetail, WebProc essMemoryDump* memoryDump)
727 { 760 {
728 for (const auto& resourceMapIter : m_resourceMaps) { 761 for (const auto& resourceMapIter : m_resourceMaps) {
729 for (const auto& resourceIter : *resourceMapIter.value) { 762 for (const auto& resourceIter : *resourceMapIter.value) {
730 Resource* resource = resourceIter.value->resource(); 763 Resource* resource = resourceIter.value->resource();
731 resource->onMemoryDump(levelOfDetail, memoryDump); 764 if (resource)
765 resource->onMemoryDump(levelOfDetail, memoryDump);
732 } 766 }
733 } 767 }
734 return true; 768 return true;
735 } 769 }
736 770
737 bool MemoryCache::isInSameLRUListForTest(const Resource* x, const Resource* y) 771 bool MemoryCache::isInSameLRUListForTest(const Resource* x, const Resource* y)
738 { 772 {
739 MemoryCacheEntry* ex = getEntryForResource(x); 773 MemoryCacheEntry* ex = getEntryForResource(x);
740 MemoryCacheEntry* ey = getEntryForResource(y); 774 MemoryCacheEntry* ey = getEntryForResource(y);
741 ASSERT(ex); 775 ASSERT(ex);
(...skipping 28 matching lines...) Expand all
770 void MemoryCache::dumpLRULists(bool includeLive) const 804 void MemoryCache::dumpLRULists(bool includeLive) const
771 { 805 {
772 printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded , Access count, Referenced, isPurgeable):\n"); 806 printf("LRU-SP lists in eviction order (Kilobytes decoded, Kilobytes encoded , Access count, Referenced, isPurgeable):\n");
773 807
774 int size = m_allResources.size(); 808 int size = m_allResources.size();
775 for (int i = size - 1; i >= 0; i--) { 809 for (int i = size - 1; i >= 0; i--) {
776 printf("\n\nList %d: ", i); 810 printf("\n\nList %d: ", i);
777 MemoryCacheEntry* current = m_allResources[i].m_tail; 811 MemoryCacheEntry* current = m_allResources[i].m_tail;
778 while (current) { 812 while (current) {
779 Resource* currentResource = current->resource(); 813 Resource* currentResource = current->resource();
780 if (includeLive || !currentResource->hasClientsOrObservers()) 814 if (currentResource && (includeLive || !currentResource->hasClientsO rObservers()))
781 printf("(%.1fK, %.1fK, %uA, %dR, %d); ", currentResource->decode dSize() / 1024.0f, (currentResource->encodedSize() + currentResource->overheadSi ze()) / 1024.0f, current->m_accessCount, currentResource->hasClientsOrObservers( ), currentResource->isPurgeable()); 815 printf("(%.1fK, %.1fK, %uA, %dR, %d); ", currentResource->decode dSize() / 1024.0f, (currentResource->encodedSize() + currentResource->overheadSi ze()) / 1024.0f, current->m_accessCount, currentResource->hasClientsOrObservers( ), currentResource->isPurgeable());
782 816
783 current = current->m_previousInAllResourcesList; 817 current = current->m_previousInAllResourcesList;
784 } 818 }
785 } 819 }
786 } 820 }
787 821
788 #endif // MEMORY_CACHE_STATS 822 #endif // MEMORY_CACHE_STATS
789 823
790 } // namespace blink 824 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/fetch/MemoryCache.h ('k') | third_party/WebKit/Source/core/fetch/Resource.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698