diff --git a/src/Microsoft.Extensions.Caching.Abstractions/IMemoryCache.cs b/src/Microsoft.Extensions.Caching.Abstractions/IMemoryCache.cs
index 7c41611d..72c05bb5 100644
--- a/src/Microsoft.Extensions.Caching.Abstractions/IMemoryCache.cs
+++ b/src/Microsoft.Extensions.Caching.Abstractions/IMemoryCache.cs
@@ -30,5 +30,11 @@ public interface IMemoryCache : IDisposable
///
/// An object identifying the entry.
void Remove(object key);
+
+ ///
+ /// Attempt to remove the given percentage of the total entries in the cache.
+ ///
+ /// The percentage of cache entries to remove.
+ void Compact(double percentage);
}
}
\ No newline at end of file
diff --git a/src/Microsoft.Extensions.Caching.Abstractions/exceptions.net45.json b/src/Microsoft.Extensions.Caching.Abstractions/exceptions.net45.json
new file mode 100644
index 00000000..2ece3d0c
--- /dev/null
+++ b/src/Microsoft.Extensions.Caching.Abstractions/exceptions.net45.json
@@ -0,0 +1,8 @@
+[
+ {
+ "OldTypeId": "public interface Microsoft.Extensions.Caching.Memory.IMemoryCache : System.IDisposable",
+ "NewTypeId": "public interface Microsoft.Extensions.Caching.Memory.IMemoryCache : System.IDisposable",
+ "NewMemberId": "System.Void Compact(System.Double percentage)",
+ "Kind": "Addition"
+ }
+]
\ No newline at end of file
diff --git a/src/Microsoft.Extensions.Caching.Abstractions/exceptions.netcore.json b/src/Microsoft.Extensions.Caching.Abstractions/exceptions.netcore.json
new file mode 100644
index 00000000..2ece3d0c
--- /dev/null
+++ b/src/Microsoft.Extensions.Caching.Abstractions/exceptions.netcore.json
@@ -0,0 +1,8 @@
+[
+ {
+ "OldTypeId": "public interface Microsoft.Extensions.Caching.Memory.IMemoryCache : System.IDisposable",
+ "NewTypeId": "public interface Microsoft.Extensions.Caching.Memory.IMemoryCache : System.IDisposable",
+ "NewMemberId": "System.Void Compact(System.Double percentage)",
+ "Kind": "Addition"
+ }
+]
\ No newline at end of file
diff --git a/src/Microsoft.Extensions.Caching.Memory/Infrastructure/GcNotification.cs b/src/Microsoft.Extensions.Caching.Memory/Infrastructure/GcNotification.cs
deleted file mode 100644
index 0448cf3c..00000000
--- a/src/Microsoft.Extensions.Caching.Memory/Infrastructure/GcNotification.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System;
-
-namespace Microsoft.Extensions.Internal
-{
- ///
- /// Registers a callback that fires each time a Gen2 garbage collection occurs,
- /// presumably due to memory pressure.
- /// For this to work no components can have a reference to the instance.
- ///
- public class GcNotification
- {
- private readonly Func _callback;
- private readonly object _state;
- private readonly int _initialCollectionCount;
-
- private GcNotification(Func callback, object state)
- {
- _callback = callback;
- _state = state;
- _initialCollectionCount = GC.CollectionCount(2);
- }
-
- public static void Register(Func callback, object state)
- {
- var notification = new GcNotification(callback, state);
- }
-
- ~GcNotification()
- {
- bool reRegister = true;
- try
- {
- // Only invoke the callback after this instance has made it into gen2.
- if (_initialCollectionCount < GC.CollectionCount(2))
- {
- reRegister = _callback(_state);
- }
- }
- catch (Exception)
- {
- // Never throw from the finalizer thread
- }
-
- if (reRegister && !Environment.HasShutdownStarted)
- {
- GC.ReRegisterForFinalize(this);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/Microsoft.Extensions.Caching.Memory/MemoryCache.cs b/src/Microsoft.Extensions.Caching.Memory/MemoryCache.cs
index e9097dc2..85c2829d 100644
--- a/src/Microsoft.Extensions.Caching.Memory/MemoryCache.cs
+++ b/src/Microsoft.Extensions.Caching.Memory/MemoryCache.cs
@@ -48,10 +48,6 @@ public MemoryCache(IOptions optionsAccessor)
_entryExpirationNotification = EntryExpired;
_clock = options.Clock ?? new SystemClock();
- if (options.CompactOnMemoryPressure)
- {
- GcNotification.Register(DoMemoryPreassureCollection, state: null);
- }
_expirationScanFrequency = options.ExpirationScanFrequency;
_lastExpirationScan = _clock.UtcNow;
}
@@ -276,20 +272,6 @@ private static void ScanForExpiredItems(MemoryCache cache)
}
}
- /// This is called after a Gen2 garbage collection. We assume this means there was memory pressure.
- /// Remove at least 10% of the total entries (or estimated memory?).
- private bool DoMemoryPreassureCollection(object state)
- {
- if (_disposed)
- {
- return false;
- }
-
- Compact(0.10);
-
- return true;
- }
-
/// Remove at least the given percentage (0.10 for 10%) of the total entries (or estimated memory?), according to the following policy:
/// 1. Remove all expired items.
/// 2. Bucket by CacheItemPriority.
diff --git a/src/Microsoft.Extensions.Caching.Memory/MemoryCacheOptions.cs b/src/Microsoft.Extensions.Caching.Memory/MemoryCacheOptions.cs
index 6d79032e..4e591b77 100644
--- a/src/Microsoft.Extensions.Caching.Memory/MemoryCacheOptions.cs
+++ b/src/Microsoft.Extensions.Caching.Memory/MemoryCacheOptions.cs
@@ -11,8 +11,6 @@ public class MemoryCacheOptions : IOptions
{
public ISystemClock Clock { get; set; }
- public bool CompactOnMemoryPressure { get; set; } = true;
-
public TimeSpan ExpirationScanFrequency { get; set; } = TimeSpan.FromMinutes(1);
MemoryCacheOptions IOptions.Value
diff --git a/src/Microsoft.Extensions.Caching.Memory/exceptions.net45.json b/src/Microsoft.Extensions.Caching.Memory/exceptions.net45.json
new file mode 100644
index 00000000..7351b76c
--- /dev/null
+++ b/src/Microsoft.Extensions.Caching.Memory/exceptions.net45.json
@@ -0,0 +1,12 @@
+[
+ {
+ "OldTypeId": "public class Microsoft.Extensions.Caching.Memory.MemoryCacheOptions : Microsoft.Extensions.Options.IOptions",
+ "OldMemberId": "public System.Boolean get_CompactOnMemoryPressure()",
+ "Kind": "Removal"
+ },
+ {
+ "OldTypeId": "public class Microsoft.Extensions.Caching.Memory.MemoryCacheOptions : Microsoft.Extensions.Options.IOptions",
+ "OldMemberId": "public System.Void set_CompactOnMemoryPressure(System.Boolean value)",
+ "Kind": "Removal"
+ }
+]
\ No newline at end of file
diff --git a/src/Microsoft.Extensions.Caching.Memory/exceptions.netcore.json b/src/Microsoft.Extensions.Caching.Memory/exceptions.netcore.json
new file mode 100644
index 00000000..7351b76c
--- /dev/null
+++ b/src/Microsoft.Extensions.Caching.Memory/exceptions.netcore.json
@@ -0,0 +1,12 @@
+[
+ {
+ "OldTypeId": "public class Microsoft.Extensions.Caching.Memory.MemoryCacheOptions : Microsoft.Extensions.Options.IOptions",
+ "OldMemberId": "public System.Boolean get_CompactOnMemoryPressure()",
+ "Kind": "Removal"
+ },
+ {
+ "OldTypeId": "public class Microsoft.Extensions.Caching.Memory.MemoryCacheOptions : Microsoft.Extensions.Options.IOptions",
+ "OldMemberId": "public System.Void set_CompactOnMemoryPressure(System.Boolean value)",
+ "Kind": "Removal"
+ }
+]
\ No newline at end of file
diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/CacheEntryScopeExpirationTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/CacheEntryScopeExpirationTests.cs
index 9980ab7d..3ca069ad 100644
--- a/test/Microsoft.Extensions.Caching.Memory.Tests/CacheEntryScopeExpirationTests.cs
+++ b/test/Microsoft.Extensions.Caching.Memory.Tests/CacheEntryScopeExpirationTests.cs
@@ -22,7 +22,6 @@ private IMemoryCache CreateCache(ISystemClock clock)
return new MemoryCache(new MemoryCacheOptions()
{
Clock = clock,
- CompactOnMemoryPressure = false,
});
}
diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/CacheServiceExtensionsTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/CacheServiceExtensionsTests.cs
index 5c76d01f..853c2f1a 100644
--- a/test/Microsoft.Extensions.Caching.Memory.Tests/CacheServiceExtensionsTests.cs
+++ b/test/Microsoft.Extensions.Caching.Memory.Tests/CacheServiceExtensionsTests.cs
@@ -124,6 +124,11 @@ public ICacheEntry CreateEntry(object key)
{
throw new NotImplementedException();
}
+
+ public void Compact(double percentage)
+ {
+ throw new NotImplementedException();
+ }
}
private class TestDistributedCache : IDistributedCache
diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/CompactTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/CompactTests.cs
index 5934f175..0d863ffe 100644
--- a/test/Microsoft.Extensions.Caching.Memory.Tests/CompactTests.cs
+++ b/test/Microsoft.Extensions.Caching.Memory.Tests/CompactTests.cs
@@ -14,7 +14,6 @@ private MemoryCache CreateCache(ISystemClock clock = null)
return new MemoryCache(new MemoryCacheOptions()
{
Clock = clock,
- CompactOnMemoryPressure = false,
});
}
diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/GcNotificationTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/GcNotificationTests.cs
deleted file mode 100644
index 292d492d..00000000
--- a/test/Microsoft.Extensions.Caching.Memory.Tests/GcNotificationTests.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) .NET Foundation. All rights reserved.
-// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
-
-using System;
-using System.Threading;
-using Microsoft.AspNetCore.Testing.xunit;
-using Microsoft.Extensions.Internal;
-using Xunit;
-
-namespace Microsoft.Extensions.Caching.Memory
-{
- public class GcNotificationTests
- {
- [ConditionalFact]
- [FrameworkSkipCondition(RuntimeFrameworks.Mono, SkipReason = "Test fails on Mono (finalizer never called).")]
- public void CallbackRegisteredAndInvoked()
- {
- var callbackInvoked = new ManualResetEvent(false);
- GcNotification.Register(state =>
- {
- callbackInvoked.Set();
- return false;
- }, null);
-
- GcCollectAndWait();
- Assert.True(callbackInvoked.WaitOne(0));
- }
-
- [Fact]
- public void CallbackInvokedMultipleTimes()
- {
- var reRegisterForFinalize = true;
- var callbackInvoked = new ManualResetEvent(false);
- GcNotification.Register(state =>
- {
- callbackInvoked.Set();
- return reRegisterForFinalize;
- }, null);
-
- GcCollectAndWait();
- Assert.True(callbackInvoked.WaitOne(0));
-
- callbackInvoked.Reset();
- reRegisterForFinalize = false;
-
- GcCollectAndWait();
- Assert.True(callbackInvoked.WaitOne(0));
-
- callbackInvoked.Reset();
-
- // No callback expected the 3rd time
- GcCollectAndWait();
- Assert.False(callbackInvoked.WaitOne(0));
- }
-
- private static void GcCollectAndWait()
- {
- // We need to collect twice for this test to work on Mono
- GC.Collect(2, GCCollectionMode.Forced, blocking: true);
- GC.Collect(2, GCCollectionMode.Forced, blocking: true);
- GC.WaitForPendingFinalizers();
- }
- }
-}
diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs
index 18e18e93..a76afe2a 100644
--- a/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs
+++ b/test/Microsoft.Extensions.Caching.Memory.Tests/MemoryCacheSetAndRemoveTests.cs
@@ -12,10 +12,7 @@ public class MemoryCacheSetAndRemoveTests
{
private static IMemoryCache CreateCache()
{
- return new MemoryCache(new MemoryCacheOptions()
- {
- CompactOnMemoryPressure = false,
- });
+ return new MemoryCache(new MemoryCacheOptions());
}
[Fact]
diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/TimeExpirationTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/TimeExpirationTests.cs
index 0237ad6b..f4cbfd99 100644
--- a/test/Microsoft.Extensions.Caching.Memory.Tests/TimeExpirationTests.cs
+++ b/test/Microsoft.Extensions.Caching.Memory.Tests/TimeExpirationTests.cs
@@ -16,7 +16,6 @@ private IMemoryCache CreateCache(ISystemClock clock)
return new MemoryCache(new MemoryCacheOptions()
{
Clock = clock,
- CompactOnMemoryPressure = false,
});
}
diff --git a/test/Microsoft.Extensions.Caching.Memory.Tests/TokenExpirationTests.cs b/test/Microsoft.Extensions.Caching.Memory.Tests/TokenExpirationTests.cs
index 6b1c6484..9c36ab26 100644
--- a/test/Microsoft.Extensions.Caching.Memory.Tests/TokenExpirationTests.cs
+++ b/test/Microsoft.Extensions.Caching.Memory.Tests/TokenExpirationTests.cs
@@ -23,7 +23,6 @@ private IMemoryCache CreateCache(ISystemClock clock)
return new MemoryCache(new MemoryCacheOptions()
{
Clock = clock,
- CompactOnMemoryPressure = false,
});
}