| 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..4811c564c175e8e4a21bc2331e5ba09848428a6e 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::IdleNotification() {
|
| + 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(
|
| @@ -155,11 +182,15 @@ size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const {
|
| return bytes_allocated_;
|
| }
|
|
|
| +TimeTicks DiscardableMemoryManager::Now() const {
|
| + return TimeTicks::Now();
|
| +}
|
| +
|
| 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 +200,29 @@ 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 +234,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 +247,17 @@ void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
|
| }
|
|
|
| if (bytes_allocated_ != bytes_allocated_before_purging)
|
| - BytesAllocatedChanged();
|
| -}
|
| -
|
| -void DiscardableMemoryManager::EnforcePolicyWithLockAcquired() {
|
| - PurgeLRUWithLockAcquiredUntilUsageIsWithin(memory_limit_);
|
| + BytesAllocatedChanged(bytes_allocated_);
|
| }
|
|
|
| -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));
|
| }
|
|
|
| } // namespace internal
|
|
|