Index: base/memory/discardable_memory_manager.cc |
diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc |
index 49ecc484a7a6ff195f4e5cb23316eaef4625a73f..d976da203c4a88494dfffa6e73dd167bee6c2c11 100644 |
--- a/base/memory/discardable_memory_manager.cc |
+++ b/base/memory/discardable_memory_manager.cc |
@@ -17,13 +17,17 @@ namespace internal { |
DiscardableMemoryManager::DiscardableMemoryManager( |
size_t memory_limit, |
- size_t bytes_to_keep_under_moderate_pressure) |
+ size_t soft_memory_limit, |
+ size_t bytes_to_keep_under_moderate_pressure, |
+ TimeDelta hard_memory_limit_expiration_time) |
: allocations_(AllocationMap::NO_AUTO_EVICT), |
- bytes_allocated_(0), |
+ bytes_allocated_(0u), |
memory_limit_(memory_limit), |
+ soft_memory_limit_(soft_memory_limit), |
bytes_to_keep_under_moderate_pressure_( |
- bytes_to_keep_under_moderate_pressure) { |
- BytesAllocatedChanged(); |
+ bytes_to_keep_under_moderate_pressure), |
+ hard_memory_limit_expiration_time_(hard_memory_limit_expiration_time) { |
+ BytesAllocatedChanged(bytes_allocated_); |
} |
DiscardableMemoryManager::~DiscardableMemoryManager() { |
@@ -48,7 +52,13 @@ void DiscardableMemoryManager::UnregisterMemoryPressureListener() { |
void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) { |
AutoLock lock(lock_); |
memory_limit_ = bytes; |
- EnforcePolicyWithLockAcquired(); |
+ PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( |
+ Now(), memory_limit_); |
+} |
+ |
+void DiscardableMemoryManager::SetSoftMemoryLimit(size_t bytes) { |
+ AutoLock lock(lock_); |
+ soft_memory_limit_ = bytes; |
} |
void DiscardableMemoryManager::SetBytesToKeepUnderModeratePressure( |
@@ -57,6 +67,16 @@ void DiscardableMemoryManager::SetBytesToKeepUnderModeratePressure( |
bytes_to_keep_under_moderate_pressure_ = bytes; |
} |
+void DiscardableMemoryManager::SetHardMemoryLimitExpirationTime( |
+ TimeDelta hard_memory_limit_expiration_time) { |
+ AutoLock lock(lock_); |
+ hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time; |
+} |
+ |
+bool DiscardableMemoryManager::ReduceMemoryUsage() { |
+ return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit(); |
+} |
+ |
void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) { |
AutoLock lock(lock_); |
// A registered memory listener is currently required. This DCHECK can be |
@@ -78,7 +98,7 @@ void DiscardableMemoryManager::Unregister(Allocation* allocation) { |
size_t bytes_purgable = info.bytes; |
DCHECK_LE(bytes_purgable, bytes_allocated_); |
bytes_allocated_ -= bytes_purgable; |
- BytesAllocatedChanged(); |
+ BytesAllocatedChanged(bytes_allocated_); |
} |
allocations_.Erase(it); |
} |
@@ -95,6 +115,7 @@ bool DiscardableMemoryManager::AcquireLock(Allocation* allocation, |
if (!info->bytes) |
return false; |
+ TimeTicks now = Now(); |
size_t bytes_required = info->purgable ? 0u : info->bytes; |
if (memory_limit_) { |
@@ -102,7 +123,8 @@ bool DiscardableMemoryManager::AcquireLock(Allocation* allocation, |
if (bytes_required < memory_limit_) |
limit = memory_limit_ - bytes_required; |
- PurgeLRUWithLockAcquiredUntilUsageIsWithin(limit); |
+ PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(now, |
+ limit); |
} |
// Check for overflow. |
@@ -111,9 +133,10 @@ bool DiscardableMemoryManager::AcquireLock(Allocation* allocation, |
*purged = !allocation->AllocateAndAcquireLock(); |
info->purgable = false; |
+ info->last_usage = now; |
if (bytes_required) { |
bytes_allocated_ += bytes_required; |
- BytesAllocatedChanged(); |
+ BytesAllocatedChanged(bytes_allocated_); |
} |
return true; |
} |
@@ -126,14 +149,18 @@ void DiscardableMemoryManager::ReleaseLock(Allocation* allocation) { |
DCHECK(it != allocations_.end()); |
AllocationInfo* info = &it->second; |
+ TimeTicks now = Now(); |
allocation->ReleaseLock(); |
info->purgable = true; |
- EnforcePolicyWithLockAcquired(); |
+ info->last_usage = now; |
+ |
+ PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( |
+ now, memory_limit_); |
} |
void DiscardableMemoryManager::PurgeAll() { |
AutoLock lock(lock_); |
- PurgeLRUWithLockAcquiredUntilUsageIsWithin(0); |
+ PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(), 0); |
} |
bool DiscardableMemoryManager::IsRegisteredForTest( |
@@ -159,7 +186,7 @@ void DiscardableMemoryManager::OnMemoryPressure( |
MemoryPressureListener::MemoryPressureLevel pressure_level) { |
switch (pressure_level) { |
case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: |
- Purge(); |
+ PurgeUntilWithinBytesToKeepUnderModeratePressure(); |
return; |
case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: |
PurgeAll(); |
@@ -169,21 +196,28 @@ void DiscardableMemoryManager::OnMemoryPressure( |
NOTREACHED(); |
} |
-void DiscardableMemoryManager::Purge() { |
+void |
+DiscardableMemoryManager::PurgeUntilWithinBytesToKeepUnderModeratePressure() { |
AutoLock lock(lock_); |
- PurgeLRUWithLockAcquiredUntilUsageIsWithin( |
- bytes_to_keep_under_moderate_pressure_); |
+ PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( |
+ Now(), bytes_to_keep_under_moderate_pressure_); |
} |
-void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin( |
- size_t limit) { |
- TRACE_EVENT1( |
- "base", |
- "DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin", |
- "limit", |
- limit); |
+bool DiscardableMemoryManager:: |
+ PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit() { |
+ AutoLock lock(lock_); |
+ |
+ PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( |
+ Now() - hard_memory_limit_expiration_time_, soft_memory_limit_); |
+ return bytes_allocated_ <= soft_memory_limit_; |
+} |
+ |
+void DiscardableMemoryManager:: |
+ PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( |
+ TimeTicks timestamp, |
+ size_t limit) { |
lock_.AssertAcquired(); |
size_t bytes_allocated_before_purging = bytes_allocated_; |
@@ -195,7 +229,9 @@ void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin( |
if (bytes_allocated_ <= limit) |
break; |
- if (!info->purgable) |
+ |
+ bool purgable = info->purgable && info->last_usage <= timestamp; |
+ if (!purgable) |
continue; |
size_t bytes_purgable = info->bytes; |
@@ -206,19 +242,21 @@ void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin( |
} |
if (bytes_allocated_ != bytes_allocated_before_purging) |
- BytesAllocatedChanged(); |
+ BytesAllocatedChanged(bytes_allocated_); |
} |
-void DiscardableMemoryManager::EnforcePolicyWithLockAcquired() { |
- PurgeLRUWithLockAcquiredUntilUsageIsWithin(memory_limit_); |
-} |
- |
-void DiscardableMemoryManager::BytesAllocatedChanged() const { |
- TRACE_COUNTER_ID1("base", "DiscardableMemoryUsage", this, bytes_allocated_); |
+void DiscardableMemoryManager::BytesAllocatedChanged( |
+ size_t new_bytes_allocated) const { |
+ TRACE_COUNTER_ID1( |
+ "base", "DiscardableMemoryUsage", this, new_bytes_allocated); |
static const char kDiscardableMemoryUsageKey[] = "dm-usage"; |
base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey, |
- Uint64ToString(bytes_allocated_)); |
+ Uint64ToString(new_bytes_allocated)); |
+} |
+ |
+TimeTicks DiscardableMemoryManager::Now() const { |
+ return TimeTicks::Now(); |
} |
} // namespace internal |