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/containers/hash_tables.h" | 8 #include "base/containers/hash_tables.h" |
9 #include "base/containers/mru_cache.h" | 9 #include "base/containers/mru_cache.h" |
10 #include "base/debug/crash_logging.h" | 10 #include "base/debug/crash_logging.h" |
11 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
13 #include "base/synchronization/lock.h" | 13 #include "base/synchronization/lock.h" |
14 | 14 |
15 namespace base { | 15 namespace base { |
16 namespace internal { | 16 namespace internal { |
17 | 17 |
18 DiscardableMemoryManager::DiscardableMemoryManager( | 18 DiscardableMemoryManager::DiscardableMemoryManager( |
19 size_t memory_limit, | 19 size_t memory_limit, |
20 size_t soft_memory_limit, | 20 size_t soft_memory_limit, |
21 size_t bytes_to_keep_under_moderate_pressure, | |
22 TimeDelta hard_memory_limit_expiration_time) | 21 TimeDelta hard_memory_limit_expiration_time) |
23 : allocations_(AllocationMap::NO_AUTO_EVICT), | 22 : allocations_(AllocationMap::NO_AUTO_EVICT), |
24 bytes_allocated_(0u), | 23 bytes_allocated_(0u), |
25 memory_limit_(memory_limit), | 24 memory_limit_(memory_limit), |
26 soft_memory_limit_(soft_memory_limit), | 25 soft_memory_limit_(soft_memory_limit), |
27 bytes_to_keep_under_moderate_pressure_( | |
28 bytes_to_keep_under_moderate_pressure), | |
29 hard_memory_limit_expiration_time_(hard_memory_limit_expiration_time) { | 26 hard_memory_limit_expiration_time_(hard_memory_limit_expiration_time) { |
30 BytesAllocatedChanged(bytes_allocated_); | 27 BytesAllocatedChanged(bytes_allocated_); |
31 } | 28 } |
32 | 29 |
33 DiscardableMemoryManager::~DiscardableMemoryManager() { | 30 DiscardableMemoryManager::~DiscardableMemoryManager() { |
34 DCHECK(allocations_.empty()); | 31 DCHECK(allocations_.empty()); |
35 DCHECK_EQ(0u, bytes_allocated_); | 32 DCHECK_EQ(0u, bytes_allocated_); |
36 } | 33 } |
37 | 34 |
38 void DiscardableMemoryManager::RegisterMemoryPressureListener() { | |
39 AutoLock lock(lock_); | |
40 DCHECK(base::MessageLoop::current()); | |
41 DCHECK(!memory_pressure_listener_); | |
42 memory_pressure_listener_.reset(new MemoryPressureListener(base::Bind( | |
43 &DiscardableMemoryManager::OnMemoryPressure, Unretained(this)))); | |
44 } | |
45 | |
46 void DiscardableMemoryManager::UnregisterMemoryPressureListener() { | |
47 AutoLock lock(lock_); | |
48 DCHECK(memory_pressure_listener_); | |
49 memory_pressure_listener_.reset(); | |
50 } | |
51 | |
52 void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) { | 35 void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) { |
53 AutoLock lock(lock_); | 36 AutoLock lock(lock_); |
54 memory_limit_ = bytes; | 37 memory_limit_ = bytes; |
55 PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( | 38 PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( |
56 Now(), memory_limit_); | 39 Now(), memory_limit_); |
57 } | 40 } |
58 | 41 |
59 void DiscardableMemoryManager::SetSoftMemoryLimit(size_t bytes) { | 42 void DiscardableMemoryManager::SetSoftMemoryLimit(size_t bytes) { |
60 AutoLock lock(lock_); | 43 AutoLock lock(lock_); |
61 soft_memory_limit_ = bytes; | 44 soft_memory_limit_ = bytes; |
62 } | 45 } |
63 | 46 |
64 void DiscardableMemoryManager::SetBytesToKeepUnderModeratePressure( | |
65 size_t bytes) { | |
66 AutoLock lock(lock_); | |
67 bytes_to_keep_under_moderate_pressure_ = bytes; | |
68 } | |
69 | |
70 void DiscardableMemoryManager::SetHardMemoryLimitExpirationTime( | 47 void DiscardableMemoryManager::SetHardMemoryLimitExpirationTime( |
71 TimeDelta hard_memory_limit_expiration_time) { | 48 TimeDelta hard_memory_limit_expiration_time) { |
72 AutoLock lock(lock_); | 49 AutoLock lock(lock_); |
73 hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time; | 50 hard_memory_limit_expiration_time_ = hard_memory_limit_expiration_time; |
74 } | 51 } |
75 | 52 |
76 bool DiscardableMemoryManager::ReduceMemoryUsage() { | 53 bool DiscardableMemoryManager::ReduceMemoryUsage() { |
77 return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit(); | 54 return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit(); |
78 } | 55 } |
79 | 56 |
| 57 void DiscardableMemoryManager::ReduceMemoryUsageUntilWithinLimit(size_t bytes) { |
| 58 AutoLock lock(lock_); |
| 59 PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(), |
| 60 bytes); |
| 61 } |
| 62 |
80 void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) { | 63 void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) { |
81 AutoLock lock(lock_); | 64 AutoLock lock(lock_); |
82 // A registered memory listener is currently required. This DCHECK can be | |
83 // moved or removed if we decide that it's useful to relax this condition. | |
84 // TODO(reveman): Enable this DCHECK when skia and blink are able to | |
85 // register memory pressure listeners. crbug.com/333907 | |
86 // DCHECK(memory_pressure_listener_); | |
87 DCHECK(allocations_.Peek(allocation) == allocations_.end()); | 65 DCHECK(allocations_.Peek(allocation) == allocations_.end()); |
88 allocations_.Put(allocation, AllocationInfo(bytes)); | 66 allocations_.Put(allocation, AllocationInfo(bytes)); |
89 } | 67 } |
90 | 68 |
91 void DiscardableMemoryManager::Unregister(Allocation* allocation) { | 69 void DiscardableMemoryManager::Unregister(Allocation* allocation) { |
92 AutoLock lock(lock_); | 70 AutoLock lock(lock_); |
93 AllocationMap::iterator it = allocations_.Peek(allocation); | 71 AllocationMap::iterator it = allocations_.Peek(allocation); |
94 DCHECK(it != allocations_.end()); | 72 DCHECK(it != allocations_.end()); |
95 const AllocationInfo& info = it->second; | 73 const AllocationInfo& info = it->second; |
96 | 74 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 AutoLock lock(lock_); | 153 AutoLock lock(lock_); |
176 AllocationMap::const_iterator it = allocations_.Peek(allocation); | 154 AllocationMap::const_iterator it = allocations_.Peek(allocation); |
177 return it != allocations_.end() && it->second.purgable; | 155 return it != allocations_.end() && it->second.purgable; |
178 } | 156 } |
179 | 157 |
180 size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const { | 158 size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const { |
181 AutoLock lock(lock_); | 159 AutoLock lock(lock_); |
182 return bytes_allocated_; | 160 return bytes_allocated_; |
183 } | 161 } |
184 | 162 |
185 void DiscardableMemoryManager::OnMemoryPressure( | |
186 MemoryPressureListener::MemoryPressureLevel pressure_level) { | |
187 switch (pressure_level) { | |
188 case MemoryPressureListener::MEMORY_PRESSURE_MODERATE: | |
189 PurgeUntilWithinBytesToKeepUnderModeratePressure(); | |
190 return; | |
191 case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL: | |
192 PurgeAll(); | |
193 return; | |
194 } | |
195 | |
196 NOTREACHED(); | |
197 } | |
198 | |
199 void | |
200 DiscardableMemoryManager::PurgeUntilWithinBytesToKeepUnderModeratePressure() { | |
201 AutoLock lock(lock_); | |
202 | |
203 PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( | |
204 Now(), bytes_to_keep_under_moderate_pressure_); | |
205 } | |
206 | |
207 bool DiscardableMemoryManager:: | 163 bool DiscardableMemoryManager:: |
208 PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit() { | 164 PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit() { |
209 AutoLock lock(lock_); | 165 AutoLock lock(lock_); |
210 | 166 |
211 PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( | 167 PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired( |
212 Now() - hard_memory_limit_expiration_time_, soft_memory_limit_); | 168 Now() - hard_memory_limit_expiration_time_, soft_memory_limit_); |
213 | 169 |
214 return bytes_allocated_ <= soft_memory_limit_; | 170 return bytes_allocated_ <= soft_memory_limit_; |
215 } | 171 } |
216 | 172 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey, | 210 base::debug::SetCrashKeyValue(kDiscardableMemoryUsageKey, |
255 Uint64ToString(new_bytes_allocated)); | 211 Uint64ToString(new_bytes_allocated)); |
256 } | 212 } |
257 | 213 |
258 TimeTicks DiscardableMemoryManager::Now() const { | 214 TimeTicks DiscardableMemoryManager::Now() const { |
259 return TimeTicks::Now(); | 215 return TimeTicks::Now(); |
260 } | 216 } |
261 | 217 |
262 } // namespace internal | 218 } // namespace internal |
263 } // namespace base | 219 } // namespace base |
OLD | NEW |