| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/discardable_memory_manager.h" | 5 #include "base/memory/discardable_memory_manager.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/run_loop.h" | |
| 9 #include "base/synchronization/waitable_event.h" | 8 #include "base/synchronization/waitable_event.h" |
| 10 #include "base/threading/thread.h" | 9 #include "base/threading/thread.h" |
| 11 #include "testing/gtest/include/gtest/gtest.h" | 10 #include "testing/gtest/include/gtest/gtest.h" |
| 12 | 11 |
| 13 namespace base { | 12 namespace base { |
| 14 namespace { | 13 namespace { |
| 15 | 14 |
| 16 class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation { | 15 class TestAllocationImpl : public internal::DiscardableMemoryManagerAllocation { |
| 17 public: | 16 public: |
| 18 TestAllocationImpl() : is_allocated_(false), is_locked_(false) {} | 17 TestAllocationImpl() : is_allocated_(false), is_locked_(false) {} |
| (...skipping 20 matching lines...) Expand all Loading... |
| 39 | 38 |
| 40 private: | 39 private: |
| 41 bool is_allocated_; | 40 bool is_allocated_; |
| 42 bool is_locked_; | 41 bool is_locked_; |
| 43 }; | 42 }; |
| 44 | 43 |
| 45 // Tests can assume that the default limit is at least 1024. Tests that rely on | 44 // Tests can assume that the default limit is at least 1024. Tests that rely on |
| 46 // something else needs to explicit set the limit. | 45 // something else needs to explicit set the limit. |
| 47 const size_t kDefaultMemoryLimit = 1024; | 46 const size_t kDefaultMemoryLimit = 1024; |
| 48 const size_t kDefaultSoftMemoryLimit = kDefaultMemoryLimit; | 47 const size_t kDefaultSoftMemoryLimit = kDefaultMemoryLimit; |
| 49 const size_t kDefaultBytesToKeepUnderModeratePressure = kDefaultMemoryLimit; | |
| 50 | 48 |
| 51 class TestDiscardableMemoryManagerImpl | 49 class TestDiscardableMemoryManagerImpl |
| 52 : public internal::DiscardableMemoryManager { | 50 : public internal::DiscardableMemoryManager { |
| 53 public: | 51 public: |
| 54 TestDiscardableMemoryManagerImpl() | 52 TestDiscardableMemoryManagerImpl() |
| 55 : DiscardableMemoryManager(kDefaultMemoryLimit, | 53 : DiscardableMemoryManager(kDefaultMemoryLimit, |
| 56 kDefaultSoftMemoryLimit, | 54 kDefaultSoftMemoryLimit, |
| 57 kDefaultBytesToKeepUnderModeratePressure, | |
| 58 TimeDelta::Max()) {} | 55 TimeDelta::Max()) {} |
| 59 | 56 |
| 60 void SetNow(TimeTicks now) { now_ = now; } | 57 void SetNow(TimeTicks now) { now_ = now; } |
| 61 | 58 |
| 62 private: | 59 private: |
| 63 // Overriden from internal::DiscardableMemoryManager: | 60 // Overriden from internal::DiscardableMemoryManager: |
| 64 virtual TimeTicks Now() const OVERRIDE { return now_; } | 61 virtual TimeTicks Now() const OVERRIDE { return now_; } |
| 65 | 62 |
| 66 TimeTicks now_; | 63 TimeTicks now_; |
| 67 }; | 64 }; |
| 68 | 65 |
| 69 class DiscardableMemoryManagerTestBase { | 66 class DiscardableMemoryManagerTestBase { |
| 70 public: | 67 public: |
| 71 DiscardableMemoryManagerTestBase() { | 68 DiscardableMemoryManagerTestBase() {} |
| 72 manager_.RegisterMemoryPressureListener(); | |
| 73 } | |
| 74 | 69 |
| 75 protected: | 70 protected: |
| 76 enum LockStatus { | 71 enum LockStatus { |
| 77 LOCK_STATUS_FAILED, | 72 LOCK_STATUS_FAILED, |
| 78 LOCK_STATUS_PURGED, | 73 LOCK_STATUS_PURGED, |
| 79 LOCK_STATUS_SUCCESS | 74 LOCK_STATUS_SUCCESS |
| 80 }; | 75 }; |
| 81 | 76 |
| 82 size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); } | 77 size_t BytesAllocated() const { return manager_.GetBytesAllocatedForTest(); } |
| 83 | 78 |
| 84 void SetMemoryLimit(size_t bytes) { manager_.SetMemoryLimit(bytes); } | 79 void SetMemoryLimit(size_t bytes) { manager_.SetMemoryLimit(bytes); } |
| 85 | 80 |
| 86 void SetSoftMemoryLimit(size_t bytes) { manager_.SetSoftMemoryLimit(bytes); } | 81 void SetSoftMemoryLimit(size_t bytes) { manager_.SetSoftMemoryLimit(bytes); } |
| 87 | 82 |
| 88 void SetBytesToKeepUnderModeratePressure(size_t bytes) { | |
| 89 manager_.SetBytesToKeepUnderModeratePressure(bytes); | |
| 90 } | |
| 91 | |
| 92 void SetHardMemoryLimitExpirationTime(TimeDelta time) { | 83 void SetHardMemoryLimitExpirationTime(TimeDelta time) { |
| 93 manager_.SetHardMemoryLimitExpirationTime(time); | 84 manager_.SetHardMemoryLimitExpirationTime(time); |
| 94 } | 85 } |
| 95 | 86 |
| 96 void Register(TestAllocationImpl* allocation, size_t bytes) { | 87 void Register(TestAllocationImpl* allocation, size_t bytes) { |
| 97 manager_.Register(allocation, bytes); | 88 manager_.Register(allocation, bytes); |
| 98 } | 89 } |
| 99 | 90 |
| 100 void Unregister(TestAllocationImpl* allocation) { | 91 void Unregister(TestAllocationImpl* allocation) { |
| 101 manager_.Unregister(allocation); | 92 manager_.Unregister(allocation); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 120 manager_.Register(allocation, bytes); | 111 manager_.Register(allocation, bytes); |
| 121 return Lock(allocation); | 112 return Lock(allocation); |
| 122 } | 113 } |
| 123 | 114 |
| 124 bool CanBePurged(TestAllocationImpl* allocation) const { | 115 bool CanBePurged(TestAllocationImpl* allocation) const { |
| 125 return manager_.CanBePurgedForTest(allocation); | 116 return manager_.CanBePurgedForTest(allocation); |
| 126 } | 117 } |
| 127 | 118 |
| 128 void SetNow(TimeTicks now) { manager_.SetNow(now); } | 119 void SetNow(TimeTicks now) { manager_.SetNow(now); } |
| 129 | 120 |
| 121 void PurgeAll() { return manager_.PurgeAll(); } |
| 122 |
| 130 bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); } | 123 bool ReduceMemoryUsage() { return manager_.ReduceMemoryUsage(); } |
| 131 | 124 |
| 125 void ReduceMemoryUsageUntilWithinLimit(size_t bytes) { |
| 126 manager_.ReduceMemoryUsageUntilWithinLimit(bytes); |
| 127 } |
| 128 |
| 132 private: | 129 private: |
| 133 MessageLoopForIO message_loop_; | |
| 134 TestDiscardableMemoryManagerImpl manager_; | 130 TestDiscardableMemoryManagerImpl manager_; |
| 135 }; | 131 }; |
| 136 | 132 |
| 137 class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase, | 133 class DiscardableMemoryManagerTest : public DiscardableMemoryManagerTestBase, |
| 138 public testing::Test { | 134 public testing::Test { |
| 139 public: | 135 public: |
| 140 DiscardableMemoryManagerTest() {} | 136 DiscardableMemoryManagerTest() {} |
| 141 }; | 137 }; |
| 142 | 138 |
| 143 TEST_F(DiscardableMemoryManagerTest, CreateAndLock) { | 139 TEST_F(DiscardableMemoryManagerTest, CreateAndLock) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 TestAllocationImpl allocation; | 181 TestAllocationImpl allocation; |
| 186 RegisterAndLock(&allocation, size); | 182 RegisterAndLock(&allocation, size); |
| 187 EXPECT_EQ(1024u, BytesAllocated()); | 183 EXPECT_EQ(1024u, BytesAllocated()); |
| 188 EXPECT_FALSE(CanBePurged(&allocation)); | 184 EXPECT_FALSE(CanBePurged(&allocation)); |
| 189 | 185 |
| 190 // Now unlock so we can lock later. | 186 // Now unlock so we can lock later. |
| 191 Unlock(&allocation); | 187 Unlock(&allocation); |
| 192 EXPECT_TRUE(CanBePurged(&allocation)); | 188 EXPECT_TRUE(CanBePurged(&allocation)); |
| 193 | 189 |
| 194 // Force the system to purge. | 190 // Force the system to purge. |
| 195 MemoryPressureListener::NotifyMemoryPressure( | 191 PurgeAll(); |
| 196 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); | |
| 197 | |
| 198 // Required because ObserverListThreadSafe notifies via PostTask. | |
| 199 RunLoop().RunUntilIdle(); | |
| 200 | 192 |
| 201 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); | 193 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(&allocation)); |
| 202 EXPECT_FALSE(CanBePurged(&allocation)); | 194 EXPECT_FALSE(CanBePurged(&allocation)); |
| 203 | 195 |
| 204 Unlock(&allocation); | 196 Unlock(&allocation); |
| 205 Unregister(&allocation); | 197 Unregister(&allocation); |
| 206 } | 198 } |
| 207 | 199 |
| 208 TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) { | 200 TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) { |
| 209 size_t size = 1024; | 201 size_t size = 1024; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 294 if (allocation_[i].is_locked()) | 286 if (allocation_[i].is_locked()) |
| 295 Unlock(&allocation_[i]); | 287 Unlock(&allocation_[i]); |
| 296 Unregister(&allocation_[i]); | 288 Unregister(&allocation_[i]); |
| 297 } | 289 } |
| 298 } | 290 } |
| 299 | 291 |
| 300 private: | 292 private: |
| 301 TestAllocationImpl allocation_[3]; | 293 TestAllocationImpl allocation_[3]; |
| 302 }; | 294 }; |
| 303 | 295 |
| 304 // Verify that memory was discarded in the correct order after applying | 296 // Verify that memory was discarded in the correct order after reducing usage to |
| 305 // memory pressure. | 297 // limit. |
| 306 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedModeratePressure) { | 298 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscarded) { |
| 307 RegisterAndUseAllocations(); | 299 RegisterAndUseAllocations(); |
| 308 | 300 |
| 309 SetBytesToKeepUnderModeratePressure(1024); | |
| 310 SetMemoryLimit(2048); | 301 SetMemoryLimit(2048); |
| 311 | 302 |
| 312 MemoryPressureListener::NotifyMemoryPressure( | 303 ReduceMemoryUsageUntilWithinLimit(1024); |
| 313 MemoryPressureListener::MEMORY_PRESSURE_MODERATE); | |
| 314 RunLoop().RunUntilIdle(); | |
| 315 | 304 |
| 316 EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); | 305 EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); |
| 317 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); | 306 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
| 318 // 0 should still be locked. | 307 // 0 should still be locked. |
| 319 EXPECT_TRUE(allocation(0)->is_locked()); | 308 EXPECT_TRUE(allocation(0)->is_locked()); |
| 320 | 309 |
| 321 UnlockAndUnregisterAllocations(); | 310 UnlockAndUnregisterAllocations(); |
| 322 } | 311 } |
| 323 | 312 |
| 324 // Verify that memory was discarded in the correct order after changing | 313 // Verify that memory was discarded in the correct order after changing |
| 325 // memory limit. | 314 // memory limit. |
| 326 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedExceedLimit) { | 315 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedExceedLimit) { |
| 327 RegisterAndUseAllocations(); | 316 RegisterAndUseAllocations(); |
| 328 | 317 |
| 329 SetBytesToKeepUnderModeratePressure(1024); | |
| 330 SetMemoryLimit(2048); | 318 SetMemoryLimit(2048); |
| 331 | 319 |
| 332 EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); | 320 EXPECT_NE(LOCK_STATUS_FAILED, Lock(allocation(2))); |
| 333 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); | 321 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
| 334 // 0 should still be locked. | 322 // 0 should still be locked. |
| 335 EXPECT_TRUE(allocation(0)->is_locked()); | 323 EXPECT_TRUE(allocation(0)->is_locked()); |
| 336 | 324 |
| 337 UnlockAndUnregisterAllocations(); | 325 UnlockAndUnregisterAllocations(); |
| 338 } | 326 } |
| 339 | 327 |
| 340 // Verify that no more memory than necessary was discarded after changing | 328 // Verify that no more memory than necessary was discarded after changing |
| 341 // memory limit. | 329 // memory limit. |
| 342 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedAmount) { | 330 TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedAmount) { |
| 343 SetBytesToKeepUnderModeratePressure(2048); | |
| 344 SetMemoryLimit(4096); | 331 SetMemoryLimit(4096); |
| 345 | 332 |
| 346 RegisterAndUseAllocations(); | 333 RegisterAndUseAllocations(); |
| 347 | 334 |
| 348 SetMemoryLimit(2048); | 335 SetMemoryLimit(2048); |
| 349 | 336 |
| 350 EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(allocation(2))); | 337 EXPECT_EQ(LOCK_STATUS_SUCCESS, Lock(allocation(2))); |
| 351 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); | 338 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(1))); |
| 352 // 0 should still be locked. | 339 // 0 should still be locked. |
| 353 EXPECT_TRUE(allocation(0)->is_locked()); | 340 EXPECT_TRUE(allocation(0)->is_locked()); |
| 354 | 341 |
| 355 UnlockAndUnregisterAllocations(); | 342 UnlockAndUnregisterAllocations(); |
| 356 } | 343 } |
| 357 | 344 |
| 358 TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) { | 345 TEST_P(DiscardableMemoryManagerPermutationTest, PurgeFreesAllUnlocked) { |
| 359 RegisterAndUseAllocations(); | 346 RegisterAndUseAllocations(); |
| 360 | 347 |
| 361 MemoryPressureListener::NotifyMemoryPressure( | 348 PurgeAll(); |
| 362 MemoryPressureListener::MEMORY_PRESSURE_CRITICAL); | |
| 363 RunLoop().RunUntilIdle(); | |
| 364 | 349 |
| 365 for (int i = 0; i < 3; ++i) { | 350 for (int i = 0; i < 3; ++i) { |
| 366 if (i == 0) | 351 if (i == 0) |
| 367 EXPECT_TRUE(allocation(i)->is_locked()); | 352 EXPECT_TRUE(allocation(i)->is_locked()); |
| 368 else | 353 else |
| 369 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i))); | 354 EXPECT_EQ(LOCK_STATUS_PURGED, Lock(allocation(i))); |
| 370 } | 355 } |
| 371 | 356 |
| 372 UnlockAndUnregisterAllocations(); | 357 UnlockAndUnregisterAllocations(); |
| 373 } | 358 } |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 Unretained(this))); | 481 Unretained(this))); |
| 497 memory_usage_thread_.message_loop()->PostTask( | 482 memory_usage_thread_.message_loop()->PostTask( |
| 498 FROM_HERE, | 483 FROM_HERE, |
| 499 Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper, | 484 Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper, |
| 500 Unretained(this))); | 485 Unretained(this))); |
| 501 thread_sync_.Wait(); | 486 thread_sync_.Wait(); |
| 502 } | 487 } |
| 503 | 488 |
| 504 } // namespace | 489 } // namespace |
| 505 } // namespace base | 490 } // namespace base |
| OLD | NEW |