Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(711)

Side by Side Diff: content/common/host_discardable_shared_memory_manager.cc

Issue 1004043002: Re-land: base: Implement browser process support for discardable memory. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: set allocator instance for blink tests Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "content/common/host_discardable_shared_memory_manager.h" 5 #include "content/common/host_discardable_shared_memory_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/debug/crash_logging.h" 10 #include "base/debug/crash_logging.h"
11 #include "base/lazy_instance.h" 11 #include "base/lazy_instance.h"
12 #include "base/numerics/safe_math.h" 12 #include "base/numerics/safe_math.h"
13 #include "base/profiler/scoped_tracker.h" 13 #include "base/profiler/scoped_tracker.h"
14 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_number_conversions.h"
15 #include "base/sys_info.h" 15 #include "base/sys_info.h"
16 #include "base/trace_event/trace_event.h" 16 #include "base/trace_event/trace_event.h"
17 17
18 namespace content { 18 namespace content {
19 namespace { 19 namespace {
20 20
21 class DiscardableMemoryShmemChunkImpl
22 : public base::DiscardableMemoryShmemChunk {
23 public:
24 explicit DiscardableMemoryShmemChunkImpl(
25 scoped_ptr<base::DiscardableSharedMemory> shared_memory)
26 : shared_memory_(shared_memory.Pass()), is_locked_(true) {}
27 ~DiscardableMemoryShmemChunkImpl() override {
28 if (is_locked_)
29 shared_memory_->Unlock(0, 0);
30 shared_memory_->Purge(base::Time::Now());
31 }
32
33 // Overridden from base::DiscardableMemoryShmemChunk:
34 bool Lock() override {
35 DCHECK(!is_locked_);
36
37 if (shared_memory_->Lock(0, 0) != base::DiscardableSharedMemory::SUCCESS)
38 return false;
39
40 is_locked_ = true;
41 return true;
42 }
43 void Unlock() override {
44 DCHECK(is_locked_);
45
46 shared_memory_->Unlock(0, 0);
47 is_locked_ = false;
48 }
49 void* Memory() const override {
50 DCHECK(is_locked_);
51 return shared_memory_->memory();
52 }
53
54 private:
55 scoped_ptr<base::DiscardableSharedMemory> shared_memory_;
56 bool is_locked_;
57
58 DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryShmemChunkImpl);
59 };
60
21 base::LazyInstance<HostDiscardableSharedMemoryManager> 61 base::LazyInstance<HostDiscardableSharedMemoryManager>
22 g_discardable_shared_memory_manager = LAZY_INSTANCE_INITIALIZER; 62 g_discardable_shared_memory_manager = LAZY_INSTANCE_INITIALIZER;
23 63
24 const int64_t kMaxDefaultMemoryLimit = 512 * 1024 * 1024; 64 const int64_t kMaxDefaultMemoryLimit = 512 * 1024 * 1024;
25 65
26 const int kEnforceMemoryPolicyDelayMs = 1000; 66 const int kEnforceMemoryPolicyDelayMs = 1000;
27 67
28 } // namespace 68 } // namespace
29 69
30 HostDiscardableSharedMemoryManager::MemorySegment::MemorySegment( 70 HostDiscardableSharedMemoryManager::MemorySegment::MemorySegment(
(...skipping 23 matching lines...) Expand all
54 } 94 }
55 95
56 HostDiscardableSharedMemoryManager* 96 HostDiscardableSharedMemoryManager*
57 HostDiscardableSharedMemoryManager::current() { 97 HostDiscardableSharedMemoryManager::current() {
58 return g_discardable_shared_memory_manager.Pointer(); 98 return g_discardable_shared_memory_manager.Pointer();
59 } 99 }
60 100
61 scoped_ptr<base::DiscardableMemoryShmemChunk> 101 scoped_ptr<base::DiscardableMemoryShmemChunk>
62 HostDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory( 102 HostDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
63 size_t size) { 103 size_t size) {
64 // TODO(reveman): Need to implement this for discardable memory support in 104 // Note: Use DiscardableSharedMemoryHeap for in-process allocation
65 // the browser process. 105 // of discardable memory if the cost of each allocation is too high.
66 NOTIMPLEMENTED(); 106 base::SharedMemoryHandle handle;
67 return nullptr; 107 AllocateLockedDiscardableSharedMemory(base::GetCurrentProcessHandle(), size,
108 &handle);
109 CHECK(base::SharedMemory::IsHandleValid(handle));
110 scoped_ptr<base::DiscardableSharedMemory> memory(
111 new base::DiscardableSharedMemory(handle));
112 CHECK(memory->Map(size));
113 return make_scoped_ptr(new DiscardableMemoryShmemChunkImpl(memory.Pass()));
68 } 114 }
69 115
70 void HostDiscardableSharedMemoryManager:: 116 void HostDiscardableSharedMemoryManager::
71 AllocateLockedDiscardableSharedMemoryForChild( 117 AllocateLockedDiscardableSharedMemoryForChild(
72 base::ProcessHandle process_handle, 118 base::ProcessHandle process_handle,
73 size_t size, 119 size_t size,
74 base::SharedMemoryHandle* shared_memory_handle) { 120 base::SharedMemoryHandle* shared_memory_handle) {
121 AllocateLockedDiscardableSharedMemory(process_handle, size,
122 shared_memory_handle);
123 }
124
125 void HostDiscardableSharedMemoryManager::ProcessRemoved(
126 base::ProcessHandle process_handle) {
127 base::AutoLock lock(lock_);
128
129 size_t bytes_allocated_before_purging = bytes_allocated_;
130 for (auto& segment : segments_) {
131 // Skip segments that belong to a different process.
132 if (segment.process_handle != process_handle)
133 continue;
134
135 size_t size = segment.memory->mapped_size();
136 DCHECK_GE(bytes_allocated_, size);
137
138 // This will unmap the memory segment and drop our reference. The result
139 // is that the memory will be released to the OS if the child process is
140 // no longer referencing it.
141 // Note: We intentionally leave the segment in the vector to avoid
142 // reconstructing the heap. The element will be removed from the heap
143 // when its last usage time is older than all other segments.
144 segment.memory->Close();
145 bytes_allocated_ -= size;
146 }
147
148 if (bytes_allocated_ != bytes_allocated_before_purging)
149 BytesAllocatedChanged(bytes_allocated_);
150 }
151
152 void HostDiscardableSharedMemoryManager::SetMemoryLimit(size_t limit) {
153 base::AutoLock lock(lock_);
154
155 memory_limit_ = limit;
156 ReduceMemoryUsageUntilWithinMemoryLimit();
157 }
158
159 void HostDiscardableSharedMemoryManager::EnforceMemoryPolicy() {
160 base::AutoLock lock(lock_);
161
162 enforce_memory_policy_pending_ = false;
163 ReduceMemoryUsageUntilWithinMemoryLimit();
164 }
165
166 void HostDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
167 base::ProcessHandle process_handle,
168 size_t size,
169 base::SharedMemoryHandle* shared_memory_handle) {
75 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405 170 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
76 // is fixed. 171 // is fixed.
77 tracked_objects::ScopedTracker tracking_profile1( 172 tracked_objects::ScopedTracker tracking_profile1(
78 FROM_HERE_WITH_EXPLICIT_FUNCTION( 173 FROM_HERE_WITH_EXPLICIT_FUNCTION(
79 "466405 AllocateLockedDiscardableSharedMemoryForChild::Start")); 174 "466405 AllocateLockedDiscardableSharedMemory::Start"));
80 base::AutoLock lock(lock_); 175 base::AutoLock lock(lock_);
81 176
82 // Memory usage must be reduced to prevent the addition of |size| from 177 // Memory usage must be reduced to prevent the addition of |size| from
83 // taking usage above the limit. Usage should be reduced to 0 in cases 178 // taking usage above the limit. Usage should be reduced to 0 in cases
84 // where |size| is greater than the limit. 179 // where |size| is greater than the limit.
85 size_t limit = 0; 180 size_t limit = 0;
86 // Note: the actual mapped size can be larger than requested and cause 181 // Note: the actual mapped size can be larger than requested and cause
87 // |bytes_allocated_| to temporarily be larger than |memory_limit_|. The 182 // |bytes_allocated_| to temporarily be larger than |memory_limit_|. The
88 // error is minimized by incrementing |bytes_allocated_| with the actual 183 // error is minimized by incrementing |bytes_allocated_| with the actual
89 // mapped size rather than |size| below. 184 // mapped size rather than |size| below.
90 if (size < memory_limit_) 185 if (size < memory_limit_)
91 limit = memory_limit_ - size; 186 limit = memory_limit_ - size;
92 187
93 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405 188 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
94 // is fixed. 189 // is fixed.
95 tracked_objects::ScopedTracker tracking_profile2( 190 tracked_objects::ScopedTracker tracking_profile2(
96 FROM_HERE_WITH_EXPLICIT_FUNCTION( 191 FROM_HERE_WITH_EXPLICIT_FUNCTION(
97 "466405 " 192 "466405 AllocateLockedDiscardableSharedMemory::ReduceMemoryUsage"));
98 "AllocateLockedDiscardableSharedMemoryForChild::ReduceMemoryUsage"));
99 if (bytes_allocated_ > limit) 193 if (bytes_allocated_ > limit)
100 ReduceMemoryUsageUntilWithinLimit(limit); 194 ReduceMemoryUsageUntilWithinLimit(limit);
101 195
102 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405 196 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
103 // is fixed. 197 // is fixed.
104 tracked_objects::ScopedTracker tracking_profile3( 198 tracked_objects::ScopedTracker tracking_profile3(
105 FROM_HERE_WITH_EXPLICIT_FUNCTION( 199 FROM_HERE_WITH_EXPLICIT_FUNCTION(
106 "466405 AllocateLockedDiscardableSharedMemoryForChild::NewMemory")); 200 "466405 AllocateLockedDiscardableSharedMemory::NewMemory"));
107 linked_ptr<base::DiscardableSharedMemory> memory( 201 linked_ptr<base::DiscardableSharedMemory> memory(
108 new base::DiscardableSharedMemory); 202 new base::DiscardableSharedMemory);
109 if (!memory->CreateAndMap(size)) { 203 if (!memory->CreateAndMap(size)) {
110 *shared_memory_handle = base::SharedMemory::NULLHandle(); 204 *shared_memory_handle = base::SharedMemory::NULLHandle();
111 return; 205 return;
112 } 206 }
113 207
114 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405 208 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
115 // is fixed. 209 // is fixed.
116 tracked_objects::ScopedTracker tracking_profile4( 210 tracked_objects::ScopedTracker tracking_profile4(
117 FROM_HERE_WITH_EXPLICIT_FUNCTION( 211 FROM_HERE_WITH_EXPLICIT_FUNCTION(
118 "466405 " 212 "466405 AllocateLockedDiscardableSharedMemory::ShareToProcess"));
119 "AllocateLockedDiscardableSharedMemoryForChild::ShareToProcess"));
120 if (!memory->ShareToProcess(process_handle, shared_memory_handle)) { 213 if (!memory->ShareToProcess(process_handle, shared_memory_handle)) {
121 LOG(ERROR) << "Cannot share discardable memory segment"; 214 LOG(ERROR) << "Cannot share discardable memory segment";
122 *shared_memory_handle = base::SharedMemory::NULLHandle(); 215 *shared_memory_handle = base::SharedMemory::NULLHandle();
123 return; 216 return;
124 } 217 }
125 218
126 base::CheckedNumeric<size_t> checked_bytes_allocated = bytes_allocated_; 219 base::CheckedNumeric<size_t> checked_bytes_allocated = bytes_allocated_;
127 checked_bytes_allocated += memory->mapped_size(); 220 checked_bytes_allocated += memory->mapped_size();
128 if (!checked_bytes_allocated.IsValid()) { 221 if (!checked_bytes_allocated.IsValid()) {
129 *shared_memory_handle = base::SharedMemory::NULLHandle(); 222 *shared_memory_handle = base::SharedMemory::NULLHandle();
130 return; 223 return;
131 } 224 }
132 225
133 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405 226 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
134 // is fixed. 227 // is fixed.
135 tracked_objects::ScopedTracker tracking_profile5( 228 tracked_objects::ScopedTracker tracking_profile5(
136 FROM_HERE_WITH_EXPLICIT_FUNCTION( 229 FROM_HERE_WITH_EXPLICIT_FUNCTION(
137 "466405 " 230 "466405 "
138 "AllocateLockedDiscardableSharedMemoryForChild::" 231 "AllocateLockedDiscardableSharedMemory::BytesAllocatedChanged"));
139 "BytesAllocatedChanged"));
140 bytes_allocated_ = checked_bytes_allocated.ValueOrDie(); 232 bytes_allocated_ = checked_bytes_allocated.ValueOrDie();
141 BytesAllocatedChanged(bytes_allocated_); 233 BytesAllocatedChanged(bytes_allocated_);
142 234
143 segments_.push_back(MemorySegment(memory, process_handle)); 235 segments_.push_back(MemorySegment(memory, process_handle));
144 std::push_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime); 236 std::push_heap(segments_.begin(), segments_.end(), CompareMemoryUsageTime);
145 237
146 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405 238 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466405
147 // is fixed. 239 // is fixed.
148 tracked_objects::ScopedTracker tracking_profile6( 240 tracked_objects::ScopedTracker tracking_profile6(
149 FROM_HERE_WITH_EXPLICIT_FUNCTION( 241 FROM_HERE_WITH_EXPLICIT_FUNCTION(
150 "466405 " 242 "466405 "
151 "AllocateLockedDiscardableSharedMemoryForChild::" 243 "AllocateLockedDiscardableSharedMemory::"
152 "ScheduleEnforceMemoryPolicy")); 244 "ScheduleEnforceMemoryPolicy"));
153 if (bytes_allocated_ > memory_limit_) 245 if (bytes_allocated_ > memory_limit_)
154 ScheduleEnforceMemoryPolicy(); 246 ScheduleEnforceMemoryPolicy();
155 } 247 }
156 248
157 void HostDiscardableSharedMemoryManager::ProcessRemoved(
158 base::ProcessHandle process_handle) {
159 base::AutoLock lock(lock_);
160
161 size_t bytes_allocated_before_purging = bytes_allocated_;
162 for (auto& segment : segments_) {
163 // Skip segments that belong to a different process.
164 if (segment.process_handle != process_handle)
165 continue;
166
167 size_t size = segment.memory->mapped_size();
168 DCHECK_GE(bytes_allocated_, size);
169
170 // This will unmap the memory segment and drop our reference. The result
171 // is that the memory will be released to the OS if the child process is
172 // no longer referencing it.
173 // Note: We intentionally leave the segment in the vector to avoid
174 // reconstructing the heap. The element will be removed from the heap
175 // when its last usage time is older than all other segments.
176 segment.memory->Close();
177 bytes_allocated_ -= size;
178 }
179
180 if (bytes_allocated_ != bytes_allocated_before_purging)
181 BytesAllocatedChanged(bytes_allocated_);
182 }
183
184 void HostDiscardableSharedMemoryManager::SetMemoryLimit(size_t limit) {
185 base::AutoLock lock(lock_);
186
187 memory_limit_ = limit;
188 ReduceMemoryUsageUntilWithinMemoryLimit();
189 }
190
191 void HostDiscardableSharedMemoryManager::EnforceMemoryPolicy() {
192 base::AutoLock lock(lock_);
193
194 enforce_memory_policy_pending_ = false;
195 ReduceMemoryUsageUntilWithinMemoryLimit();
196 }
197
198 void HostDiscardableSharedMemoryManager::OnMemoryPressure( 249 void HostDiscardableSharedMemoryManager::OnMemoryPressure(
199 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { 250 base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
200 base::AutoLock lock(lock_); 251 base::AutoLock lock(lock_);
201 252
202 switch (memory_pressure_level) { 253 switch (memory_pressure_level) {
203 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: 254 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
204 break; 255 break;
205 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: 256 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
206 // Purge memory until usage is within half of |memory_limit_|. 257 // Purge memory until usage is within half of |memory_limit_|.
207 ReduceMemoryUsageUntilWithinLimit(memory_limit_ / 2); 258 ReduceMemoryUsageUntilWithinLimit(memory_limit_ / 2);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 343
293 enforce_memory_policy_pending_ = true; 344 enforce_memory_policy_pending_ = true;
294 base::MessageLoop::current()->PostDelayedTask( 345 base::MessageLoop::current()->PostDelayedTask(
295 FROM_HERE, 346 FROM_HERE,
296 base::Bind(&HostDiscardableSharedMemoryManager::EnforceMemoryPolicy, 347 base::Bind(&HostDiscardableSharedMemoryManager::EnforceMemoryPolicy,
297 weak_ptr_factory_.GetWeakPtr()), 348 weak_ptr_factory_.GetWeakPtr()),
298 base::TimeDelta::FromMilliseconds(kEnforceMemoryPolicyDelayMs)); 349 base::TimeDelta::FromMilliseconds(kEnforceMemoryPolicyDelayMs));
299 } 350 }
300 351
301 } // namespace content 352 } // namespace content
OLDNEW
« no previous file with comments | « content/common/host_discardable_shared_memory_manager.h ('k') | content/renderer/render_thread_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698