diff options
author | reveman <reveman@chromium.org> | 2015-03-11 20:27:04 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-12 03:27:29 +0000 |
commit | 2092eaa97b727840b932824dd0f7582a4868a00b (patch) | |
tree | cf5f4e32cc269acf9c8ea6a68a0772f1d2e2e32f /base/memory | |
parent | 77f0e1aa1344e35343d6932415f2b3c0f381ef6f (diff) | |
download | chromium_src-2092eaa97b727840b932824dd0f7582a4868a00b.zip chromium_src-2092eaa97b727840b932824dd0f7582a4868a00b.tar.gz chromium_src-2092eaa97b727840b932824dd0f7582a4868a00b.tar.bz2 |
base: Remove unused DiscardableMemoryManager class.
BUG=442945,422953
Review URL: https://codereview.chromium.org/999903002
Cr-Commit-Position: refs/heads/master@{#320224}
Diffstat (limited to 'base/memory')
-rw-r--r-- | base/memory/BUILD.gn | 4 | ||||
-rw-r--r-- | base/memory/discardable_memory_manager.cc | 218 | ||||
-rw-r--r-- | base/memory/discardable_memory_manager.h | 166 | ||||
-rw-r--r-- | base/memory/discardable_memory_manager_unittest.cc | 490 |
4 files changed, 0 insertions, 878 deletions
diff --git a/base/memory/BUILD.gn b/base/memory/BUILD.gn index 535202a..5d016ff 100644 --- a/base/memory/BUILD.gn +++ b/base/memory/BUILD.gn @@ -11,8 +11,6 @@ source_set("memory") { "discardable_memory_android.cc", "discardable_memory_linux.cc", "discardable_memory_mac.cc", - "discardable_memory_manager.cc", - "discardable_memory_manager.h", "discardable_memory_shmem.cc", "discardable_memory_shmem.h", "discardable_memory_shmem_allocator.cc", @@ -48,8 +46,6 @@ source_set("memory") { sources -= [ "discardable_memory.cc", "discardable_memory.h", - "discardable_memory_manager.cc", - "discardable_memory_manager.h", "discardable_memory_shmem.cc", "discardable_memory_shmem.h", "discardable_memory_shmem_allocator.cc", diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc deleted file mode 100644 index cbbdb47..0000000 --- a/base/memory/discardable_memory_manager.cc +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_manager.h" - -#include "base/bind.h" -#include "base/containers/adapters.h" -#include "base/containers/hash_tables.h" -#include "base/containers/mru_cache.h" -#include "base/debug/crash_logging.h" -#include "base/strings/string_number_conversions.h" -#include "base/synchronization/lock.h" -#include "base/trace_event/trace_event.h" - -namespace base { -namespace internal { - -DiscardableMemoryManager::DiscardableMemoryManager( - size_t memory_limit, - size_t soft_memory_limit, - TimeDelta hard_memory_limit_expiration_time) - : allocations_(AllocationMap::NO_AUTO_EVICT), - bytes_allocated_(0u), - memory_limit_(memory_limit), - soft_memory_limit_(soft_memory_limit), - hard_memory_limit_expiration_time_(hard_memory_limit_expiration_time) { - BytesAllocatedChanged(bytes_allocated_); -} - -DiscardableMemoryManager::~DiscardableMemoryManager() { - DCHECK(allocations_.empty()); - DCHECK_EQ(0u, bytes_allocated_); -} - -void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) { - AutoLock lock(lock_); - memory_limit_ = bytes; - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - Now(), memory_limit_); -} - -void DiscardableMemoryManager::SetSoftMemoryLimit(size_t bytes) { - AutoLock lock(lock_); - soft_memory_limit_ = 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::ReduceMemoryUsageUntilWithinLimit(size_t bytes) { - AutoLock lock(lock_); - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(), - bytes); -} - -void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) { - AutoLock lock(lock_); - DCHECK(allocations_.Peek(allocation) == allocations_.end()); - allocations_.Put(allocation, AllocationInfo(bytes)); -} - -void DiscardableMemoryManager::Unregister(Allocation* allocation) { - AutoLock lock(lock_); - AllocationMap::iterator it = allocations_.Peek(allocation); - DCHECK(it != allocations_.end()); - const AllocationInfo& info = it->second; - - if (info.purgable) { - size_t bytes_purgable = info.bytes; - DCHECK_LE(bytes_purgable, bytes_allocated_); - bytes_allocated_ -= bytes_purgable; - BytesAllocatedChanged(bytes_allocated_); - } - allocations_.Erase(it); -} - -bool DiscardableMemoryManager::AcquireLock(Allocation* allocation, - bool* purged) { - AutoLock lock(lock_); - // Note: |allocations_| is an MRU cache, and use of |Get| here updates that - // cache. - AllocationMap::iterator it = allocations_.Get(allocation); - DCHECK(it != allocations_.end()); - AllocationInfo* info = &it->second; - - if (!info->bytes) - return false; - - TimeTicks now = Now(); - size_t bytes_required = info->purgable ? 0u : info->bytes; - - if (memory_limit_) { - size_t limit = 0; - if (bytes_required < memory_limit_) - limit = memory_limit_ - bytes_required; - - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(now, - limit); - } - - // Check for overflow. - if (std::numeric_limits<size_t>::max() - bytes_required < bytes_allocated_) - return false; - - *purged = !allocation->AllocateAndAcquireLock(); - info->purgable = false; - info->last_usage = now; - if (bytes_required) { - bytes_allocated_ += bytes_required; - BytesAllocatedChanged(bytes_allocated_); - } - return true; -} - -void DiscardableMemoryManager::ReleaseLock(Allocation* allocation) { - AutoLock lock(lock_); - // Note: |allocations_| is an MRU cache, and use of |Get| here updates that - // cache. - AllocationMap::iterator it = allocations_.Get(allocation); - DCHECK(it != allocations_.end()); - AllocationInfo* info = &it->second; - - TimeTicks now = Now(); - allocation->ReleaseLock(); - info->purgable = true; - info->last_usage = now; - - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - now, memory_limit_); -} - -void DiscardableMemoryManager::PurgeAll() { - AutoLock lock(lock_); - PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(), 0); -} - -bool DiscardableMemoryManager::IsRegisteredForTest( - Allocation* allocation) const { - AutoLock lock(lock_); - AllocationMap::const_iterator it = allocations_.Peek(allocation); - return it != allocations_.end(); -} - -bool DiscardableMemoryManager::CanBePurgedForTest( - Allocation* allocation) const { - AutoLock lock(lock_); - AllocationMap::const_iterator it = allocations_.Peek(allocation); - return it != allocations_.end() && it->second.purgable; -} - -size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const { - AutoLock lock(lock_); - return bytes_allocated_; -} - -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_; - for (auto& entry : base::Reversed(allocations_)) { - Allocation* allocation = entry.first; - AllocationInfo* info = &entry.second; - - if (bytes_allocated_ <= limit) - break; - - bool purgable = info->purgable && info->last_usage <= timestamp; - if (!purgable) - continue; - - size_t bytes_purgable = info->bytes; - DCHECK_LE(bytes_purgable, bytes_allocated_); - bytes_allocated_ -= bytes_purgable; - info->purgable = false; - allocation->Purge(); - } - - if (bytes_allocated_ != bytes_allocated_before_purging) - BytesAllocatedChanged(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(new_bytes_allocated)); -} - -TimeTicks DiscardableMemoryManager::Now() const { - return TimeTicks::Now(); -} - -} // namespace internal -} // namespace base diff --git a/base/memory/discardable_memory_manager.h b/base/memory/discardable_memory_manager.h deleted file mode 100644 index 43737f8..0000000 --- a/base/memory/discardable_memory_manager.h +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_ -#define BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_ - -#include "base/base_export.h" -#include "base/containers/hash_tables.h" -#include "base/containers/mru_cache.h" -#include "base/synchronization/lock.h" -#include "base/time/time.h" - -namespace base { -namespace internal { - -// This interface is used by the DiscardableMemoryManager class to provide some -// level of userspace control over discardable memory allocations. -class DiscardableMemoryManagerAllocation { - public: - // Allocate and acquire a lock that prevents the allocation from being purged - // by the system. Returns true if memory was previously allocated and is still - // resident. - virtual bool AllocateAndAcquireLock() = 0; - - // Release a previously acquired lock on the allocation so that it can be - // purged by the system. - virtual void ReleaseLock() = 0; - - // Explicitly purge this allocation. It is illegal to call this while a lock - // is acquired on the allocation. - virtual void Purge() = 0; - - protected: - virtual ~DiscardableMemoryManagerAllocation() {} -}; - -} // namespace internal -} // namespace base - -namespace base { -namespace internal { - -// The DiscardableMemoryManager manages a collection of -// DiscardableMemoryManagerAllocation instances. It is used on platforms that -// need some level of userspace control over discardable memory. It keeps track -// of all allocation instances (in case they need to be purged), and the total -// amount of allocated memory (in case this forces a purge). When memory usage -// reaches the limit, the manager purges the LRU memory. -class BASE_EXPORT_PRIVATE DiscardableMemoryManager { - public: - typedef DiscardableMemoryManagerAllocation Allocation; - - DiscardableMemoryManager(size_t memory_limit, - size_t soft_memory_limit, - TimeDelta hard_memory_limit_expiration_time); - virtual ~DiscardableMemoryManager(); - - // The maximum number of bytes of memory that may be allocated before we force - // a purge. - void SetMemoryLimit(size_t bytes); - - // The number of bytes of memory that may be allocated but unused for the hard - // limit expiration time without getting purged. - void SetSoftMemoryLimit(size_t bytes); - - // Sets the memory usage cutoff time for hard memory limit. - void SetHardMemoryLimitExpirationTime( - TimeDelta hard_memory_limit_expiration_time); - - // This will attempt to reduce memory footprint until within soft memory - // limit. Returns true if there's no need to call this again until allocations - // have been used. - bool ReduceMemoryUsage(); - - // This can be called to attempt to reduce memory footprint until within - // limit for bytes to keep under moderate pressure. - void ReduceMemoryUsageUntilWithinLimit(size_t bytes); - - // Adds the given allocation to the manager's collection. - void Register(Allocation* allocation, size_t bytes); - - // Removes the given allocation from the manager's collection. - void Unregister(Allocation* allocation); - - // Returns false if an error occurred. Otherwise, returns true and sets - // |purged| to indicate whether or not allocation has been purged since last - // use. - bool AcquireLock(Allocation* allocation, bool* purged); - - // Release a previously acquired lock on allocation. This allows the manager - // to purge it if necessary. - void ReleaseLock(Allocation* allocation); - - // Purges all discardable memory. - void PurgeAll(); - - // Returns true if allocation has been added to the manager's collection. This - // should only be used by tests. - bool IsRegisteredForTest(Allocation* allocation) const; - - // Returns true if allocation can be purged. This should only be used by - // tests. - bool CanBePurgedForTest(Allocation* allocation) const; - - // Returns total amount of allocated discardable memory. This should only be - // used by tests. - size_t GetBytesAllocatedForTest() const; - - private: - struct AllocationInfo { - explicit AllocationInfo(size_t bytes) : bytes(bytes), purgable(false) {} - - const size_t bytes; - bool purgable; - TimeTicks last_usage; - }; - typedef HashingMRUCache<Allocation*, AllocationInfo> AllocationMap; - - // Purges memory not used since |hard_memory_limit_expiration_time_| before - // "right now" until usage is less or equal to |soft_memory_limit_|. - // Returns true if total amount of memory is less or equal to soft memory - // limit. - bool PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit(); - - // Purges memory that has not been used since |timestamp| until usage is less - // or equal to |limit|. - // Caller must acquire |lock_| prior to calling this function. - void PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( - TimeTicks timestamp, - size_t limit); - - // Called when a change to |bytes_allocated_| has been made. - void BytesAllocatedChanged(size_t new_bytes_allocated) const; - - // Virtual for tests. - virtual TimeTicks Now() const; - - // Needs to be held when accessing members. - mutable Lock lock_; - - // A MRU cache of all allocated bits of memory. Used for purging. - AllocationMap allocations_; - - // The total amount of allocated memory. - size_t bytes_allocated_; - - // The maximum number of bytes of memory that may be allocated. - size_t memory_limit_; - - // The number of bytes of memory that may be allocated but not used for - // |hard_memory_limit_expiration_time_| amount of time when receiving an idle - // notification. - size_t soft_memory_limit_; - - // Amount of time it takes for an allocation to become affected by - // |soft_memory_limit_|. - TimeDelta hard_memory_limit_expiration_time_; - - DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryManager); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_ diff --git a/base/memory/discardable_memory_manager_unittest.cc b/base/memory/discardable_memory_manager_unittest.cc deleted file mode 100644 index 6717f09..0000000 --- a/base/memory/discardable_memory_manager_unittest.cc +++ /dev/null @@ -1,490 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/memory/discardable_memory_manager.h" - -#include "base/bind.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace base { -namespace { - -class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation { - public: - TestAllocationImpl() : is_allocated_(false), is_locked_(false) {} - ~TestAllocationImpl() override { DCHECK(!is_locked_); } - - // Overridden from internal::DiscardableMemoryManagerAllocation: - bool AllocateAndAcquireLock() override { - bool was_allocated = is_allocated_; - is_allocated_ = true; - DCHECK(!is_locked_); - is_locked_ = true; - return was_allocated; - } - void ReleaseLock() override { - DCHECK(is_locked_); - is_locked_ = false; - } - void Purge() override { - DCHECK(is_allocated_); - is_allocated_ = false; - } - - bool is_locked() const { return is_locked_; } - - private: - bool is_allocated_; - bool is_locked_; -}; - -// Tests can assume that the default limit is at least 1024. Tests that rely on -// something else needs to explicit set the limit. -const size_t kDefaultMemoryLimit = 1024; -const size_t kDefaultSoftMemoryLimit = kDefaultMemoryLimit; - -class TestDiscardableMemoryManagerImpl - : public internal::DiscardableMemoryManager { - public: - TestDiscardableMemoryManagerImpl() - : DiscardableMemoryManager(kDefaultMemoryLimit, - kDefaultSoftMemoryLimit, - TimeDelta::Max()) {} - - void SetNow(TimeTicks now) { now_ = now; } - - private: - // Overriden from internal::DiscardableMemoryManager: - TimeTicks Now() const override { return now_; } - - TimeTicks now_; -}; - -class DiscardableMemoryManagerTestBase { - public: - DiscardableMemoryManagerTestBase() {} - - protected: - enum LockStatus { - LOCK_STATUS_FAILED, - LOCK_STATUS_PURGED, - LOCK_STATUS_SUCCESS - }; - - size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); } - - void SetMemoryLimit(size_t bytes) { manager_.SetMemoryLimit(bytes); } - - void SetSoftMemoryLimit(size_t bytes) { manager_.SetSoftMemoryLimit(bytes); } - - void SetHardMemoryLimitExpirationTime(TimeDelta time) { - manager_.SetHardMemoryLimitExpirationTime(time); - } - - void Register(TestAllocationImpl* allocation, size_t bytes) { - manager_.Register(allocation, bytes); - } - - void Unregister(TestAllocationImpl* allocation) { - manager_.Unregister(allocation); - } - - bool IsRegistered(TestAllocationImpl* allocation) const { - return manager_.IsRegisteredForTest(allocation); - } - - LockStatus Lock(TestAllocationImpl* allocation) { - bool purged; - if (!manager_.AcquireLock(allocation, &purged)) - return LOCK_STATUS_FAILED; - return purged ? LOCK_STATUS_PURGED : LOCK_STATUS_SUCCESS; - } - - void Unlock(TestAllocationImpl* allocation) { - manager_.ReleaseLock(allocation); - } - - LockStatus RegisterAndLock(TestAllocationImpl* allocation, size_t bytes) { - manager_.Register(allocation, bytes); - return Lock(allocation); - } - - bool CanBePurged(TestAllocationImpl* allocation) const { - return manager_.CanBePurgedForTest(allocation); - } - - void SetNow(TimeTicks now) { manager_.SetNow(now); } - - void PurgeAll() { return manager_.PurgeAll(); } - - bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); } - - void ReduceMemoryUsageUntilWithinLimit(size_t bytes) { - manager_.ReduceMemoryUsageUntilWithinLimit(bytes); - } - - private: - TestDiscardableMemoryManagerImpl manager_; -}; - -class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase, - public testing::Test { - public: - DiscardableMemoryManagerTest() {} -}; - -TEST_F(DiscardableMemoryManagerTest, CreateAndLock) { - size_t size = 1024; - TestAllocationImpl allocation; - Register(&allocation, size); - EXPECT_TRUE(IsRegistered(&allocation)); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); - EXPECT_TRUE(allocation.is_locked()); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, CreateZeroSize) { - size_t size = 0; - TestAllocationImpl allocation; - Register(&allocation, size); - EXPECT_TRUE(IsRegistered(&allocation)); - EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&allocation)); - EXPECT_EQ(0u, BytesAllocated()); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, LockAfterUnlock) { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - - // Now unlock so we can lock later. - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - - EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(&allocation)); - EXPECT_FALSE(CanBePurged(&allocation)); - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, LockAfterPurge) { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - - // Now unlock so we can lock later. - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - - // Force the system to purge. - PurgeAll(); - - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); - EXPECT_FALSE(CanBePurged(&allocation)); - - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - - // Now unlock so we can lock later. - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - - // Set max allowed allocation to 1 byte. This will cause the memory to be - // purged. - SetMemoryLimit(1); - - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); - EXPECT_FALSE(CanBePurged(&allocation)); - - Unlock(&allocation); - Unregister(&allocation); -} - -TEST_F(DiscardableMemoryManagerTest, Overflow) { - size_t size = 1024; - { - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - - size_t massive_size = std::numeric_limits<size_t>::max(); - TestAllocationImpl massive_allocation; - Register(&massive_allocation, massive_size); - EXPECT_EQ(LOCK_STATUS_FAILED, Lock(&massive_allocation)); - EXPECT_EQ(1024u, BytesAllocated()); - - Unlock(&allocation); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&massive_allocation)); - Unlock(&massive_allocation); - Unregister(&massive_allocation); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -class PermutationTestData { - public: - PermutationTestData(unsigned d0, unsigned d1, unsigned d2) { - ordering_[0] = d0; - ordering_[1] = d1; - ordering_[2] = d2; - } - - const unsigned* ordering() const { return ordering_; } - - private: - unsigned ordering_[3]; -}; - -class DiscardableMemoryManagerPermutationTest - : public DiscardableMemoryManagerTestBase, - public testing::TestWithParam<PermutationTestData> { - public: - DiscardableMemoryManagerPermutationTest() {} - - protected: - // Use memory in order specified by ordering parameter. - void RegisterAndUseAllocations() { - for (int i = 0; i < 3; ++i) { - RegisterAndLock(&allocation_[i], 1024); - Unlock(&allocation_[i]); - } - for (int i = 0; i < 3; ++i) { - int index = GetParam().ordering()[i]; - EXPECT_NE(LOCK_STATUS_FAILED, Lock(&allocation_[index])); - // Leave i == 0 locked. - if (i > 0) - Unlock(&allocation_[index]); - } - } - - TestAllocationImpl* allocation(unsigned position) { - return &allocation_[GetParam().ordering()[position]]; - } - - void UnlockAndUnregisterAllocations() { - for (int i = 0; i < 3; ++i) { - if (allocation_[i].is_locked()) - Unlock(&allocation_[i]); - Unregister(&allocation_[i]); - } - } - - private: - TestAllocationImpl allocation_[3]; -}; - -// Verify that memory was discarded in the correct order after reducing usage to -// limit. -TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscarded) { - RegisterAndUseAllocations(); - - SetMemoryLimit(2048); - - ReduceMemoryUsageUntilWithinLimit(1024); - - EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); - // 0 should still be locked. - EXPECT_TRUE(allocation(0)->is_locked()); - - UnlockAndUnregisterAllocations(); -} - -// Verify that memory was discarded in the correct order after changing -// memory limit. -TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedExceedLimit) { - RegisterAndUseAllocations(); - - SetMemoryLimit(2048); - - EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); - // 0 should still be locked. - EXPECT_TRUE(allocation(0)->is_locked()); - - UnlockAndUnregisterAllocations(); -} - -// Verify that no more memory than necessary was discarded after changing -// memory limit. -TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedAmount) { - SetMemoryLimit(4096); - - RegisterAndUseAllocations(); - - SetMemoryLimit(2048); - - EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(allocation(2))); - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); - // 0 should still be locked. - EXPECT_TRUE(allocation(0)->is_locked()); - - UnlockAndUnregisterAllocations(); -} - -TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) { - RegisterAndUseAllocations(); - - PurgeAll(); - - for (int i = 0; i < 3; ++i) { - if (i == 0) - EXPECT_TRUE(allocation(i)->is_locked()); - else - EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i))); - } - - UnlockAndUnregisterAllocations(); -} - -INSTANTIATE_TEST_CASE_P(DiscardableMemoryManagerPermutationTests, - DiscardableMemoryManagerPermutationTest, - ::testing::Values(PermutationTestData(0, 1, 2), - PermutationTestData(0, 2, 1), - PermutationTestData(1, 0, 2), - PermutationTestData(1, 2, 0), - PermutationTestData(2, 0, 1), - PermutationTestData(2, 1, 0))); - -TEST_F(DiscardableMemoryManagerTest, NormalDestruction) { - { - size_t size = 1024; - TestAllocationImpl allocation; - Register(&allocation, size); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -TEST_F(DiscardableMemoryManagerTest, DestructionAfterLocked) { - { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - EXPECT_FALSE(CanBePurged(&allocation)); - Unlock(&allocation); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -TEST_F(DiscardableMemoryManagerTest, DestructionAfterPurged) { - { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - EXPECT_EQ(1024u, BytesAllocated()); - Unlock(&allocation); - EXPECT_TRUE(CanBePurged(&allocation)); - SetMemoryLimit(0); - EXPECT_EQ(0u, BytesAllocated()); - Unregister(&allocation); - } - EXPECT_EQ(0u, BytesAllocated()); -} - -TEST_F(DiscardableMemoryManagerTest, ReduceMemoryUsage) { - SetMemoryLimit(3072); - SetSoftMemoryLimit(1024); - SetHardMemoryLimitExpirationTime(TimeDelta::FromInternalValue(1)); - - size_t size = 1024; - TestAllocationImpl allocation[3]; - RegisterAndLock(&allocation[0], size); - RegisterAndLock(&allocation[1], size); - RegisterAndLock(&allocation[2], size); - EXPECT_EQ(3072u, BytesAllocated()); - - // Above soft limit but nothing that can be purged. - EXPECT_FALSE(ReduceMemoryUsage()); - - SetNow(TimeTicks::FromInternalValue(0)); - Unlock(&allocation[0]); - - // Above soft limit but still nothing that can be purged as all unlocked - // allocations are within the hard limit cutoff time. - EXPECT_FALSE(ReduceMemoryUsage()); - - SetNow(TimeTicks::FromInternalValue(1)); - Unlock(&allocation[1]); - - // One unlocked allocation is no longer within the hard limit cutoff time. It - // should be purged and ReduceMemoryUsage() should return false as we're not - // yet within the soft memory limit. - EXPECT_FALSE(ReduceMemoryUsage()); - EXPECT_EQ(2048u, BytesAllocated()); - - // One more unlocked allocation is no longer within the hard limit cutoff - // time. It should be purged and ReduceMemoryUsage() should return true as - // we're now within the soft memory limit. - SetNow(TimeTicks::FromInternalValue(2)); - EXPECT_TRUE(ReduceMemoryUsage()); - EXPECT_EQ(1024u, BytesAllocated()); - - Unlock(&allocation[2]); - - Unregister(&allocation[0]); - Unregister(&allocation[1]); - Unregister(&allocation[2]); -} - -class ThreadedDiscardableMemoryManagerTest - : public DiscardableMemoryManagerTest { - public: - ThreadedDiscardableMemoryManagerTest() - : memory_usage_thread_("memory_usage_thread"), - thread_sync_(true, false) {} - - void SetUp() override { memory_usage_thread_.Start(); } - - void TearDown() override { memory_usage_thread_.Stop(); } - - void UseMemoryHelper() { - size_t size = 1024; - TestAllocationImpl allocation; - RegisterAndLock(&allocation, size); - Unlock(&allocation); - Unregister(&allocation); - } - - void SignalHelper() { thread_sync_.Signal(); } - - Thread memory_usage_thread_; - WaitableEvent thread_sync_; -}; - -TEST_F(ThreadedDiscardableMemoryManagerTest, UseMemoryOnThread) { - memory_usage_thread_.message_loop()->PostTask( - FROM_HERE, - Bind(&ThreadedDiscardableMemoryManagerTest::UseMemoryHelper, - Unretained(this))); - memory_usage_thread_.message_loop()->PostTask( - FROM_HERE, - Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper, - Unretained(this))); - thread_sync_.Wait(); -} - -} // namespace -} // namespace base |