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

Side by Side Diff: content/browser/memory/memory_coordinator_impl.cc

Issue 2718963002: Drop the global memory state from memory coordinator (Closed)
Patch Set: tweak Created 3 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 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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/browser/memory/memory_coordinator_impl.h" 5 #include "content/browser/memory/memory_coordinator_impl.h"
6 6
7 #include "base/memory/memory_coordinator_client_registry.h" 7 #include "base/memory/memory_coordinator_client_registry.h"
8 #include "base/memory/ptr_util.h" 8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/histogram_macros.h" 9 #include "base/metrics/histogram_macros.h"
10 #include "base/process/process_handle.h" 10 #include "base/process/process_handle.h"
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 } 159 }
160 160
161 // static 161 // static
162 MemoryCoordinatorImpl* MemoryCoordinatorImpl::GetInstance() { 162 MemoryCoordinatorImpl* MemoryCoordinatorImpl::GetInstance() {
163 if (!base::FeatureList::IsEnabled(features::kMemoryCoordinator)) 163 if (!base::FeatureList::IsEnabled(features::kMemoryCoordinator))
164 return nullptr; 164 return nullptr;
165 return base::Singleton<MemoryCoordinatorImpl, 165 return base::Singleton<MemoryCoordinatorImpl,
166 MemoryCoordinatorImplSingletonTraits>::get(); 166 MemoryCoordinatorImplSingletonTraits>::get();
167 } 167 }
168 168
169 const int kDefaultMinimumTransitionPeriodSeconds = 30;
170
169 MemoryCoordinatorImpl::MemoryCoordinatorImpl( 171 MemoryCoordinatorImpl::MemoryCoordinatorImpl(
170 scoped_refptr<base::SingleThreadTaskRunner> task_runner, 172 scoped_refptr<base::SingleThreadTaskRunner> task_runner,
171 std::unique_ptr<MemoryMonitor> memory_monitor) 173 std::unique_ptr<MemoryMonitor> memory_monitor)
172 : delegate_(GetContentClient()->browser()->GetMemoryCoordinatorDelegate()), 174 : delegate_(GetContentClient()->browser()->GetMemoryCoordinatorDelegate()),
173 memory_monitor_(std::move(memory_monitor)), 175 memory_monitor_(std::move(memory_monitor)),
174 state_updater_(base::MakeUnique<MemoryStateUpdater>(this, task_runner)) { 176 state_updater_(base::MakeUnique<MemoryStateUpdater>(this, task_runner)),
177 minimum_state_transition_period_(base::TimeDelta::FromSeconds(
178 kDefaultMinimumTransitionPeriodSeconds)) {
175 DCHECK(memory_monitor_.get()); 179 DCHECK(memory_monitor_.get());
176 base::MemoryCoordinatorProxy::SetMemoryCoordinator(this); 180 base::MemoryCoordinatorProxy::SetMemoryCoordinator(this);
177 } 181 }
178 182
179 MemoryCoordinatorImpl::~MemoryCoordinatorImpl() {} 183 MemoryCoordinatorImpl::~MemoryCoordinatorImpl() {}
180 184
181 void MemoryCoordinatorImpl::Start() { 185 void MemoryCoordinatorImpl::Start() {
182 DCHECK(CalledOnValidThread()); 186 DCHECK(CalledOnValidThread());
183 DCHECK(last_state_change_.is_null()); 187 DCHECK(last_state_change_.is_null());
184 188
185 notification_registrar_.Add( 189 notification_registrar_.Add(
186 this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED, 190 this, NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED,
187 NotificationService::AllBrowserContextsAndSources()); 191 NotificationService::AllBrowserContextsAndSources());
188 last_state_change_ = base::TimeTicks::Now(); 192 last_state_change_ = base::TimeTicks::Now();
189 state_updater_->ScheduleUpdateState(base::TimeDelta()); 193 state_updater_->ScheduleUpdateCondition(base::TimeDelta());
190 } 194 }
191 195
192 void MemoryCoordinatorImpl::CreateHandle( 196 void MemoryCoordinatorImpl::CreateHandle(
193 int render_process_id, 197 int render_process_id,
194 mojom::MemoryCoordinatorHandleRequest request) { 198 mojom::MemoryCoordinatorHandleRequest request) {
195 std::unique_ptr<MemoryCoordinatorHandleImpl> handle( 199 std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
196 new MemoryCoordinatorHandleImpl(std::move(request), this, 200 new MemoryCoordinatorHandleImpl(std::move(request), this,
197 render_process_id)); 201 render_process_id));
198 handle->binding().set_connection_error_handler( 202 handle->binding().set_connection_error_handler(
199 base::Bind(&MemoryCoordinatorImpl::OnConnectionError, 203 base::Bind(&MemoryCoordinatorImpl::OnConnectionError,
200 base::Unretained(this), render_process_id)); 204 base::Unretained(this), render_process_id));
201 CreateChildInfoMapEntry(render_process_id, std::move(handle)); 205 CreateChildInfoMapEntry(render_process_id, std::move(handle));
202 } 206 }
203 207
204 bool MemoryCoordinatorImpl::SetChildMemoryState(int render_process_id, 208 bool MemoryCoordinatorImpl::SetChildMemoryState(int render_process_id,
205 MemoryState memory_state) { 209 MemoryState memory_state) {
206 // Can't set an invalid memory state. 210 // Can't set an invalid memory state.
207 if (memory_state == MemoryState::UNKNOWN) 211 if (memory_state == MemoryState::UNKNOWN)
208 return false; 212 return false;
209 213
210 // Can't send a message to a child that doesn't exist. 214 // Can't send a message to a child that doesn't exist.
211 auto iter = children_.find(render_process_id); 215 auto iter = children_.find(render_process_id);
212 if (iter == children_.end()) 216 if (iter == children_.end())
213 return false; 217 return false;
214 218
215 // Can't send a message to a child that isn't bound. 219 // Can't send a message to a child that isn't bound.
216 if (!iter->second.handle->child().is_bound()) 220 if (!iter->second.handle->child().is_bound())
217 return false; 221 return false;
218 222
219 memory_state = OverrideGlobalState(memory_state, iter->second); 223 memory_state = OverrideState(memory_state, iter->second);
220 224
221 // A nop doesn't need to be sent, but is considered successful. 225 // A nop doesn't need to be sent, but is considered successful.
222 if (iter->second.memory_state == memory_state) 226 if (iter->second.memory_state == memory_state)
223 return true; 227 return true;
224 228
225 // Can't suspend the given renderer. 229 // Can't suspend the given renderer.
226 if (memory_state == MemoryState::SUSPENDED && 230 if (memory_state == MemoryState::SUSPENDED &&
227 !CanSuspendRenderer(render_process_id)) 231 !CanSuspendRenderer(render_process_id))
228 return false; 232 return false;
229 233
234 base::TimeTicks now = base::TimeTicks::Now();
235 // State should remain unchanged for a certain period of time.
236 if (now - iter->second.last_state_change < minimum_state_transition_period_)
237 return false;
238
230 // Update the internal state and send the message. 239 // Update the internal state and send the message.
231 iter->second.memory_state = memory_state; 240 iter->second.memory_state = memory_state;
241 iter->second.last_state_change = now;
232 iter->second.handle->child()->OnStateChange(ToMojomMemoryState(memory_state)); 242 iter->second.handle->child()->OnStateChange(ToMojomMemoryState(memory_state));
233 return true; 243 return true;
234 } 244 }
235 245
236 base::MemoryState MemoryCoordinatorImpl::GetChildMemoryState( 246 base::MemoryState MemoryCoordinatorImpl::GetChildMemoryState(
237 int render_process_id) const { 247 int render_process_id) const {
238 auto iter = children_.find(render_process_id); 248 auto iter = children_.find(render_process_id);
239 if (iter == children_.end()) 249 if (iter == children_.end())
240 return base::MemoryState::UNKNOWN; 250 return base::MemoryState::UNKNOWN;
241 return iter->second.memory_state; 251 return iter->second.memory_state;
242 } 252 }
243 253
244 void MemoryCoordinatorImpl::RecordMemoryPressure( 254 void MemoryCoordinatorImpl::RecordMemoryPressure(
245 base::MemoryPressureMonitor::MemoryPressureLevel level) { 255 base::MemoryPressureMonitor::MemoryPressureLevel level) {
246 DCHECK(GetGlobalMemoryState() != base::MemoryState::UNKNOWN); 256 // TODO(bashi): Update metrics.
247 int state = static_cast<int>(GetGlobalMemoryState()); 257 int condition = static_cast<int>(GetMemoryCondtion());
248 switch (level) { 258 switch (level) {
249 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: 259 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
250 UMA_HISTOGRAM_ENUMERATION( 260 UMA_HISTOGRAM_ENUMERATION(
251 "Memory.Coordinator.StateOnModerateNotificationReceived", 261 "Memory.Coordinator.StateOnModerateNotificationReceived", condition,
252 state, base::kMemoryStateMax); 262 base::kMemoryStateMax);
253 break; 263 break;
254 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: 264 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
255 UMA_HISTOGRAM_ENUMERATION( 265 UMA_HISTOGRAM_ENUMERATION(
256 "Memory.Coordinator.StateOnCriticalNotificationReceived", 266 "Memory.Coordinator.StateOnCriticalNotificationReceived", condition,
257 state, base::kMemoryStateMax); 267 base::kMemoryStateMax);
258 break; 268 break;
259 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: 269 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
260 NOTREACHED(); 270 NOTREACHED();
261 } 271 }
262 } 272 }
263 273
264 base::MemoryState MemoryCoordinatorImpl::GetGlobalMemoryState() const { 274 base::MemoryState MemoryCoordinatorImpl::GetCurrentMemoryState() const {
265 return current_state_; 275 return current_state_;
266 } 276 }
267 277
268 base::MemoryState MemoryCoordinatorImpl::GetCurrentMemoryState() const {
269 // SUSPENDED state may not make sense to the browser process. Use THROTTLED
270 // instead when the global state is SUSPENDED.
271 // TODO(bashi): Maybe worth considering another state for the browser.
272 return current_state_ == MemoryState::SUSPENDED ? MemoryState::THROTTLED
273 : current_state_;
274 }
275
276 void MemoryCoordinatorImpl::SetCurrentMemoryStateForTesting( 278 void MemoryCoordinatorImpl::SetCurrentMemoryStateForTesting(
277 base::MemoryState memory_state) { 279 base::MemoryState memory_state) {
278 // This changes the current state temporariy for testing. The state will be 280 current_state_ = memory_state;
279 // updated 1 minute later.
280 ForceSetGlobalState(memory_state, base::TimeDelta::FromMinutes(1));
281 } 281 }
282 282
283 void MemoryCoordinatorImpl::ForceSetGlobalState(base::MemoryState new_state, 283 void MemoryCoordinatorImpl::ForceSetMemoryCondition(MemoryCondition condition,
284 base::TimeDelta duration) { 284 base::TimeDelta duration) {
285 DCHECK(new_state != MemoryState::UNKNOWN); 285 UpdateConditionIfNeeded(condition);
286 ChangeStateIfNeeded(current_state_, new_state); 286 state_updater_->ScheduleUpdateCondition(duration);
287 state_updater_->ScheduleUpdateState(duration);
288 } 287 }
289 288
290 void MemoryCoordinatorImpl::Observe(int type, 289 void MemoryCoordinatorImpl::Observe(int type,
291 const NotificationSource& source, 290 const NotificationSource& source,
292 const NotificationDetails& details) { 291 const NotificationDetails& details) {
bashi 2017/02/27 06:53:58 FYI: This is called when a user switches tabs.
293 DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED); 292 DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED);
294 RenderWidgetHost* render_widget_host = Source<RenderWidgetHost>(source).ptr(); 293 RenderWidgetHost* render_widget_host = Source<RenderWidgetHost>(source).ptr();
295 RenderProcessHost* process = render_widget_host->GetProcess(); 294 RenderProcessHost* process = render_widget_host->GetProcess();
296 if (!process) 295 if (!process)
297 return; 296 return;
298 auto iter = children().find(process->GetID()); 297 auto iter = children().find(process->GetID());
299 if (iter == children().end()) 298 if (iter == children().end())
300 return; 299 return;
301 iter->second.is_visible = *Details<bool>(details).ptr(); 300 iter->second.is_visible = *Details<bool>(details).ptr();
302 auto new_state = GetGlobalMemoryState(); 301 // TODO(bashi): Tentative.
302 MemoryState new_state = MemoryState::NORMAL;
303 if (!iter->second.is_visible &&
304 GetMemoryCondtion() != MemoryCondition::NORMAL)
305 new_state = MemoryState::THROTTLED;
303 SetChildMemoryState(iter->first, new_state); 306 SetChildMemoryState(iter->first, new_state);
bashi 2017/02/27 06:53:58 This basically means: Foregrounded renderers: cha
304 } 307 }
305 308
306 base::MemoryState MemoryCoordinatorImpl::GetStateForProcess( 309 base::MemoryState MemoryCoordinatorImpl::GetStateForProcess(
307 base::ProcessHandle handle) { 310 base::ProcessHandle handle) {
308 DCHECK(CalledOnValidThread()); 311 DCHECK(CalledOnValidThread());
309 if (handle == base::kNullProcessHandle) 312 if (handle == base::kNullProcessHandle)
310 return MemoryState::UNKNOWN; 313 return MemoryState::UNKNOWN;
311 if (handle == base::GetCurrentProcessHandle()) 314 if (handle == base::GetCurrentProcessHandle())
312 return GetCurrentMemoryState(); 315 return current_state_;
313 316
314 for (auto& iter : children()) { 317 for (auto& iter : children()) {
315 auto* render_process_host = GetRenderProcessHost(iter.first); 318 auto* render_process_host = GetRenderProcessHost(iter.first);
316 if (render_process_host && render_process_host->GetHandle() == handle) 319 if (render_process_host && render_process_host->GetHandle() == handle)
317 return iter.second.memory_state; 320 return iter.second.memory_state;
318 } 321 }
319 return MemoryState::UNKNOWN; 322 return MemoryState::UNKNOWN;
320 } 323 }
321 324
322 bool MemoryCoordinatorImpl::ChangeStateIfNeeded(base::MemoryState prev_state, 325 const char* MemoryConditionToString(MemoryCondition condition) {
323 base::MemoryState next_state) { 326 switch (condition) {
327 case MemoryCondition::NORMAL:
328 return "normal";
329 case MemoryCondition::WARNING:
330 return "warning";
331 case MemoryCondition::CRITICAL:
332 return "critical";
333 }
334 }
335
336 void MemoryCoordinatorImpl::UpdateConditionIfNeeded(
337 MemoryCondition next_condition) {
324 DCHECK(CalledOnValidThread()); 338 DCHECK(CalledOnValidThread());
325 if (prev_state == next_state) 339 if (memory_condition_ == next_condition)
326 return false; 340 return;
327 341
328 base::TimeTicks prev_last_state_change = last_state_change_; 342 MemoryCondition prev_condition = memory_condition_;
329 last_state_change_ = base::TimeTicks::Now(); 343 memory_condition_ = next_condition;
330 current_state_ = next_state;
331 344
332 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("memory-infra"), 345 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("memory-infra"),
333 "MemoryCoordinatorImpl::ChangeStateIfNeeded", "prev", 346 "MemoryCoordinatorImpl::UpdateConditionIfNeeded", "prev",
334 MemoryStateToString(prev_state), "next", 347 MemoryConditionToString(prev_condition), "next",
335 MemoryStateToString(next_state)); 348 MemoryConditionToString(next_condition));
336 RecordStateChange(prev_state, next_state, 349
bashi 2017/02/27 06:53:58 Most of UMAs recorded here weren't helpful. We wil
337 last_state_change_ - prev_last_state_change); 350 // TODO(bashi): Record some metrics.
338 NotifyStateToClients(); 351
339 NotifyStateToChildren(); 352 // TODO(bashi): Below actions are tentative. We might want to prioritize
340 return true; 353 // processes and handle them one-by-one.
bashi 2017/02/27 06:53:58 I think we need to discuss what we should do here.
354 if (next_condition == MemoryCondition::NORMAL) {
355 NotifyStateToChildren(MemoryState::NORMAL);
356 UpdateCurrentMemoryState(MemoryState::NORMAL);
357 }
358 if (prev_condition == MemoryCondition::NORMAL &&
359 next_condition == MemoryCondition::WARNING) {
360 NotifyStateToChildren(MemoryState::THROTTLED);
361 // Idea: Purge memory from background processes.
362 }
363 if (prev_condition != MemoryCondition::CRITICAL &&
364 next_condition == MemoryCondition::CRITICAL) {
365 UpdateCurrentMemoryState(MemoryState::THROTTLED);
366 // Idea: Throttle memory allocation in foreground renderers.
367 // Idea: Start discarding tabs.
368 }
369 }
370
371 void MemoryCoordinatorImpl::UpdateCurrentMemoryState(
372 base::MemoryState memory_state) {
373 base::TimeTicks now = base::TimeTicks::Now();
374 if (now - last_state_change_ < minimum_state_transition_period_)
375 return;
376 last_state_change_ = now;
377 current_state_ = memory_state;
378 NotifyStateToClients(memory_state);
341 } 379 }
342 380
343 void MemoryCoordinatorImpl::DiscardTab() { 381 void MemoryCoordinatorImpl::DiscardTab() {
344 if (delegate_) 382 if (delegate_)
345 delegate_->DiscardTab(); 383 delegate_->DiscardTab();
346 } 384 }
347 385
348 RenderProcessHost* MemoryCoordinatorImpl::GetRenderProcessHost( 386 RenderProcessHost* MemoryCoordinatorImpl::GetRenderProcessHost(
349 int render_process_id) { 387 int render_process_id) {
350 return RenderProcessHost::FromID(render_process_id); 388 return RenderProcessHost::FromID(render_process_id);
(...skipping 27 matching lines...) Expand all
378 if (render_process_host->GetWorkerRefCount() > 0) 416 if (render_process_host->GetWorkerRefCount() > 0)
379 return false; 417 return false;
380 // Assumes that we can't suspend renderers if there is no delegate. 418 // Assumes that we can't suspend renderers if there is no delegate.
381 if (!delegate_) 419 if (!delegate_)
382 return false; 420 return false;
383 return delegate_->CanSuspendBackgroundedRenderer(render_process_id); 421 return delegate_->CanSuspendBackgroundedRenderer(render_process_id);
384 } 422 }
385 423
386 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) { 424 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) {
387 // Populate the global state as an initial state of a newly created process. 425 // Populate the global state as an initial state of a newly created process.
388 auto new_state = GetGlobalMemoryState(); 426 auto new_state = GetMemoryCondtion() == MemoryCondition::CRITICAL
427 ? MemoryState::THROTTLED
428 : MemoryState::NORMAL;
389 SetChildMemoryState(render_process_id, new_state); 429 SetChildMemoryState(render_process_id, new_state);
390 } 430 }
391 431
392 base::MemoryState MemoryCoordinatorImpl::OverrideGlobalState( 432 base::MemoryState MemoryCoordinatorImpl::OverrideState(MemoryState memory_state,
393 MemoryState memory_state, 433 const ChildInfo& child) {
394 const ChildInfo& child) {
395 // We don't suspend foreground renderers. Throttle them instead. 434 // We don't suspend foreground renderers. Throttle them instead.
396 if (child.is_visible && memory_state == MemoryState::SUSPENDED) 435 if (child.is_visible && memory_state == MemoryState::SUSPENDED)
397 return MemoryState::THROTTLED; 436 return MemoryState::THROTTLED;
398 #if defined(OS_ANDROID) 437 #if defined(OS_ANDROID)
399 // On Android, we throttle background renderers immediately. 438 // On Android, we throttle background renderers immediately.
400 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android 439 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android
401 // and move this ifdef to the class. 440 // and move this ifdef to the class.
402 if (!child.is_visible && memory_state == MemoryState::NORMAL) 441 if (!child.is_visible && memory_state == MemoryState::NORMAL)
403 return MemoryState::THROTTLED; 442 return MemoryState::THROTTLED;
404 // TODO(bashi): Suspend background renderers after a certain period of time. 443 // TODO(bashi): Suspend background renderers after a certain period of time.
405 #endif // defined(OS_ANDROID) 444 #endif // defined(OS_ANDROID)
406 return memory_state; 445 return memory_state;
407 } 446 }
408 447
409 void MemoryCoordinatorImpl::CreateChildInfoMapEntry( 448 void MemoryCoordinatorImpl::CreateChildInfoMapEntry(
410 int render_process_id, 449 int render_process_id,
411 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) { 450 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) {
412 auto& child_info = children_[render_process_id]; 451 auto& child_info = children_[render_process_id];
413 // Process always start with normal memory state. 452 // Process always start with normal memory state.
414 // We'll set renderer's memory state to the current global state when the 453 // We'll set renderer's memory state to the current global state when the
415 // corresponding renderer process is ready to communicate. Renderer processes 454 // corresponding renderer process is ready to communicate. Renderer processes
416 // call AddChild() when they are ready. 455 // call AddChild() when they are ready.
417 child_info.memory_state = MemoryState::NORMAL; 456 child_info.memory_state = MemoryState::NORMAL;
457 child_info.last_state_change = base::TimeTicks::Now();
418 child_info.is_visible = true; 458 child_info.is_visible = true;
419 child_info.handle = std::move(handle); 459 child_info.handle = std::move(handle);
420 } 460 }
421 461
422 void MemoryCoordinatorImpl::NotifyStateToClients() { 462 void MemoryCoordinatorImpl::NotifyStateToClients(MemoryState state) {
423 auto state = GetCurrentMemoryState();
424 base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(state); 463 base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(state);
425 } 464 }
426 465
427 void MemoryCoordinatorImpl::NotifyStateToChildren() { 466 void MemoryCoordinatorImpl::NotifyStateToChildren(MemoryState state) {
428 // It's OK to call SetChildMemoryState() unconditionally because it checks 467 // It's OK to call SetChildMemoryState() unconditionally because it checks
429 // whether this state transition is valid. 468 // whether this state transition is valid.
430 for (auto& iter : children()) 469 for (auto& iter : children())
431 SetChildMemoryState(iter.first, current_state_); 470 SetChildMemoryState(iter.first, state);
432 } 471 }
433 472
434 void MemoryCoordinatorImpl::RecordStateChange(MemoryState prev_state, 473 void MemoryCoordinatorImpl::RecordStateChange(MemoryState prev_state,
435 MemoryState next_state, 474 MemoryState next_state,
436 base::TimeDelta duration) { 475 base::TimeDelta duration) {
437 size_t total_private_kb = 0; 476 size_t total_private_kb = 0;
438 477
439 // TODO(bashi): On MacOS we can't get process metrics for child processes and 478 // TODO(bashi): On MacOS we can't get process metrics for child processes and
440 // therefore can't calculate the total private memory. 479 // therefore can't calculate the total private memory.
441 #if !defined(OS_MACOSX) 480 #if !defined(OS_MACOSX)
(...skipping 20 matching lines...) Expand all
462 501
463 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {} 502 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {}
464 503
465 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) { 504 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) {
466 // This is a nop, but exists for compatibility with STL containers. 505 // This is a nop, but exists for compatibility with STL containers.
467 } 506 }
468 507
469 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {} 508 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {}
470 509
471 } // namespace content 510 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/memory/memory_coordinator_impl.h ('k') | content/browser/memory/memory_monitor_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698