| Index: components/memory_pressure/memory_pressure_stats_collector.cc
|
| diff --git a/components/memory_pressure/memory_pressure_stats_collector.cc b/components/memory_pressure/memory_pressure_stats_collector.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1f3211753c26dd58d1d25d2c264b3ce8f0c6fede
|
| --- /dev/null
|
| +++ b/components/memory_pressure/memory_pressure_stats_collector.cc
|
| @@ -0,0 +1,174 @@
|
| +// 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 "base/metrics/histogram.h"
|
| +
|
| +namespace memory_pressure {
|
| +
|
| +namespace {
|
| +
|
| +using MemoryPressureLevel = MemoryPressureListener::MemoryPressureLevel;
|
| +
|
| +// A special memory pressure level that is used to indicate that the stats
|
| +// collector has not yet been called.
|
| +const MemoryPressureLevel MEMORY_PRESSURE_LEVEL_INVALID =
|
| + static_cast<MemoryPressureLevel>(
|
| + MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE - 1);
|
| +
|
| +// 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_COUNT;
|
| +}
|
| +
|
| +// 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;
|
| + }
|
| + NOTREACHED();
|
| + return MEMORY_PRESSURE_LEVEL_INVALID;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +MemoryPressureStatsCollector::MemoryPressureStatsCollector(
|
| + ReportingDelegate* reporting_delegate,
|
| + base::TickClock* tick_clock)
|
| + : reporting_delegate_(reporting_delegate),
|
| + tick_clock_(tick_clock),
|
| + last_pressure_level_(MEMORY_PRESSURE_LEVEL_INVALID) {}
|
| +
|
| +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_pressure_level_ == MEMORY_PRESSURE_LEVEL_INVALID) {
|
| + 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) {
|
| + reporting_delegate_->ReportLevelChange(last_pressure_level_,
|
| + current_pressure_level);
|
| + }
|
| +
|
| + // Increment the appropriate cumulative bucket.
|
| + int index = MemoryPressureLevelToUmaEnumValue(current_pressure_level);
|
| + base::TimeDelta time_since_update = now - last_update_time_;
|
| + unreported_cumulative_time_[index] += time_since_update;
|
| +
|
| + // 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);
|
| +
|
| + reporting_delegate_->ReportCumulativeTime(
|
| + MemoryPressureLevelFromUmaEnumValue(
|
| + static_cast<MemoryPressureLevelUMA>(i)),
|
| + static_cast<int>(seconds));
|
| + }
|
| +}
|
| +
|
| +namespace {
|
| +
|
| +// Enumeration of UMA pressure level changes. This needs to be kept in sync
|
| +// with histograms.xml and the memory pressure levels defined in
|
| +// MemoryPressureListener.
|
| +enum MemoryPressureLevelChangeUMA {
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_NONE_TO_MODERATE = 0,
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_NONE_TO_CRITICAL = 1,
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_MODERATE_TO_CRITICAL = 2,
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_CRITICAL_TO_MODERATE = 3,
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_CRITICAL_TO_NONE = 4,
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_MODERATE_TO_NONE = 5,
|
| + // This must be the last value in the enum.
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_COUNT
|
| +};
|
| +
|
| +// Converts a pressure state change to an UMA enumeration value.
|
| +MemoryPressureLevelChangeUMA MemoryPressureLevelChangeToUmaEnumValue(
|
| + MemoryPressureLevel old_level,
|
| + MemoryPressureLevel new_level) {
|
| + switch (old_level) {
|
| + case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: {
|
| + if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)
|
| + return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_NONE_TO_MODERATE;
|
| + if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)
|
| + return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_NONE_TO_CRITICAL;
|
| + }
|
| + case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: {
|
| + if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE)
|
| + return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_MODERATE_TO_NONE;
|
| + if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL)
|
| + return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_MODERATE_TO_CRITICAL;
|
| + }
|
| + case MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: {
|
| + if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE)
|
| + return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_CRITICAL_TO_MODERATE;
|
| + if (new_level == MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE)
|
| + return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_CRITICAL_TO_MODERATE;
|
| + }
|
| + }
|
| + NOTREACHED();
|
| + return UMA_MEMORY_PRESSURE_LEVEL_CHANGE_COUNT;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +void MemoryPressureStatsCollector::UmaReportingDelegate::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));
|
| +}
|
| +
|
| +void MemoryPressureStatsCollector::UmaReportingDelegate::ReportLevelChange(
|
| + MemoryPressureLevel old_pressure_level,
|
| + MemoryPressureLevel new_pressure_level) {
|
| + UMA_HISTOGRAM_ENUMERATION("Memory.PressureLevelChange",
|
| + MemoryPressureLevelChangeToUmaEnumValue(
|
| + old_pressure_level, new_pressure_level),
|
| + UMA_MEMORY_PRESSURE_LEVEL_CHANGE_COUNT);
|
| +}
|
| +
|
| +} // namespace memory_pressure
|
|
|