| Index: base/memory/memory_pressure_monitor.h
|
| diff --git a/base/memory/memory_pressure_monitor.h b/base/memory/memory_pressure_monitor.h
|
| index 90c94209653423aa29e714fbb4b7754b5e7a9bd3..01cfc3b2fa5fdbf3baf0ca2fd825d3d5c3aed473 100644
|
| --- a/base/memory/memory_pressure_monitor.h
|
| +++ b/base/memory/memory_pressure_monitor.h
|
| @@ -7,11 +7,55 @@
|
|
|
| #include "base/base_export.h"
|
| #include "base/memory/memory_pressure_listener.h"
|
| +#include "base/memory/memory_pressure_monitor.h"
|
| +
|
| +#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
|
| +#include "base/memory/weak_ptr.h"
|
| +#include "base/threading/thread_checker.h"
|
| +#include "base/timer/timer.h"
|
| +#endif
|
| +
|
| +#if defined(OS_CHROMEOS) || defined(OS_LINUX)
|
| +#include "base/gtest_prod_util.h"
|
| +#include "base/macros.h"
|
| +#endif
|
| +
|
| +#if defined(OS_CHROMEOS)
|
| +#include "base/files/scoped_file.h"
|
| +#endif
|
| +
|
| +#if defined(OS_WIN)
|
| +// To not pull in windows.h.
|
| +typedef struct _MEMORYSTATUSEX MEMORYSTATUSEX;
|
| +#endif
|
| +
|
| +#if defined(OS_MACOSX)
|
| +#include <dispatch/dispatch.h>
|
| +
|
| +// The following was added to <dispatch/source.h> after 10.8.
|
| +// TODO(shrike): Remove the DISPATCH_MEMORYPRESSURE_NORMAL ifndef once builders
|
| +// reach 10.9 or higher.
|
| +#ifndef DISPATCH_MEMORYPRESSURE_NORMAL
|
| +
|
| +#define DISPATCH_MEMORYPRESSURE_NORMAL 0x01
|
| +#define DISPATCH_MEMORYPRESSURE_WARN 0x02
|
| +#define DISPATCH_MEMORYPRESSURE_CRITICAL 0x04
|
| +
|
| +#endif // DISPATCH_MEMORYPRESSURE_NORMAL
|
| +#endif
|
|
|
| namespace base {
|
|
|
| -// TODO(chrisha): Make this a concrete class with per-OS implementations rather
|
| -// than an abstract base class.
|
| +class TestMemoryPressureMonitor;
|
| +
|
| +#if defined(OS_MACOSX)
|
| +struct DispatchSourceSDeleter {
|
| + void operator()(dispatch_source_s* ptr) {
|
| + dispatch_source_cancel(ptr);
|
| + dispatch_release(ptr);
|
| + }
|
| +};
|
| +#endif
|
|
|
| // Declares the interface for a MemoryPressureMonitor. There are multiple
|
| // OS specific implementations of this class. An instance of the memory
|
| @@ -28,14 +72,214 @@ class BASE_EXPORT MemoryPressureMonitor {
|
| // Return the singleton MemoryPressureMonitor.
|
| static MemoryPressureMonitor* Get();
|
|
|
| - // Returns the currently observed memory pressure.
|
| - virtual MemoryPressureLevel GetCurrentPressureLevel() const = 0;
|
| + // Get the current memory pressure level.
|
| + virtual MemoryPressureLevel GetCurrentPressureLevel() const;
|
|
|
| - protected:
|
| +#if defined(OS_CHROMEOS)
|
| + // There are two memory pressure events:
|
| + // MODERATE - which will mainly release caches.
|
| + // CRITICAL - which will discard tabs.
|
| + // The |MemoryPressureThresholds| enum selects the strategy of firing these
|
| + // events: A conservative strategy will keep as much content in memory as
|
| + // possible (causing the system to swap to zram) and an aggressive strategy
|
| + // will release memory earlier to avoid swapping.
|
| + enum MemoryPressureThresholds {
|
| + // Use the system default.
|
| + THRESHOLD_DEFAULT = 0,
|
| + // Try to keep as much content in memory as possible.
|
| + THRESHOLD_CONSERVATIVE = 1,
|
| + // Discard caches earlier, allowing to keep more tabs in memory.
|
| + THRESHOLD_AGGRESSIVE_CACHE_DISCARD = 2,
|
| + // Discard tabs earlier, allowing the system to get faster.
|
| + THRESHOLD_AGGRESSIVE_TAB_DISCARD = 3,
|
| + // Discard caches and tabs earlier to allow the system to be faster.
|
| + THRESHOLD_AGGRESSIVE = 4
|
| + };
|
| + MemoryPressureMonitor(MemoryPressureThresholds thresholds);
|
| +#endif
|
| +
|
| +#if defined(OS_LINUX) || defined(OS_MACOSX) || defined(OS_WIN)
|
| MemoryPressureMonitor();
|
| +#endif
|
| +
|
| +#if defined(OS_CHROMEOS) || defined(OS_LINUX)
|
| + using GetUsedMemoryInPercentCallback = int (*)();
|
| + // Redo the memory pressure calculation soon and call again if a critical
|
| + // memory pressure prevails. Note that this call will trigger an asynchronous
|
| + // action which gives the system time to release memory back into the pool.
|
| + void ScheduleEarlyCheck();
|
| +#endif
|
| +
|
| +#if defined(OS_WIN)
|
| + // Constants governing the polling and hysteresis behaviour of the observer.
|
| +
|
| + // The polling interval, in milliseconds. While under critical pressure, this
|
| + // is also the timer to repeat cleanup attempts.
|
| + static const int kPollingIntervalMs;
|
| + // The time which should pass between 2 successive moderate memory pressure
|
| + // signals, in milliseconds.
|
| + static const int kModeratePressureCooldownMs;
|
| + // The number of cycles that should pass between 2 successive moderate memory
|
| + // pressure signals.
|
| + static const int kModeratePressureCooldownCycles;
|
| +
|
| + // Constants governing the memory pressure level detection.
|
| +
|
| + // The amount of total system memory beyond which a system is considered to be
|
| + // a large-memory system.
|
| + static const int kLargeMemoryThresholdMb;
|
| + // Default minimum free memory thresholds for small-memory systems, in MB.
|
| + static const int kSmallMemoryDefaultModerateThresholdMb;
|
| + static const int kSmallMemoryDefaultCriticalThresholdMb;
|
| + // Default minimum free memory thresholds for large-memory systems, in MB.
|
| + static const int kLargeMemoryDefaultModerateThresholdMb;
|
| + static const int kLargeMemoryDefaultCriticalThresholdMb;
|
| +
|
| + // Constructor with explicit memory thresholds. These represent the amount of
|
| + // free memory below which the applicable memory pressure state engages.
|
| + MemoryPressureMonitor(int moderate_threshold_mb, int critical_threshold_mb);
|
| +
|
| + // Schedules a memory pressure check to run soon. This must be called on the
|
| + // same thread where the monitor was instantiated.
|
| + void CheckMemoryPressureSoon();
|
| +
|
| + // Returns the moderate pressure level free memory threshold, in MB.
|
| + int moderate_threshold_mb() const { return moderate_threshold_mb_; }
|
| +
|
| + // Returns the critical pressure level free memory threshold, in MB.
|
| + int critical_threshold_mb() const { return critical_threshold_mb_; }
|
| +#endif
|
| +
|
| + protected:
|
| +#if defined(OS_WIN)
|
| + // Internals are exposed for unittests.
|
| +
|
| + // Automatically infers threshold values based on system memory. This invokes
|
| + // GetMemoryStatus so it can be mocked in unittests.
|
| + void InferThresholds();
|
| +
|
| + // Starts observing the memory fill level. Calls to StartObserving should
|
| + // always be matched with calls to StopObserving.
|
| + void StartObserving();
|
| +
|
| + // Stop observing the memory fill level. May be safely called if
|
| + // StartObserving has not been called. Must be called from the same thread on
|
| + // which the monitor was instantiated.
|
| + void StopObserving();
|
| +
|
| + // Checks memory pressure, storing the current level, applying any hysteresis
|
| + // and emitting memory pressure level change signals as necessary. This
|
| + // function is called periodically while the monitor is observing memory
|
| + // pressure. This is split out from CheckMemoryPressureAndRecordStatistics so
|
| + // that it may be called by CheckMemoryPressureSoon and not invoke UMA
|
| + // logging. Must be called from the same thread on which the monitor was
|
| + // instantiated.
|
| + void CheckMemoryPressure();
|
| +
|
| + // Wrapper to CheckMemoryPressure that also records the observed memory
|
| + // pressure level via an UMA enumeration. This is the function that is called
|
| + // periodically by the timer. Must be called from the same thread on which the
|
| + // monitor was instantiated.
|
| + void CheckMemoryPressureAndRecordStatistics();
|
| +
|
| + // Calculates the current instantaneous memory pressure level. This does not
|
| + // use any hysteresis and simply returns the result at the current moment. Can
|
| + // be called on any thread.
|
| + MemoryPressureLevel CalculateCurrentPressureLevel();
|
| +
|
| + // Gets system memory status. This is virtual as a unittesting hook. Returns
|
| + // true if the system call succeeds, false otherwise. Can be called on any
|
| + // thread.
|
| + virtual bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status);
|
| +#endif
|
|
|
| private:
|
| + friend TestMemoryPressureMonitor;
|
| DISALLOW_COPY_AND_ASSIGN(MemoryPressureMonitor);
|
| +
|
| + static MemoryPressureMonitor* g_monitor;
|
| +
|
| +#if defined(OS_CHROMEOS) || defined(OS_LINUX)
|
| + friend TestMemoryPressureMonitor;
|
| + // Starts observing the memory fill level.
|
| + // Calls to StartObserving should always be matched with calls to
|
| + // StopObserving.
|
| + void StartObserving();
|
| +
|
| + // Stop observing the memory fill level.
|
| + // May be safely called if StartObserving has not been called.
|
| + void StopObserving();
|
| +
|
| + // The function which gets periodically called to check any changes in the
|
| + // memory pressure. It will report pressure changes as well as continuous
|
| + // critical pressure levels.
|
| + void CheckMemoryPressure();
|
| +
|
| + // The function periodically checks the memory pressure changes and records
|
| + // the UMA histogram statistics for the current memory pressure level.
|
| + void CheckMemoryPressureAndRecordStatistics();
|
| +
|
| + // Get the memory pressure in percent (virtual for testing).
|
| + virtual int GetUsedMemoryInPercent();
|
| +
|
| + // The current memory pressure.
|
| + base::MemoryPressureListener::MemoryPressureLevel
|
| + current_memory_pressure_level_;
|
| +
|
| + // A periodic timer to check for resource pressure changes. This will get
|
| + // replaced by a kernel triggered event system (see crbug.com/381196).
|
| + base::RepeatingTimer<MemoryPressureMonitor> timer_;
|
| +
|
| + // To slow down the amount of moderate pressure event calls, this counter
|
| + // gets used to count the number of events since the last event occured.
|
| + int moderate_pressure_repeat_count_;
|
| +#endif
|
| +
|
| +#if defined(OS_CHROMEOS)
|
| + // The thresholds for moderate and critical pressure.
|
| + const int moderate_pressure_threshold_percent_;
|
| + const int critical_pressure_threshold_percent_;
|
| +
|
| + // File descriptor used to detect low memory condition.
|
| + ScopedFD low_mem_file_;
|
| +#endif
|
| +
|
| +#if defined(OS_WIN)
|
| + // Threshold amounts of available memory that trigger pressure levels. See
|
| + // memory_pressure_monitor.cc for a discussion of reasonable values for these.
|
| + int moderate_threshold_mb_;
|
| + int critical_threshold_mb_;
|
| +
|
| + // A periodic timer to check for memory pressure changes.
|
| + base::RepeatingTimer<MemoryPressureMonitor> timer_;
|
| +
|
| + // The current memory pressure.
|
| + MemoryPressureLevel current_memory_pressure_level_;
|
| +
|
| + // To slow down the amount of moderate pressure event calls, this gets used to
|
| + // count the number of events since the last event occured. This is used by
|
| + // |CheckMemoryPressure| to apply hysteresis on the raw results of
|
| + // |CalculateCurrentPressureLevel|.
|
| + int moderate_pressure_repeat_count_;
|
| +
|
| + // Ensures that this object is used from a single thread.
|
| + base::ThreadChecker thread_checker_;
|
| +#endif
|
| +
|
| +#if defined(OS_MACOSX)
|
| + static MemoryPressureLevel MemoryPressureLevelForMacMemoryPressure(
|
| + int mac_memory_pressure);
|
| + static void NotifyMemoryPressureChanged(dispatch_source_s* event_source);
|
| +
|
| + scoped_ptr<dispatch_source_s, DispatchSourceSDeleter>
|
| + memory_level_event_source_;
|
| +#endif
|
| +
|
| +#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_WIN)
|
| + // Weak pointer factory to ourself used for scheduling calls to
|
| + // CheckMemoryPressure/CheckMemoryPressureAndRecordStatistics via |timer_|.
|
| + base::WeakPtrFactory<MemoryPressureMonitor> weak_ptr_factory_;
|
| +#endif
|
| };
|
|
|
| } // namespace base
|
|
|