void MemoryCache::pruneDeadResources() { unsigned capacity = deadCapacity(); if (capacity && m_deadSize <= capacity) return; unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again. pruneDeadResourcesToSize(targetSize); }
void MemoryCache::pruneDeadResources() { unsigned capacity = deadCapacity(); if (!m_deadSize || (capacity && m_deadSize <= capacity)) return; unsigned targetSize = static_cast<unsigned>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again. int size = m_allResources.size(); // See if we have any purged resources we can evict. for (int i = 0; i < size; i++) { Resource* current = m_allResources[i].m_tail; while (current) { Resource* prev = current->m_prevInAllResourcesList; if (current->wasPurged()) { ASSERT(!current->hasClients()); ASSERT(!current->isPreloaded()); evict(current); } current = prev; } } if (targetSize && m_deadSize <= targetSize) return; bool canShrinkLRULists = true; for (int i = size - 1; i >= 0; i--) { // Remove from the tail, since this is the least frequently accessed of the objects. Resource* current = m_allResources[i].m_tail; // First flush all the decoded data in this queue. while (current) { // Protect 'previous' so it can't get deleted during destroyDecodedData(). ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; ASSERT(!previous || previous->inCache()); if (!current->hasClients() && !current->isPreloaded() && current->isLoaded()) { // Destroy our decoded data. This will remove us from // m_liveDecodedResources, and possibly move us to a different // LRU list in m_allResources. current->destroyDecodedData(); if (targetSize && m_deadSize <= targetSize) return; } // Decoded data may reference other resources. Stop iterating if 'previous' somehow got // kicked out of cache during destroyDecodedData(). if (previous && !previous->inCache()) break; current = previous.get(); } // Now evict objects from this queue. current = m_allResources[i].m_tail; while (current) { ResourcePtr<Resource> previous = current->m_prevInAllResourcesList; ASSERT(!previous || previous->inCache()); if (!current->hasClients() && !current->isPreloaded() && !current->isCacheValidator()) { evict(current); if (targetSize && m_deadSize <= targetSize) return; } if (previous && !previous->inCache()) break; current = previous.get(); } // Shrink the vector back down so we don't waste time inspecting // empty LRU lists on future prunes. if (m_allResources[i].m_head) canShrinkLRULists = false; else if (canShrinkLRULists) m_allResources.resize(i); } }
unsigned MemoryCache::liveCapacity() const { // Live resource capacity is whatever is left over after calculating dead resource capacity. return m_capacity - deadCapacity(); }
void MemoryCache::pruneDeadResources(PruneStrategy strategy) { size_t capacity = deadCapacity(); if (strategy == MaximalPrune) capacity = 0; if (!m_deadSize || (capacity && m_deadSize <= capacity)) return; size_t targetSize = static_cast<size_t>(capacity * cTargetPrunePercentage); // Cut by a percentage to avoid immediately pruning again. int size = m_allResources.size(); // See if we have any purged resources we can evict. for (int i = 0; i < size; i++) { MemoryCacheEntry* current = m_allResources[i].m_tail; while (current) { MemoryCacheEntry* previous = current->m_previousInAllResourcesList; // Main Resources in the cache are only substitue data that was // precached and should not be evicted. if (current->m_resource->wasPurged() && current->m_resource->canDelete() && current->m_resource->type() != Resource::MainResource) { ASSERT(!current->m_resource->hasClients()); ASSERT(!current->m_resource->isPreloaded()); bool wasEvicted = evict(current); ASSERT_UNUSED(wasEvicted, wasEvicted); } current = previous; } } if (targetSize && m_deadSize <= targetSize) return; bool canShrinkLRULists = true; for (int i = size - 1; i >= 0; i--) { // Remove from the tail, since this is the least frequently accessed of the objects. MemoryCacheEntry* current = m_allResources[i].m_tail; // First flush all the decoded data in this queue. while (current) { // Protect 'previous' so it can't get deleted during destroyDecodedData(). MemoryCacheEntry* previous = current->m_previousInAllResourcesList; if (previous) { // These release assertions are for investigating crashes and // should be removed shortly. RELEASE_ASSERT(previous->m_resource); RELEASE_ASSERT(contains(previous->m_resource.get())); } if (!current->m_resource->hasClients() && !current->m_resource->isPreloaded() && current->m_resource->isLoaded()) { // Destroy our decoded data. This will remove us from // m_liveDecodedResources, and possibly move us to a different // LRU list in m_allResources. current->m_resource->prune(); if (targetSize && m_deadSize <= targetSize) return; } // Decoded data may reference other resources. Stop iterating if 'previous' somehow got // kicked out of cache during destroyDecodedData(). if (previous && !contains(previous->m_resource.get())) break; current = previous; } // Now evict objects from this queue. current = m_allResources[i].m_tail; while (current) { MemoryCacheEntry* previous = current->m_previousInAllResourcesList; if (previous) { // These release assertions are for investigating crashes and // should be removed shortly. RELEASE_ASSERT(previous->m_resource); RELEASE_ASSERT(contains(previous->m_resource.get())); } if (!current->m_resource->hasClients() && !current->m_resource->isPreloaded() && !current->m_resource->isCacheValidator() && current->m_resource->canDelete() && current->m_resource->type() != Resource::MainResource) { // Main Resources in the cache are only substitue data that was // precached and should not be evicted. bool wasEvicted = evict(current); ASSERT_UNUSED(wasEvicted, wasEvicted); if (targetSize && m_deadSize <= targetSize) return; } if (previous && !contains(previous->m_resource.get())) break; current = previous; } // Shrink the vector back down so we don't waste time inspecting // empty LRU lists on future prunes. if (m_allResources[i].m_head) canShrinkLRULists = false; else if (canShrinkLRULists) m_allResources.resize(i); } }