blob: b4ff482bd4e0331fc00d9f2a9c0e4878dd807400 [file]
// Copyright 2015 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 "components/memory_pressure/memory_pressure_stats_collector.h"
#include <stddef.h>
#include <stdint.h>
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/tick_clock.h"
namespace memory_pressure {
namespace {
using MemoryPressureLevel = MemoryPressureListener::MemoryPressureLevel;
// Converts a memory pressure level to an UMA enumeration value.
MemoryPressureLevelUMA MemoryPressureLevelToUmaEnumValue(
MemoryPressureLevel level) {
switch (level) {
case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
return UMA_MEMORY_PRESSURE_LEVEL_NONE;
case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
return UMA_MEMORY_PRESSURE_LEVEL_MODERATE;
case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
return UMA_MEMORY_PRESSURE_LEVEL_CRITICAL;
}
NOTREACHED();
return UMA_MEMORY_PRESSURE_LEVEL_NONE;
}
// Converts an UMA enumeration value to a memory pressure level.
MemoryPressureLevel MemoryPressureLevelFromUmaEnumValue(
MemoryPressureLevelUMA level) {
switch (level) {
case UMA_MEMORY_PRESSURE_LEVEL_NONE:
return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
case UMA_MEMORY_PRESSURE_LEVEL_MODERATE:
return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
case UMA_MEMORY_PRESSURE_LEVEL_CRITICAL:
return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
case UMA_MEMORY_PRESSURE_LEVEL_COUNT:
NOTREACHED();
break;
}
NOTREACHED();
return MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
}
} // namespace
MemoryPressureStatsCollector::MemoryPressureStatsCollector(
base::TickClock* tick_clock)
: tick_clock_(tick_clock),
last_pressure_level_(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) {
}
void MemoryPressureStatsCollector::UpdateStatistics(
MemoryPressureLevel current_pressure_level) {
base::TimeTicks now = tick_clock_->NowTicks();
// Special case: first call to the collector. Observations have just started
// so there's nothing to report.
if (last_update_time_.is_null()) {
last_pressure_level_ = current_pressure_level;
last_update_time_ = now;
return;
}
// If the pressure level has transitioned then report this.
if (last_pressure_level_ != current_pressure_level)
ReportLevelChange(last_pressure_level_, current_pressure_level);
// Increment the appropriate cumulative bucket.
int index = MemoryPressureLevelToUmaEnumValue(current_pressure_level);
unreported_cumulative_time_[index] += now - last_update_time_;
// Update last pressure related state.
last_pressure_level_ = current_pressure_level;
last_update_time_ = now;
// Make reports about the amount of time spent cumulatively at each level.
for (size_t i = 0; i < arraysize(unreported_cumulative_time_); ++i) {
// Report the largest number of whole seconds possible at this moment and
// carry around the rest for a future report.
if (unreported_cumulative_time_[i].is_zero())
continue;
int64_t seconds = unreported_cumulative_time_[i].InSeconds();
if (seconds == 0)
continue;
unreported_cumulative_time_[i] -= base::TimeDelta::FromSeconds(seconds);
ReportCumulativeTime(MemoryPressureLevelFromUmaEnumValue(
static_cast<MemoryPressureLevelUMA>(i)),
static_cast<int>(seconds));
}
}
// static
void MemoryPressureStatsCollector::ReportCumulativeTime(
MemoryPressureLevel pressure_level,
int seconds) {
// Use the more primitive STATIC_HISTOGRAM_POINTER_BLOCK macro because the
// simple UMA_HISTOGRAM macros don't expose 'AddCount' functionality.
STATIC_HISTOGRAM_POINTER_BLOCK(
"Memory.PressureLevel",
AddCount(MemoryPressureLevelToUmaEnumValue(pressure_level), seconds),
base::LinearHistogram::FactoryGet(
"Memory.PressureLevel", 1, UMA_MEMORY_PRESSURE_LEVEL_COUNT,
UMA_MEMORY_PRESSURE_LEVEL_COUNT + 1,
base::HistogramBase::kUmaTargetedHistogramFlag));
}
// static
void MemoryPressureStatsCollector::ReportLevelChange(
MemoryPressureLevel old_pressure_level,
MemoryPressureLevel new_pressure_level) {
// TODO(chrisha): Report Memory.PressureLevelChange when this code is in use.
}
} // namespace memory_pressure