blob: e80d4b36c234a2db6b95a1a53a88d25c408cfdc0 [file] [log] [blame]
// Copyright 2016 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 "content/browser/memory/memory_condition_observer.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "content/browser/memory/memory_monitor.h"
namespace content {
namespace {
// An expected renderer size. These values come from the median of appropriate
// UMA stats.
#if defined(OS_ANDROID) || defined(OS_IOS)
const int kExpectedRendererSizeMB = 40;
#elif defined(OS_WIN)
const int kExpectedRendererSizeMB = 70;
#else // Mac, Linux, and ChromeOS
const int kExpectedRendererSizeMB = 120;
#endif
const int kNewRenderersUntilCritical = 2;
const int kDefaultMonitoringIntervalSeconds = 1;
const int kMonitoringIntervalBackgroundedSeconds = 120;
} // namespace
MemoryConditionObserver::MemoryConditionObserver(
MemoryCoordinatorImpl* coordinator,
scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: coordinator_(coordinator), task_runner_(task_runner) {
DCHECK(coordinator_);
monitoring_interval_ =
base::TimeDelta::FromSeconds(kDefaultMonitoringIntervalSeconds);
monitoring_interval_foregrounded_ =
base::TimeDelta::FromSeconds(kDefaultMonitoringIntervalSeconds);
monitoring_interval_backgrounded_ =
base::TimeDelta::FromSeconds(kMonitoringIntervalBackgroundedSeconds);
}
MemoryConditionObserver::~MemoryConditionObserver() {}
void MemoryConditionObserver::ScheduleUpdateCondition(base::TimeDelta delay) {
update_condition_closure_.Reset(base::Bind(
&MemoryConditionObserver::UpdateCondition, base::Unretained(this)));
task_runner_->PostDelayedTask(FROM_HERE, update_condition_closure_.callback(),
delay);
}
void MemoryConditionObserver::OnForegrounded() {
SetMonitoringInterval(monitoring_interval_foregrounded_);
}
void MemoryConditionObserver::OnBackgrounded() {
SetMonitoringInterval(monitoring_interval_backgrounded_);
}
void MemoryConditionObserver::SetMonitoringInterval(base::TimeDelta interval) {
DCHECK(!interval.is_zero());
if (interval == monitoring_interval_)
return;
monitoring_interval_ = interval;
ScheduleUpdateCondition(interval);
}
MemoryCondition MemoryConditionObserver::CalculateNextCondition() {
int available =
coordinator_->memory_monitor()->GetFreeMemoryUntilCriticalMB();
// TODO(chrisha): Move this histogram recording to a better place when
// https://codereview.chromium.org/2479673002/ is landed.
UMA_HISTOGRAM_MEMORY_LARGE_MB("Memory.Coordinator.FreeMemoryUntilCritical",
available);
int expected_renderer_count = available / kExpectedRendererSizeMB;
if (available <= 0 || expected_renderer_count < kNewRenderersUntilCritical)
return MemoryCondition::CRITICAL;
return MemoryCondition::NORMAL;
}
void MemoryConditionObserver::UpdateCondition() {
auto next_condition = CalculateNextCondition();
coordinator_->UpdateConditionIfNeeded(next_condition);
ScheduleUpdateCondition(monitoring_interval_);
}
} // namespace content