diff --git a/BitFaster.Caching.Benchmarks/Lfu/LfuJustGetOrAdd.cs b/BitFaster.Caching.Benchmarks/Lfu/LfuJustGetOrAdd.cs index 47b24376..689225d2 100644 --- a/BitFaster.Caching.Benchmarks/Lfu/LfuJustGetOrAdd.cs +++ b/BitFaster.Caching.Benchmarks/Lfu/LfuJustGetOrAdd.cs @@ -22,11 +22,11 @@ public class LfuJustGetOrAdd const int stripes = 1; private static readonly BackgroundThreadScheduler background = new BackgroundThreadScheduler(); - private static readonly ConcurrentLfu concurrentLfu = new ConcurrentLfu(stripes, 9, background, EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + private static readonly ConcurrentLfu concurrentLfu = new ConcurrentLfu(stripes, 9, background, EqualityComparer.Default); - private static readonly ConcurrentLfu concurrentLfuFore = new ConcurrentLfu(stripes, 9, new ForegroundScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); - private static readonly ConcurrentLfu concurrentLfuTp = new ConcurrentLfu(stripes, 9, new ThreadPoolScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); - private static readonly ConcurrentLfu concurrentLfuNull = new ConcurrentLfu(stripes, 9, new NullScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + private static readonly ConcurrentLfu concurrentLfuFore = new ConcurrentLfu(stripes, 9, new ForegroundScheduler(), EqualityComparer.Default); + private static readonly ConcurrentLfu concurrentLfuTp = new ConcurrentLfu(stripes, 9, new ThreadPoolScheduler(), EqualityComparer.Default); + private static readonly ConcurrentLfu concurrentLfuNull = new ConcurrentLfu(stripes, 9, new NullScheduler(), EqualityComparer.Default); [GlobalSetup] public void GlobalSetup() diff --git a/BitFaster.Caching.Benchmarks/Lru/LruJustGetOrAdd.cs b/BitFaster.Caching.Benchmarks/Lru/LruJustGetOrAdd.cs index bd301498..b2831ff9 100644 --- a/BitFaster.Caching.Benchmarks/Lru/LruJustGetOrAdd.cs +++ b/BitFaster.Caching.Benchmarks/Lru/LruJustGetOrAdd.cs @@ -48,7 +48,7 @@ public class LruJustGetOrAdd private static readonly ICache atomicFastLru = new ConcurrentLruBuilder().WithConcurrencyLevel(8).WithCapacity(9).WithAtomicGetOrAdd().Build(); private static readonly BackgroundThreadScheduler background = new BackgroundThreadScheduler(); - private static readonly ConcurrentLfu concurrentLfu = new ConcurrentLfu(1, 9, background, EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + private static readonly ConcurrentLfu concurrentLfu = new ConcurrentLfu(1, 9, background, EqualityComparer.Default); private static readonly int key = 1; diff --git a/BitFaster.Caching.HitRateAnalysis/Analysis.cs b/BitFaster.Caching.HitRateAnalysis/Analysis.cs index 716fad9f..86a0f42e 100644 --- a/BitFaster.Caching.HitRateAnalysis/Analysis.cs +++ b/BitFaster.Caching.HitRateAnalysis/Analysis.cs @@ -2,9 +2,6 @@ using System.Collections.Generic; using System.Globalization; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using BitFaster.Caching.Lfu; using BitFaster.Caching.Lru; using BitFaster.Caching.Scheduler; @@ -22,7 +19,7 @@ public Analysis(int cacheSize) { concurrentLru = new ConcurrentLru(1, cacheSize, EqualityComparer.Default); classicLru = new ClassicLru(1, cacheSize, EqualityComparer.Default); - concurrentLfu = new ConcurrentLfu(1, cacheSize, new ForegroundScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + concurrentLfu = new ConcurrentLfu(1, cacheSize, new ForegroundScheduler(), EqualityComparer.Default); } public int CacheSize => concurrentLru.Capacity; diff --git a/BitFaster.Caching.ThroughputAnalysis/Program.cs b/BitFaster.Caching.ThroughputAnalysis/Program.cs index fb84d86d..04e2168d 100644 --- a/BitFaster.Caching.ThroughputAnalysis/Program.cs +++ b/BitFaster.Caching.ThroughputAnalysis/Program.cs @@ -22,7 +22,7 @@ class Program const double s = 0.86; const int n = 500; static int capacity = 500; - const int maxThreads = 64; + const int maxThreads = 52; const int sampleCount = 2000; const int repeatCount = 400; @@ -58,7 +58,6 @@ static void Main(string[] args) resultTable.Columns.Add(tc.ToString()); } - DataRow classicLru = resultTable.NewRow(); DataRow memoryCache = resultTable.NewRow(); DataRow concurrentLru = resultTable.NewRow(); @@ -102,7 +101,7 @@ static void Main(string[] args) for (int i = 0; i < warmup + runs; i++) { var scheduler = new BackgroundThreadScheduler(); - results[i] = MeasureThroughput(new ConcurrentLfu(concurrencyLevel: tc, capacity: capacity, scheduler: scheduler, EqualityComparer.Default, LfuBufferSize.Default(concurrencyLevel: tc, capacity: capacity)), tc); + results[i] = MeasureThroughput(new ConcurrentLfu(concurrencyLevel: tc, capacity: capacity, scheduler: scheduler, EqualityComparer.Default), tc); scheduler.Dispose(); } avg = AverageLast(results, runs) / 1000000; diff --git a/BitFaster.Caching.UnitTests/Buffers/StripedBufferSizeTests.cs b/BitFaster.Caching.UnitTests/Buffers/StripedBufferSizeTests.cs deleted file mode 100644 index d9eed4af..00000000 --- a/BitFaster.Caching.UnitTests/Buffers/StripedBufferSizeTests.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using BitFaster.Caching.Buffers; -using FluentAssertions; -using Xunit; - -namespace BitFaster.Caching.UnitTests.Buffers -{ - public class StripedBufferSizeTests - { - [Fact] - public void WhenBufferSizeIsLessThan1CtorThrows() - { - Action constructor = () => { var x = new StripedBufferSize(-1, 1); }; - - constructor.Should().Throw(); - } - - [Fact] - public void WhenStripeCountIsLessThan1CtorThrows() - { - Action constructor = () => { var x = new StripedBufferSize(1, -1); }; - - constructor.Should().Throw(); - } - - [Fact] - public void SizeIsRoundedToNextPowerOf2() - { - var bs = new StripedBufferSize(6, 16); - - bs.BufferSize.Should().Be(8); - } - - [Fact] - public void StripeCountIsRoundedToNextPowerOf2() - { - var bs = new StripedBufferSize(16, 6); - - bs.StripeCount.Should().Be(8); - } - } -} diff --git a/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuBuilderTests.cs b/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuBuilderTests.cs index ea5a8973..7013b16d 100644 --- a/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuBuilderTests.cs +++ b/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuBuilderTests.cs @@ -1,6 +1,5 @@ using System; using BitFaster.Caching.Atomic; -using BitFaster.Caching.Buffers; using BitFaster.Caching.Lfu; using BitFaster.Caching.Scheduler; using FluentAssertions; @@ -53,16 +52,6 @@ public void TestComparer() lfu.TryGet("A", out var value).Should().BeTrue(); } - [Fact] - public void TestBufferConfiguraiton() - { - ICache lfu = new ConcurrentLfuBuilder() - .WithBufferConfiguration(new LfuBufferSize( - new StripedBufferSize(128, 2) - )) - .Build(); - } - // 1 [Fact] public void WithScopedValues() diff --git a/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuTests.cs b/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuTests.cs index f2822db7..e973e46b 100644 --- a/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuTests.cs +++ b/BitFaster.Caching.UnitTests/Lfu/ConcurrentLfuTests.cs @@ -18,7 +18,7 @@ public class ConcurrentLfuTests { private readonly ITestOutputHelper output; - private ConcurrentLfu cache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + private ConcurrentLfu cache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default); private ValueFactory valueFactory = new ValueFactory(); public ConcurrentLfuTests(ITestOutputHelper output) @@ -75,7 +75,7 @@ public void WhenItemsAddedExceedsCapacityItemsAreDiscarded() [Fact] public void WhenItemIsEvictedItIsDisposed() { - var dcache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + var dcache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default); var disposables = new DisposableItem[25]; for (int i = 0; i < 25; i++) @@ -299,7 +299,7 @@ public void WriteUpdatesProtectedLruOrder() [Fact] public void WhenHitRateChangesWindowSizeIsAdapted() { - cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default); // First completely fill the cache, push entries into protected for (int i = 0; i < 20; i++) @@ -368,13 +368,13 @@ public void WhenHitRateChangesWindowSizeIsAdapted() public void ReadSchedulesMaintenanceWhenBufferIsFull() { var scheduler = new TestScheduler(); - cache = new ConcurrentLfu(1, 20, scheduler, EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + cache = new ConcurrentLfu(1, 20, scheduler, EqualityComparer.Default); cache.GetOrAdd(1, k => k); scheduler.RunCount.Should().Be(1); cache.PendingMaintenance(); - for (int i = 0; i < LfuBufferSize.DefaultBufferSize; i++) + for (int i = 0; i < ConcurrentLfu.DefaultBufferSize; i++) { scheduler.RunCount.Should().Be(1); cache.GetOrAdd(1, k => k); @@ -389,30 +389,29 @@ public void ReadSchedulesMaintenanceWhenBufferIsFull() public void WhenReadBufferIsFullReadsAreDropped() { var scheduler = new TestScheduler(); - cache = new ConcurrentLfu(1, 20, scheduler, EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + cache = new ConcurrentLfu(1, 20, scheduler, EqualityComparer.Default); cache.GetOrAdd(1, k => k); scheduler.RunCount.Should().Be(1); cache.PendingMaintenance(); - for (int i = 0; i < LfuBufferSize.DefaultBufferSize * 2; i++) + for (int i = 0; i < ConcurrentLfu.DefaultBufferSize * 2; i++) { cache.GetOrAdd(1, k => k); } cache.PendingMaintenance(); - cache.Metrics.Value.Hits.Should().Be(LfuBufferSize.DefaultBufferSize); + cache.Metrics.Value.Hits.Should().Be(ConcurrentLfu.DefaultBufferSize); } [Fact] public void WhenWriteBufferIsFullAddDoesMaintenance() { - var bufferSize = LfuBufferSize.DefaultBufferSize; + var bufferSize = ConcurrentLfu.DefaultBufferSize; var scheduler = new TestScheduler(); - var bufferConfig = new LfuBufferSize(new StripedBufferSize(bufferSize, 1)); - cache = new ConcurrentLfu(1, bufferSize * 2, scheduler, EqualityComparer.Default, bufferConfig); + cache = new ConcurrentLfu(1, bufferSize * 2, scheduler, EqualityComparer.Default); // add an item, flush write buffer cache.GetOrAdd(-1, k => k); @@ -439,8 +438,7 @@ public void WhenWriteBufferIsFullUpdatesAreDropped() int capacity = 20; var bufferSize = Math.Min(BitOps.CeilingPowerOfTwo(capacity), 128); var scheduler = new TestScheduler(); - var bufferConfig = new LfuBufferSize(new StripedBufferSize(bufferSize, 1)); - cache = new ConcurrentLfu(1, capacity, scheduler, EqualityComparer.Default, bufferConfig); + cache = new ConcurrentLfu(1, capacity, scheduler, EqualityComparer.Default); cache.GetOrAdd(1, k => k); scheduler.RunCount.Should().Be(1); @@ -572,7 +570,7 @@ public void WhenItemIsRemovedItIsRemoved() [Fact] public void WhenItemIsRemovedItIsDisposed() { - var dcache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + var dcache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default); var disposable = new DisposableItem(); dcache.GetOrAdd(1, k => disposable); @@ -661,7 +659,7 @@ public void TrimRemovesNItems() public void TrimWhileItemsInWriteBufferRemovesNItems() { // null scheduler == no maintenance, all writes fit in buffer - cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default); for (int i = 0; i < 25; i++) { @@ -699,7 +697,7 @@ public void VerifyHitsWithBackgroundScheduler() public void VerifyHitsWithThreadPoolScheduler() { // when running all tests in parallel, sample count drops significantly: set low bar for stability. - cache = new ConcurrentLfu(1, 20, new ThreadPoolScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + cache = new ConcurrentLfu(1, 20, new ThreadPoolScheduler(), EqualityComparer.Default); VerifyHits(iterations: 10000000, minSamples: 500000); } @@ -709,7 +707,7 @@ public void VerifyHitsWithThreadPoolScheduler() [Fact] public void VerifyHitsWithNullScheduler() { - cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default); VerifyHits(iterations: 10000000, minSamples: -1); } @@ -720,12 +718,12 @@ public void VerifyHitsWithNullScheduler() [Fact] public void VerifyHitsWithForegroundScheduler() { - cache = new ConcurrentLfu(1, 20, new ForegroundScheduler(), EqualityComparer.Default, LfuBufferSize.Default(1, 128)); + cache = new ConcurrentLfu(1, 20, new ForegroundScheduler(), EqualityComparer.Default); // Note: TryAdd will drop 1 read per full read buffer, since TryAdd will return false // before TryScheduleDrain is called. This serves as sanity check. int iterations = 10000000; - int dropped = iterations / LfuBufferSize.DefaultBufferSize; + int dropped = iterations / ConcurrentLfu.DefaultBufferSize; this.output.WriteLine($"Will drop {dropped} reads."); @@ -735,8 +733,7 @@ public void VerifyHitsWithForegroundScheduler() [Fact] public void VerifyMisses() { - cache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default, - new LfuBufferSize(new StripedBufferSize(1, 1))); + cache = new ConcurrentLfu(1, 20, new BackgroundThreadScheduler(), EqualityComparer.Default); int iterations = 100000; Func func = x => x; @@ -770,8 +767,7 @@ public void VerifyMisses() public async Task ThreadedVerifyMisses() { // buffer size is 1, this will cause dropped writes on some threads where the buffer is full - cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default, - new LfuBufferSize(new StripedBufferSize(1, 1))); + cache = new ConcurrentLfu(1, 20, new NullScheduler(), EqualityComparer.Default); int threads = 4; int iterations = 100000; diff --git a/BitFaster.Caching.UnitTests/Lfu/LfuBufferSizeTests.cs b/BitFaster.Caching.UnitTests/Lfu/LfuBufferSizeTests.cs deleted file mode 100644 index ec3936b6..00000000 --- a/BitFaster.Caching.UnitTests/Lfu/LfuBufferSizeTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using BitFaster.Caching.Buffers; -using BitFaster.Caching.Lfu; -using FluentAssertions; -using Xunit; - -namespace BitFaster.Caching.UnitTests.Lfu -{ - public class LfuBufferSizeTests - { - [Fact] - public void WhenReadBufferIsNullThrows() - { - Action constructor = () => { var x = new LfuBufferSize(null); }; - - constructor.Should().Throw(); - } - - [SkippableTheory] - [InlineData(1, 3, 1, 32)] - [InlineData(1, 14, 1, 128)] - [InlineData(1, 50, 1, 128)] - [InlineData(1, 100, 1, 128)] - [InlineData(4, 100, 4, 128)] - [InlineData(16, 100, 8, 128)] // fails win - [InlineData(64, 100, 8, 128)] // fails win - [InlineData(1, 1000, 1, 128)] - [InlineData(4, 1000, 4, 128)] - [InlineData(32, 1000, 32, 128)] // fails win + fails mac - [InlineData(256, 100000, 32, 128)] // fails win + fails mac - public void CalculateDefaultBufferSize(int concurrencyLevel, int capacity, int expectedReadStripes, int expectedReadBuffer) - { - // Some of these tests depend on the CPU Core count - skip if run on a different config machine. - bool notExpectedCpuCount = Environment.ProcessorCount != 12; - bool concurrencyLevelThresholdExceeded = BitOps.CeilingPowerOfTwo(concurrencyLevel) > BitOps.CeilingPowerOfTwo(Environment.ProcessorCount * 2); - - Skip.If(concurrencyLevelThresholdExceeded && notExpectedCpuCount, "Test outcome depends on machine CPU count"); - - var bufferSize = LfuBufferSize.Default(concurrencyLevel, capacity); - - bufferSize.Read.StripeCount.Should().Be(expectedReadStripes); - bufferSize.Read.BufferSize.Should().Be(expectedReadBuffer); - } - } -} diff --git a/BitFaster.Caching/Buffers/StripedBufferSize.cs b/BitFaster.Caching/Buffers/StripedBufferSize.cs deleted file mode 100644 index a0f873f4..00000000 --- a/BitFaster.Caching/Buffers/StripedBufferSize.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; - -namespace BitFaster.Caching.Buffers -{ - /// - /// Represents the size of a striped buffer. - /// - public sealed class StripedBufferSize - { - /// - /// Initializes a new instance of the StripedBufferSize class with the specified buffer size and stripe count. - /// - /// The size of each striped buffer. - /// The number of stripes. - public StripedBufferSize(int bufferSize, int stripeCount) - { - if (bufferSize < 1) - { - throw new ArgumentOutOfRangeException(nameof(bufferSize)); - } - - if (stripeCount < 1) - { - throw new ArgumentOutOfRangeException(nameof(stripeCount)); - } - - BufferSize = BitOps.CeilingPowerOfTwo(bufferSize); - StripeCount = BitOps.CeilingPowerOfTwo(stripeCount); - } - - /// - /// The size of the buffer. Each stripe will be initialized with a buffer of this size. - /// - public int BufferSize { get; } - - /// - /// The number of stripes. - /// - public int StripeCount { get; } - } -} diff --git a/BitFaster.Caching/Buffers/StripedMpmcBuffer.cs b/BitFaster.Caching/Buffers/StripedMpmcBuffer.cs index 34470788..ed81ca73 100644 --- a/BitFaster.Caching/Buffers/StripedMpmcBuffer.cs +++ b/BitFaster.Caching/Buffers/StripedMpmcBuffer.cs @@ -20,21 +20,12 @@ public sealed class StripedMpmcBuffer /// The stripe count. /// The buffer size. public StripedMpmcBuffer(int stripeCount, int bufferSize) - : this(new StripedBufferSize(bufferSize, stripeCount)) - { - } - - /// - /// Initializes a new instance of the StripedMpmcBuffer class with the specified buffer size. - /// - /// The buffer size. - public StripedMpmcBuffer(StripedBufferSize bufferSize) - { - buffers = new MpmcBoundedBuffer[bufferSize.StripeCount]; + { + buffers = new MpmcBoundedBuffer[stripeCount]; - for (var i = 0; i < bufferSize.StripeCount; i++) + for (var i = 0; i < stripeCount; i++) { - buffers[i] = new MpmcBoundedBuffer(bufferSize.BufferSize); + buffers[i] = new MpmcBoundedBuffer(bufferSize); } } diff --git a/BitFaster.Caching/Buffers/StripedMpscBuffer.cs b/BitFaster.Caching/Buffers/StripedMpscBuffer.cs index 7b5c6fed..ad3d3fe5 100644 --- a/BitFaster.Caching/Buffers/StripedMpscBuffer.cs +++ b/BitFaster.Caching/Buffers/StripedMpscBuffer.cs @@ -23,21 +23,12 @@ public sealed class StripedMpscBuffer where T : class /// The stripe count. /// The buffer size. public StripedMpscBuffer(int stripeCount, int bufferSize) - : this(new StripedBufferSize(bufferSize, stripeCount)) { - } - - /// - /// Initializes a new instance of the StripedMpscBuffer class with the specified buffer size. - /// - /// The buffer size. - public StripedMpscBuffer(StripedBufferSize bufferSize) - { - buffers = new MpscBoundedBuffer[bufferSize.StripeCount]; + buffers = new MpscBoundedBuffer[stripeCount]; - for (var i = 0; i < bufferSize.StripeCount; i++) + for (var i = 0; i < stripeCount; i++) { - buffers[i] = new MpscBoundedBuffer(bufferSize.BufferSize); + buffers[i] = new MpscBoundedBuffer(bufferSize); } } diff --git a/BitFaster.Caching/Lfu/Builder/AsyncConcurrentLfuBuilder.cs b/BitFaster.Caching/Lfu/Builder/AsyncConcurrentLfuBuilder.cs index 08c41b1f..ba1b5a59 100644 --- a/BitFaster.Caching/Lfu/Builder/AsyncConcurrentLfuBuilder.cs +++ b/BitFaster.Caching/Lfu/Builder/AsyncConcurrentLfuBuilder.cs @@ -16,7 +16,7 @@ internal AsyncConcurrentLfuBuilder(LfuInfo info) /// public override IAsyncCache Build() { - return new ConcurrentLfu(info.ConcurrencyLevel, info.Capacity, info.Scheduler, info.KeyComparer, info.BufferConfiguration); + return new ConcurrentLfu(info.ConcurrencyLevel, info.Capacity, info.Scheduler, info.KeyComparer); } } } diff --git a/BitFaster.Caching/Lfu/Builder/LfuBuilderBase.cs b/BitFaster.Caching/Lfu/Builder/LfuBuilderBase.cs index 662cb103..630511e9 100644 --- a/BitFaster.Caching/Lfu/Builder/LfuBuilderBase.cs +++ b/BitFaster.Caching/Lfu/Builder/LfuBuilderBase.cs @@ -64,17 +64,6 @@ public TBuilder WithKeyComparer(IEqualityComparer comparer) return this as TBuilder; } - /// - /// Use the specified buffer configuration. Smaller buffers consume less memory, larger buffers can - /// increase concurrent throughput. - /// - /// A ConcurrentLfuBuilder - public TBuilder WithBufferConfiguration(LfuBufferSize bufferConfiguration) - { - this.info.BufferConfiguration = bufferConfiguration; - return this as TBuilder; - } - /// /// Builds a cache configured via the method calls invoked on the builder instance. /// diff --git a/BitFaster.Caching/Lfu/Builder/LfuInfo.cs b/BitFaster.Caching/Lfu/Builder/LfuInfo.cs index 18201b6a..d1f4e511 100644 --- a/BitFaster.Caching/Lfu/Builder/LfuInfo.cs +++ b/BitFaster.Caching/Lfu/Builder/LfuInfo.cs @@ -1,6 +1,5 @@ -using System; + using System.Collections.Generic; -using System.Text; using BitFaster.Caching.Lru; using BitFaster.Caching.Scheduler; @@ -8,8 +7,6 @@ namespace BitFaster.Caching.Lfu.Builder { internal sealed class LfuInfo { - private LfuBufferSize bufferConfiguration; - public int Capacity { get; set; } = 128; public int ConcurrencyLevel { get; set; } = Defaults.ConcurrencyLevel; @@ -17,17 +14,5 @@ internal sealed class LfuInfo public IScheduler Scheduler { get; set; } = new ThreadPoolScheduler(); public IEqualityComparer KeyComparer { get; set; } = EqualityComparer.Default; - - public LfuBufferSize BufferConfiguration - { - get - { - return this.bufferConfiguration ?? LfuBufferSize.Default(ConcurrencyLevel, Capacity); - } - set - { - bufferConfiguration = value; - } - } } } diff --git a/BitFaster.Caching/Lfu/ConcurrentLfu.cs b/BitFaster.Caching/Lfu/ConcurrentLfu.cs index c432fa3e..cc4cbcd0 100644 --- a/BitFaster.Caching/Lfu/ConcurrentLfu.cs +++ b/BitFaster.Caching/Lfu/ConcurrentLfu.cs @@ -32,6 +32,11 @@ public sealed class ConcurrentLfu : ICache, IAsyncCache, IBoun { private const int MaxWriteBufferRetries = 64; + /// + /// The default buffer size. + /// + public const int DefaultBufferSize = 128; + private readonly ConcurrentDictionary> dictionary; private readonly StripedMpscBuffer> readBuffer; @@ -59,7 +64,7 @@ public sealed class ConcurrentLfu : ICache, IAsyncCache, IBoun /// /// The capacity. public ConcurrentLfu(int capacity) - : this(Defaults.ConcurrencyLevel, capacity, new ThreadPoolScheduler(), EqualityComparer.Default, LfuBufferSize.Default(Defaults.ConcurrencyLevel, capacity)) + : this(Defaults.ConcurrencyLevel, capacity, new ThreadPoolScheduler(), EqualityComparer.Default) { } @@ -70,12 +75,13 @@ public ConcurrentLfu(int capacity) /// The capacity. /// The scheduler. /// The equality comparer. - /// The buffer size. - public ConcurrentLfu(int concurrencyLevel, int capacity, IScheduler scheduler, IEqualityComparer comparer, LfuBufferSize bufferSize) + public ConcurrentLfu(int concurrencyLevel, int capacity, IScheduler scheduler, IEqualityComparer comparer) { this.dictionary = new ConcurrentDictionary>(concurrencyLevel, capacity, comparer); - this.readBuffer = new StripedMpscBuffer>(bufferSize.Read); + // cap concurrency at proc count * 2 + int readStripes = Math.Min(BitOps.CeilingPowerOfTwo(concurrencyLevel), BitOps.CeilingPowerOfTwo(Environment.ProcessorCount * 2)); + this.readBuffer = new StripedMpscBuffer>(readStripes, DefaultBufferSize); // Cap the write buffer to the cache size, or 128. Whichever is smaller. int writeBufferSize = Math.Min(BitOps.CeilingPowerOfTwo(capacity), 128); diff --git a/BitFaster.Caching/Lfu/ConcurrentLfuBuilder.cs b/BitFaster.Caching/Lfu/ConcurrentLfuBuilder.cs index d4913ddf..022837b7 100644 --- a/BitFaster.Caching/Lfu/ConcurrentLfuBuilder.cs +++ b/BitFaster.Caching/Lfu/ConcurrentLfuBuilder.cs @@ -34,7 +34,7 @@ internal ConcurrentLfuBuilder(LfuInfo info) /// public override ICache Build() { - return new ConcurrentLfu(info.ConcurrencyLevel, info.Capacity, info.Scheduler, info.KeyComparer, info.BufferConfiguration); + return new ConcurrentLfu(info.ConcurrencyLevel, info.Capacity, info.Scheduler, info.KeyComparer); } } } diff --git a/BitFaster.Caching/Lfu/LfuBufferSize.cs b/BitFaster.Caching/Lfu/LfuBufferSize.cs deleted file mode 100644 index 862224a0..00000000 --- a/BitFaster.Caching/Lfu/LfuBufferSize.cs +++ /dev/null @@ -1,58 +0,0 @@ - -using System; -using BitFaster.Caching.Buffers; - -namespace BitFaster.Caching.Lfu -{ - /// - /// Represents the read and write buffer sizes used to initialize ConcurrentLfu. - /// - public class LfuBufferSize - { - /// - /// The default buffer size. - /// - public const int DefaultBufferSize = 128; - - /// - /// Initializes a new instance of the LfuBufferSize class with the specified read and write buffer sizes. - /// - /// The read buffer size. - public LfuBufferSize(StripedBufferSize readBufferSize) - { - Read = readBufferSize ?? throw new ArgumentNullException(nameof(readBufferSize)); - } - - /// - /// Gets the read buffer size. - /// - public StripedBufferSize Read { get; } - - /// - /// Estimates default buffer sizes intended to give optimal throughput. - /// - /// The estimated number of threads that will use the cache concurrently. - /// The capacity of the cache. The size of the write buffer is constained to avoid the cache growing to greater than 2x capacity while writes are buffered. - /// An LruBufferSize - public static LfuBufferSize Default(int concurrencyLevel, int capacity) - { - if (capacity < 13) - { - return new LfuBufferSize( - new StripedBufferSize(32, 1)); - } - - // cap concurrency at proc count * 2 - concurrencyLevel = Math.Min(BitOps.CeilingPowerOfTwo(concurrencyLevel), BitOps.CeilingPowerOfTwo(Environment.ProcessorCount * 2)); - - // cap read buffer at aprrox 10x total capacity - while (concurrencyLevel * DefaultBufferSize > BitOps.CeilingPowerOfTwo(capacity * 10)) - { - concurrencyLevel /= 2; - } - - return new LfuBufferSize( - new StripedBufferSize(DefaultBufferSize, concurrencyLevel)); - } - } -}