Commit f518237b authored by lgrey's avatar lgrey Committed by Commit bot

[Mac] Report statistics more regularly in Mac memory pressure monitor

Currently, we only report UMA statistics on receiving a pressure
change event from the system. This means that we could be missing
many ticks of "normal" pressure from sessions that never encounter
pressure, skewing our stats. Other platforms don't have this issue
since they poll.

This change piggybacks statistic reporting on GetCurrentPressureLevel()
which is called regularly by RendererFrameManager::GetMaxNumberOfSavedFrames()
This also allows us to enable reporting for Sierra.

To make this work, GetCurrentPressureLevel is now declared non-const.
There don't appear to be any const MemoryPressureMonitors in the codebase
at the moment, so this should be safe.

BUG=655304

Review-Url: https://codereview.chromium.org/2495003004
Cr-Commit-Position: refs/heads/master@{#434660}
parent 0f23a537
......@@ -35,7 +35,7 @@ class BASE_EXPORT MemoryPressureMonitor {
static void RecordMemoryPressure(MemoryPressureLevel level, int ticks);
// Returns the currently observed memory pressure.
virtual MemoryPressureLevel GetCurrentPressureLevel() const = 0;
virtual MemoryPressureLevel GetCurrentPressureLevel() = 0;
// Sets a notification callback. The default callback invokes
// base::MemoryPressureListener::NotifyMemoryPressure.
......
......@@ -134,7 +134,7 @@ void MemoryPressureMonitor::ScheduleEarlyCheck() {
}
MemoryPressureListener::MemoryPressureLevel
MemoryPressureMonitor::GetCurrentPressureLevel() const {
MemoryPressureMonitor::GetCurrentPressureLevel() {
return current_memory_pressure_level_;
}
......
......@@ -58,7 +58,7 @@ class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor {
void ScheduleEarlyCheck();
// Get the current memory pressure level.
MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel() const
MemoryPressureListener::MemoryPressureLevel GetCurrentPressureLevel()
override;
void SetDispatchCallback(const DispatchCallback& callback) override;
......
......@@ -18,6 +18,10 @@
DISPATCH_EXPORT const struct dispatch_source_type_s
_dispatch_source_type_memorypressure;
namespace {
static const int kUMATickSize = 5;
} // namespace
namespace base {
namespace mac {
......@@ -44,9 +48,9 @@ MemoryPressureMonitor::MemoryPressureMonitor()
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0))),
dispatch_callback_(
base::Bind(&MemoryPressureListener::NotifyMemoryPressure)),
last_pressure_change_(CFAbsoluteTimeGetCurrent()),
last_statistic_report_(CFAbsoluteTimeGetCurrent()),
last_pressure_level_(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
reporting_error_(0) {
last_pressure_level_ = GetCurrentPressureLevel();
dispatch_source_set_event_handler(memory_level_event_source_, ^{
OnMemoryPressureChanged(memory_level_event_source_.get(),
dispatch_callback_);
......@@ -59,43 +63,59 @@ MemoryPressureMonitor::~MemoryPressureMonitor() {
}
MemoryPressureListener::MemoryPressureLevel
MemoryPressureMonitor::GetCurrentPressureLevel() const {
MemoryPressureMonitor::GetCurrentPressureLevel() {
int mac_memory_pressure;
size_t length = sizeof(int);
sysctlbyname("kern.memorystatus_vm_pressure_level", &mac_memory_pressure,
&length, nullptr, 0);
return MemoryPressureLevelForMacMemoryPressure(mac_memory_pressure);
MemoryPressureListener::MemoryPressureLevel memory_pressure_level =
MemoryPressureLevelForMacMemoryPressure(mac_memory_pressure);
bool pressure_level_changed = false;
if (last_pressure_level_ != memory_pressure_level) {
pressure_level_changed = true;
}
SendStatisticsIfNecessary(pressure_level_changed);
last_pressure_level_ = memory_pressure_level;
return memory_pressure_level;
}
void MemoryPressureMonitor::OnMemoryPressureChanged(
dispatch_source_s* event_source,
const MemoryPressureMonitor::DispatchCallback& dispatch_callback) {
int mac_memory_pressure = dispatch_source_get_data(event_source);
MemoryPressureListener::MemoryPressureLevel memory_pressure_level =
MemoryPressureLevelForMacMemoryPressure(mac_memory_pressure);
CFTimeInterval now = CFAbsoluteTimeGetCurrent();
CFTimeInterval since_last_change = now - last_pressure_change_;
last_pressure_change_ = now;
double ticks_to_report;
reporting_error_ =
modf(since_last_change + reporting_error_, &ticks_to_report);
// Sierra fails to call the handler when pressure returns to normal,
// which would skew our data. For example, if pressure went to 'warn'
// at T0, back to 'normal' at T1, then to 'critical' at T10, we would
// report 10 ticks of 'warn' instead of 1 tick of 'warn' and 9 ticks
// of 'normal'.
// This is rdar://29114314
if (mac::IsAtMostOS10_11())
RecordMemoryPressure(last_pressure_level_,
static_cast<int>(ticks_to_report));
bool pressure_level_changed = false;
if (last_pressure_level_ != memory_pressure_level) {
pressure_level_changed = true;
}
SendStatisticsIfNecessary(pressure_level_changed);
last_pressure_level_ = memory_pressure_level;
if (memory_pressure_level !=
MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE)
dispatch_callback.Run(memory_pressure_level);
}
void MemoryPressureMonitor::SendStatisticsIfNecessary(
bool pressure_level_changed) {
CFTimeInterval now = CFAbsoluteTimeGetCurrent();
CFTimeInterval since_last_report = now - last_statistic_report_;
last_statistic_report_ = now;
double accumulated_time = since_last_report + reporting_error_;
int ticks_to_report = static_cast<int>(accumulated_time / kUMATickSize);
reporting_error_ = std::fmod(accumulated_time, kUMATickSize);
// Round up on change to ensure we capture it
if (pressure_level_changed && ticks_to_report < 1) {
ticks_to_report = 1;
reporting_error_ = 0;
}
if (ticks_to_report >= 1)
RecordMemoryPressure(last_pressure_level_, ticks_to_report);
}
void MemoryPressureMonitor::SetDispatchCallback(
const DispatchCallback& callback) {
dispatch_callback_ = callback;
......
......@@ -27,7 +27,7 @@ class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor {
~MemoryPressureMonitor() override;
// Returns the currently-observed memory pressure.
MemoryPressureLevel GetCurrentPressureLevel() const override;
MemoryPressureLevel GetCurrentPressureLevel() override;
void SetDispatchCallback(const DispatchCallback& callback) override;
......@@ -38,12 +38,13 @@ class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor {
MemoryPressureLevelForMacMemoryPressure(int mac_memory_pressure);
void OnMemoryPressureChanged(dispatch_source_s* event_source,
const DispatchCallback& dispatch_callback);
void SendStatisticsIfNecessary(bool pressure_level_changed);
ScopedDispatchObject<dispatch_source_t> memory_level_event_source_;
DispatchCallback dispatch_callback_;
CFTimeInterval last_pressure_change_;
CFTimeInterval last_statistic_report_;
MemoryPressureLevel last_pressure_level_;
......
......@@ -90,7 +90,7 @@ void MemoryPressureMonitor::CheckMemoryPressureSoon() {
}
MemoryPressureListener::MemoryPressureLevel
MemoryPressureMonitor::GetCurrentPressureLevel() const {
MemoryPressureMonitor::GetCurrentPressureLevel() {
return current_memory_pressure_level_;
}
......
......@@ -62,7 +62,7 @@ class BASE_EXPORT MemoryPressureMonitor : public base::MemoryPressureMonitor {
void CheckMemoryPressureSoon();
// Get the current memory pressure level. This can be called from any thread.
MemoryPressureLevel GetCurrentPressureLevel() const override;
MemoryPressureLevel GetCurrentPressureLevel() override;
void SetDispatchCallback(const DispatchCallback& callback) override;
// Returns the moderate pressure level free memory threshold, in MB.
......
......@@ -121,7 +121,7 @@ class DummyMemoryPressureMonitor : public base::MemoryPressureMonitor {
}
// base::CriticalMemoryPressureMonitor:
MemoryPressureLevel GetCurrentPressureLevel() const override {
MemoryPressureLevel GetCurrentPressureLevel() override {
return memory_pressure_level_;
}
void SetDispatchCallback(const DispatchCallback& callback) override {}
......
......@@ -55,7 +55,7 @@ CastMemoryPressureMonitor::CastMemoryPressureMonitor()
CastMemoryPressureMonitor::~CastMemoryPressureMonitor() {}
CastMemoryPressureMonitor::MemoryPressureLevel
CastMemoryPressureMonitor::GetCurrentPressureLevel() const {
CastMemoryPressureMonitor::GetCurrentPressureLevel() {
return current_level_;
}
......
......@@ -21,7 +21,7 @@ class CastMemoryPressureMonitor : public base::MemoryPressureMonitor {
~CastMemoryPressureMonitor() override;
// base::MemoryPressureMonitor implementation:
MemoryPressureLevel GetCurrentPressureLevel() const override;
MemoryPressureLevel GetCurrentPressureLevel() override;
void SetDispatchCallback(const DispatchCallback& callback) override;
private:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment