Skip to content

Commit

Permalink
base: Introduce an explicit call for reducing emulated discardable me…
Browse files Browse the repository at this point in the history
…mory usage.

    
This removes the use of memory pressure signals from discardable memory
system and instead introduces an explicit call for reducing emulated
discardable memory that the renderer can call when all widgets are hidden
until we have a better mechanism in place.
    
BUG=398087
TEST=base_unittests,content_browsertests

Review URL: https://codereview.chromium.org/448173002

Cr-Commit-Position: refs/heads/master@{#288793}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@288793 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
reveman@chromium.org committed Aug 11, 2014
1 parent 672c7bf commit f5965a3
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 193 deletions.
8 changes: 0 additions & 8 deletions base/memory/discardable_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,6 @@ class BASE_EXPORT DiscardableMemory {
public:
virtual ~DiscardableMemory() {}

// Call this on a thread with a MessageLoop current to allow discardable
// memory implementations to respond to memory pressure signals.
static void RegisterMemoryPressureListeners();

// Call this to prevent discardable memory implementations from responding
// to memory pressure signals.
static void UnregisterMemoryPressureListeners();

// Gets the discardable memory type with a given name.
static DiscardableMemoryType GetNamedType(const std::string& name);

Expand Down
15 changes: 1 addition & 14 deletions base/memory/discardable_memory_android.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,7 @@ size_t GetOptimalAshmemRegionSizeForAllocator() {
// Holds the shared state used for allocations.
struct SharedState {
SharedState()
: manager(kAshmemMemoryLimit,
kAshmemMemoryLimit,
kAshmemMemoryLimit,
TimeDelta::Max()),
: manager(kAshmemMemoryLimit, kAshmemMemoryLimit, TimeDelta::Max()),
allocator(kAshmemAllocatorName,
GetOptimalAshmemRegionSizeForAllocator()) {}

Expand All @@ -46,16 +43,6 @@ LazyInstance<SharedState>::Leaky g_shared_state = LAZY_INSTANCE_INITIALIZER;

} // namespace

// static
void DiscardableMemory::RegisterMemoryPressureListeners() {
internal::DiscardableMemoryEmulated::RegisterMemoryPressureListeners();
}

// static
void DiscardableMemory::UnregisterMemoryPressureListeners() {
internal::DiscardableMemoryEmulated::UnregisterMemoryPressureListeners();
}

// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
Expand Down
16 changes: 5 additions & 11 deletions base/memory/discardable_memory_emulated.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,12 @@ namespace {
// This is admittedly pretty magical.
const size_t kEmulatedMemoryLimit = 512 * 1024 * 1024;
const size_t kEmulatedSoftMemoryLimit = 32 * 1024 * 1024;
const size_t kEmulatedBytesToKeepUnderModeratePressure = 4 * 1024 * 1024;
const size_t kEmulatedHardMemoryLimitExpirationTimeMs = 1000;

struct SharedState {
SharedState()
: manager(kEmulatedMemoryLimit,
kEmulatedSoftMemoryLimit,
kEmulatedBytesToKeepUnderModeratePressure,
TimeDelta::FromMilliseconds(
kEmulatedHardMemoryLimitExpirationTimeMs)) {}

Expand All @@ -45,18 +43,14 @@ DiscardableMemoryEmulated::~DiscardableMemoryEmulated() {
}

// static
void DiscardableMemoryEmulated::RegisterMemoryPressureListeners() {
g_shared_state.Pointer()->manager.RegisterMemoryPressureListener();
}

// static
void DiscardableMemoryEmulated::UnregisterMemoryPressureListeners() {
g_shared_state.Pointer()->manager.UnregisterMemoryPressureListener();
bool DiscardableMemoryEmulated::ReduceMemoryUsage() {
return g_shared_state.Pointer()->manager.ReduceMemoryUsage();
}

// static
bool DiscardableMemoryEmulated::ReduceMemoryUsage() {
return g_shared_state.Pointer()->manager.ReduceMemoryUsage();
void DiscardableMemoryEmulated::ReduceMemoryUsageUntilWithinLimit(
size_t bytes) {
g_shared_state.Pointer()->manager.ReduceMemoryUsageUntilWithinLimit(bytes);
}

// static
Expand Down
7 changes: 5 additions & 2 deletions base/memory/discardable_memory_emulated.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@ class DiscardableMemoryEmulated
explicit DiscardableMemoryEmulated(size_t bytes);
virtual ~DiscardableMemoryEmulated();

static void RegisterMemoryPressureListeners();
static void UnregisterMemoryPressureListeners();
static bool ReduceMemoryUsage();

// TODO(reveman): Remove this as it is breaking the discardable memory design
// principle that implementations should not rely on information this is
// unavailable in kernel space. crbug.com/400423
BASE_EXPORT static void ReduceMemoryUsageUntilWithinLimit(size_t bytes);

static void PurgeForTesting();

bool Initialize();
Expand Down
10 changes: 0 additions & 10 deletions base/memory/discardable_memory_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,6 @@

namespace base {

// static
void DiscardableMemory::RegisterMemoryPressureListeners() {
internal::DiscardableMemoryEmulated::RegisterMemoryPressureListeners();
}

// static
void DiscardableMemory::UnregisterMemoryPressureListeners() {
internal::DiscardableMemoryEmulated::UnregisterMemoryPressureListeners();
}

// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
Expand Down
16 changes: 1 addition & 15 deletions base/memory/discardable_memory_mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@ namespace {
const size_t kMacMemoryLimit = 512 * 1024 * 1024;

struct SharedState {
SharedState()
: manager(kMacMemoryLimit,
kMacMemoryLimit,
kMacMemoryLimit,
TimeDelta::Max()) {}
SharedState() : manager(kMacMemoryLimit, kMacMemoryLimit, TimeDelta::Max()) {}

internal::DiscardableMemoryManager manager;
};
Expand Down Expand Up @@ -159,16 +155,6 @@ class DiscardableMemoryMac

} // namespace

// static
void DiscardableMemory::RegisterMemoryPressureListeners() {
internal::DiscardableMemoryEmulated::RegisterMemoryPressureListeners();
}

// static
void DiscardableMemory::UnregisterMemoryPressureListeners() {
internal::DiscardableMemoryEmulated::UnregisterMemoryPressureListeners();
}

// static
bool DiscardableMemory::ReduceMemoryUsage() {
return internal::DiscardableMemoryEmulated::ReduceMemoryUsage();
Expand Down
56 changes: 6 additions & 50 deletions base/memory/discardable_memory_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,11 @@ namespace internal {
DiscardableMemoryManager::DiscardableMemoryManager(
size_t memory_limit,
size_t soft_memory_limit,
size_t bytes_to_keep_under_moderate_pressure,
TimeDelta hard_memory_limit_expiration_time)
: allocations_(AllocationMap::NO_AUTO_EVICT),
bytes_allocated_(0u),
memory_limit_(memory_limit),
soft_memory_limit_(soft_memory_limit),
bytes_to_keep_under_moderate_pressure_(
bytes_to_keep_under_moderate_pressure),
hard_memory_limit_expiration_time_(hard_memory_limit_expiration_time) {
BytesAllocatedChanged(bytes_allocated_);
}
Expand All @@ -35,20 +32,6 @@ DiscardableMemoryManager::~DiscardableMemoryManager() {
DCHECK_EQ(0u, bytes_allocated_);
}

void DiscardableMemoryManager::RegisterMemoryPressureListener() {
AutoLock lock(lock_);
DCHECK(base::MessageLoop::current());
DCHECK(!memory_pressure_listener_);
memory_pressure_listener_.reset(new MemoryPressureListener(base::Bind(
&DiscardableMemoryManager::OnMemoryPressure, Unretained(this))));
}

void DiscardableMemoryManager::UnregisterMemoryPressureListener() {
AutoLock lock(lock_);
DCHECK(memory_pressure_listener_);
memory_pressure_listener_.reset();
}

void DiscardableMemoryManager::SetMemoryLimit(size_t bytes) {
AutoLock lock(lock_);
memory_limit_ = bytes;
Expand All @@ -61,12 +44,6 @@ void DiscardableMemoryManager::SetSoftMemoryLimit(size_t bytes) {
soft_memory_limit_ = bytes;
}

void DiscardableMemoryManager::SetBytesToKeepUnderModeratePressure(
size_t bytes) {
AutoLock lock(lock_);
bytes_to_keep_under_moderate_pressure_ = bytes;
}

void DiscardableMemoryManager::SetHardMemoryLimitExpirationTime(
TimeDelta hard_memory_limit_expiration_time) {
AutoLock lock(lock_);
Expand All @@ -77,13 +54,14 @@ bool DiscardableMemoryManager::ReduceMemoryUsage() {
return PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit();
}

void DiscardableMemoryManager::ReduceMemoryUsageUntilWithinLimit(size_t bytes) {
AutoLock lock(lock_);
PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(Now(),
bytes);
}

void DiscardableMemoryManager::Register(Allocation* allocation, size_t bytes) {
AutoLock lock(lock_);
// A registered memory listener is currently required. This DCHECK can be
// moved or removed if we decide that it's useful to relax this condition.
// TODO(reveman): Enable this DCHECK when skia and blink are able to
// register memory pressure listeners. crbug.com/333907
// DCHECK(memory_pressure_listener_);
DCHECK(allocations_.Peek(allocation) == allocations_.end());
allocations_.Put(allocation, AllocationInfo(bytes));
}
Expand Down Expand Up @@ -182,28 +160,6 @@ size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const {
return bytes_allocated_;
}

void DiscardableMemoryManager::OnMemoryPressure(
MemoryPressureListener::MemoryPressureLevel pressure_level) {
switch (pressure_level) {
case MemoryPressureListener::MEMORY_PRESSURE_MODERATE:
PurgeUntilWithinBytesToKeepUnderModeratePressure();
return;
case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL:
PurgeAll();
return;
}

NOTREACHED();
}

void
DiscardableMemoryManager::PurgeUntilWithinBytesToKeepUnderModeratePressure() {
AutoLock lock(lock_);

PurgeIfNotUsedSinceTimestampUntilUsageIsWithinLimitWithLockAcquired(
Now(), bytes_to_keep_under_moderate_pressure_);
}

bool DiscardableMemoryManager::
PurgeIfNotUsedSinceHardLimitCutoffUntilWithinSoftMemoryLimit() {
AutoLock lock(lock_);
Expand Down
36 changes: 4 additions & 32 deletions base/memory/discardable_memory_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include "base/base_export.h"
#include "base/containers/hash_tables.h"
#include "base/containers/mru_cache.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/synchronization/lock.h"
#include "base/time/time.h"

Expand Down Expand Up @@ -60,27 +59,15 @@ namespace internal {
// of all allocation instances (in case they need to be purged), and the total
// amount of allocated memory (in case this forces a purge). When memory usage
// reaches the limit, the manager purges the LRU memory.
//
// When notified of memory pressure, the manager either purges the LRU memory --
// if the pressure is moderate -- or all discardable memory if the pressure is
// critical.
class BASE_EXPORT_PRIVATE DiscardableMemoryManager {
public:
typedef DiscardableMemoryManagerAllocation Allocation;

DiscardableMemoryManager(size_t memory_limit,
size_t soft_memory_limit,
size_t bytes_to_keep_under_moderate_pressure,
TimeDelta hard_memory_limit_expiration_time);
virtual ~DiscardableMemoryManager();

// Call this to register memory pressure listener. Must be called on a thread
// with a MessageLoop current.
void RegisterMemoryPressureListener();

// Call this to unregister memory pressure listener.
void UnregisterMemoryPressureListener();

// The maximum number of bytes of memory that may be allocated before we force
// a purge.
void SetMemoryLimit(size_t bytes);
Expand All @@ -89,9 +76,6 @@ class BASE_EXPORT_PRIVATE DiscardableMemoryManager {
// limit expiration time without getting purged.
void SetSoftMemoryLimit(size_t bytes);

// Sets the amount of memory to keep when we're under moderate pressure.
void SetBytesToKeepUnderModeratePressure(size_t bytes);

// Sets the memory usage cutoff time for hard memory limit.
void SetHardMemoryLimitExpirationTime(
TimeDelta hard_memory_limit_expiration_time);
Expand All @@ -101,6 +85,10 @@ class BASE_EXPORT_PRIVATE DiscardableMemoryManager {
// have been used.
bool ReduceMemoryUsage();

// This can be called to attempt to reduce memory footprint until within
// limit for bytes to keep under moderate pressure.
void ReduceMemoryUsageUntilWithinLimit(size_t bytes);

// Adds the given allocation to the manager's collection.
void Register(Allocation* allocation, size_t bytes);

Expand Down Expand Up @@ -141,14 +129,6 @@ class BASE_EXPORT_PRIVATE DiscardableMemoryManager {
};
typedef HashingMRUCache<Allocation*, AllocationInfo> AllocationMap;

// This can be called as a hint that the system is under memory pressure.
void OnMemoryPressure(
MemoryPressureListener::MemoryPressureLevel pressure_level);

// Purges memory until usage is less or equal to
// |bytes_to_keep_under_moderate_pressure_|.
void PurgeUntilWithinBytesToKeepUnderModeratePressure();

// Purges memory not used since |hard_memory_limit_expiration_time_| before
// "right now" until usage is less or equal to |soft_memory_limit_|.
// Returns true if total amount of memory is less or equal to soft memory
Expand Down Expand Up @@ -185,14 +165,6 @@ class BASE_EXPORT_PRIVATE DiscardableMemoryManager {
// notification.
size_t soft_memory_limit_;

// Under moderate memory pressure, we will purge memory until usage is within
// this limit.
size_t bytes_to_keep_under_moderate_pressure_;

// Allows us to be respond when the system reports that it is under memory
// pressure.
scoped_ptr<MemoryPressureListener> memory_pressure_listener_;

// Amount of time it takes for an allocation to become affected by
// |soft_memory_limit_|.
TimeDelta hard_memory_limit_expiration_time_;
Expand Down
Loading

0 comments on commit f5965a3

Please sign in to comment.