Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Lightweight.Caching.Benchmarks/Lru/LruCycle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class LruCycle
private static readonly FastConcurrentLru<int, int> fastConcurrentLru = new FastConcurrentLru<int, int>(8, 9, EqualityComparer<int>.Default);
private static readonly FastConcurrentTLru<int, int> fastConcurrentTLru = new FastConcurrentTLru<int, int>(8, 9, EqualityComparer<int>.Default, TimeSpan.FromMinutes(1));

private static MemoryCache memoryCache = MemoryCache.Default;
private static MemoryCache memoryCache = System.Runtime.Caching.MemoryCache.Default;

[GlobalSetup]
public void GlobalSetup()
Expand Down Expand Up @@ -60,7 +60,7 @@ public void GlobalSetup()
}

[Benchmark(Baseline = true, OperationsPerInvoke = 24)]
public void ConcurrentDictionaryGetOrAdd()
public void ConcurrentDictionary()
{
Func<int, int> func = x => x;
dictionary.GetOrAdd(1, func);
Expand Down Expand Up @@ -93,7 +93,7 @@ public void ConcurrentDictionaryGetOrAdd()
}

[Benchmark(OperationsPerInvoke = 24)]
public void FastConcurrentLruGetOrAdd()
public void FastConcurrentLru()
{
// size is 9, so segment size is 3. 6 items will cause queue cycling
// without eviction. Hot => cold when not accessed.
Expand Down Expand Up @@ -128,7 +128,7 @@ public void FastConcurrentLruGetOrAdd()
}

[Benchmark(OperationsPerInvoke = 24)]
public void ConcurrentLruGetOrAdd()
public void ConcurrentLru()
{
// size is 9, so segment size is 3. 6 items will cause queue cycling
// without eviction. Hot => cold when not accessed.
Expand Down Expand Up @@ -163,7 +163,7 @@ public void ConcurrentLruGetOrAdd()
}

[Benchmark(OperationsPerInvoke = 24)]
public void FastConcurrentTLruGetOrAdd()
public void FastConcurrentTLru()
{
// size is 9, so segment size is 3. 6 items will cause queue cycling
// without eviction. Hot => cold when not accessed.
Expand Down Expand Up @@ -198,7 +198,7 @@ public void FastConcurrentTLruGetOrAdd()
}

[Benchmark(OperationsPerInvoke = 24)]
public void ConcurrentTLruGetOrAdd()
public void ConcurrentTLru()
{
// size is 9, so segment size is 3. 6 items will cause queue cycling
// without eviction. Hot => cold when not accessed.
Expand Down Expand Up @@ -233,7 +233,7 @@ public void ConcurrentTLruGetOrAdd()
}

[Benchmark(OperationsPerInvoke = 24)]
public void ClassicLruGetOrAdd()
public void ClassicLru()
{
// size is 9, so segment size is 3. 6 items will cause queue cycling
// without eviction. Hot => cold when not accessed.
Expand Down Expand Up @@ -268,7 +268,7 @@ public void ClassicLruGetOrAdd()
}

[Benchmark(OperationsPerInvoke = 24)]
public void MemoryCacheGetStringKey()
public void MemoryCache()
{
memoryCache.Get("1");
memoryCache.Get("2");
Expand Down
12 changes: 0 additions & 12 deletions Lightweight.Caching.Benchmarks/Lru/LruGetOrAddTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,6 @@ public void ConcurrentDictionaryGetOrAdd()
dictionary.GetOrAdd(1, func);
}

//[Benchmark()]
//public DateTime DateTimeUtcNow()
//{
// return DateTime.UtcNow;
//}

[Benchmark()]
public void FastConcurrentLruGetOrAdd()
{
Expand Down Expand Up @@ -79,12 +73,6 @@ public void ClassicLruGetOrAdd()
classicLru.GetOrAdd(1, func);
}

//[Benchmark()]
//public void MemoryCacheGetIntKey()
//{
// memoryCache.Get(key.ToString());
//}

[Benchmark()]
public void MemoryCacheGetStringKey()
{
Expand Down
120 changes: 120 additions & 0 deletions Lightweight.Caching.Benchmarks/Lru/MissHitHitRemove.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.Caching;
using System.Text;
using BenchmarkDotNet.Attributes;
using Lightweight.Caching.Lru;

namespace Lightweight.Caching.Benchmarks.Lru
{
[MemoryDiagnoser]
public class MissHitHitRemove
{
const int capacity = 9;
const int arraySize = 16;

private static readonly ConcurrentDictionary<int, byte[]> dictionary = new ConcurrentDictionary<int, byte[]>(8, capacity, EqualityComparer<int>.Default);

private static readonly ClassicLru<int, byte[]> classicLru = new ClassicLru<int, byte[]>(8, capacity, EqualityComparer<int>.Default);
private static readonly ConcurrentLru<int, byte[]> concurrentLru = new ConcurrentLru<int, byte[]>(8, capacity, EqualityComparer<int>.Default);
private static readonly ConcurrentTLru<int, byte[]> concurrentTlru = new ConcurrentTLru<int, byte[]>(8, capacity, EqualityComparer<int>.Default, TimeSpan.FromMinutes(10));
private static readonly FastConcurrentLru<int, byte[]> fastConcurrentLru = new FastConcurrentLru<int, byte[]>(8, capacity, EqualityComparer<int>.Default);
private static readonly FastConcurrentTLru<int, byte[]> fastConcurrentTLru = new FastConcurrentTLru<int, byte[]>(8, capacity, EqualityComparer<int>.Default, TimeSpan.FromMinutes(1));

private static MemoryCache memoryCache = System.Runtime.Caching.MemoryCache.Default;

[Benchmark(Baseline = true)]
public void ConcurrentDictionary()
{
Func<int, byte[]> func = x => new byte[arraySize];
dictionary.GetOrAdd(1, func);

dictionary.GetOrAdd(1, func);
dictionary.GetOrAdd(1, func);

dictionary.TryRemove(1, out var removed);
}

[Benchmark()]
public void FastConcurrentLru()
{
Func<int, byte[]> func = x => new byte[arraySize];
fastConcurrentLru.GetOrAdd(1, func);

fastConcurrentLru.GetOrAdd(1, func);
fastConcurrentLru.GetOrAdd(1, func);

fastConcurrentLru.TryRemove(1);
}

[Benchmark()]
public void ConcurrentLru()
{
Func<int, byte[]> func = x => new byte[arraySize];
concurrentLru.GetOrAdd(1, func);

concurrentLru.GetOrAdd(1, func);
concurrentLru.GetOrAdd(1, func);

concurrentLru.TryRemove(1);
}

[Benchmark()]
public void FastConcurrentTlru()
{
Func<int, byte[]> func = x => new byte[arraySize];
fastConcurrentTLru.GetOrAdd(1, func);

fastConcurrentTLru.GetOrAdd(1, func);
fastConcurrentTLru.GetOrAdd(1, func);

fastConcurrentTLru.TryRemove(1);
}

[Benchmark()]
public void ConcurrentTlru()
{
Func<int, byte[]> func = x => new byte[arraySize];
concurrentTlru.GetOrAdd(1, func);

concurrentTlru.GetOrAdd(1, func);
concurrentTlru.GetOrAdd(1, func);

concurrentTlru.TryRemove(1);
}

[Benchmark()]
public void ClassicLru()
{
Func<int, byte[]> func = x => new byte[arraySize];
classicLru.GetOrAdd(1, func);

classicLru.GetOrAdd(1, func);
classicLru.GetOrAdd(1, func);

classicLru.TryRemove(1);
}

[Benchmark()]
public void MemoryCache()
{
if (memoryCache.Get("1") == null)
{
memoryCache.Set("1", new byte[arraySize], new CacheItemPolicy());
}

if (memoryCache.Get("1") == null)
{
memoryCache.Set("1", new byte[arraySize], new CacheItemPolicy());
}

if (memoryCache.Get("1") == null)
{
memoryCache.Set("1", new byte[arraySize], new CacheItemPolicy());
}

memoryCache.Remove("1");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace Lightweight.Caching.Benchmarks
{
[MemoryDiagnoser]
public class SegmentedLruTests
public class PrimitiveBenchmarks
{
private static readonly ConcurrentDictionary<int, int> dictionary = new ConcurrentDictionary<int, int>(8, 9, EqualityComparer<int>.Default);
LinkedList<int> intList = new LinkedList<int>(new int[] { 1, 2, 3 });
Expand Down Expand Up @@ -45,6 +45,12 @@ public void LinkedListLockSwapFirstToLast()
}
}

[Benchmark()]
public DateTime DateTimeUtcNow()
{
return DateTime.UtcNow;
}

[Benchmark()]
public void DictionaryGetOrAdd()
{
Expand Down
2 changes: 1 addition & 1 deletion Lightweight.Caching.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Program
static void Main(string[] args)
{
var summary = BenchmarkRunner
.Run<LruCycle>(ManualConfig.Create(DefaultConfig.Instance)
.Run<MissHitHitRemove>(ManualConfig.Create(DefaultConfig.Instance)
.AddJob(Job.RyuJitX64));
}
}
Expand Down
24 changes: 19 additions & 5 deletions Lightweight.Caching.UnitTests/Lru/ConcurrentLruTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,14 +141,14 @@ public async Task WhenDifferentKeysAreRequesteValueIsCreatedForEachAsync()
[Fact]
public void WhenValuesAreNotReadAndMoreKeysRequestedThanCapacityCountDoesNotIncrease()
{
int capacity = hotCap + coldCap;
for (int i = 0; i < capacity + 1; i++)
int hotColdCapacity = hotCap + coldCap;
for (int i = 0; i < hotColdCapacity + 1; i++)
{
lru.GetOrAdd(i, valueFactory.Create);
}

lru.Count.Should().Be(capacity);
valueFactory.timesCalled.Should().Be(capacity + 1);
lru.Count.Should().Be(hotColdCapacity);
valueFactory.timesCalled.Should().Be(hotColdCapacity + 1);
}

[Fact]
Expand Down Expand Up @@ -352,7 +352,21 @@ public void WhenKeyDoesNotExistTryRemoveReturnsFalse()
lru.TryRemove(2).Should().BeFalse();
}

private class DisposableItem : IDisposable
[Fact]
public void WhenRepeatedlyAddingAndRemovingSameValueLruRemainsInConsistentState()
{
int capacity = hotCap + coldCap + warmCap;
for (int i = 0; i < capacity; i++)
{
// Because TryRemove leaves the item in the queue, when it is eventually removed
// from the cold queue, it should not remove the newly created value.
lru.GetOrAdd(1, valueFactory.Create);
lru.TryGet(1, out var value).Should().BeTrue();
lru.TryRemove(1);
}
}

private class DisposableItem : IDisposable
{
public bool IsDisposed { get; private set; }

Expand Down
2 changes: 1 addition & 1 deletion Lightweight.Caching/Lightweight.Caching.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Version>0.9.1</Version>
<Copyright>Copyright © Alex Peck 2020</Copyright>
<PackageProjectUrl></PackageProjectUrl>
<RepositoryUrl>https://github.com/plexcake/Lightweight.Caching</RepositoryUrl>
<RepositoryUrl>https://github.com/bitfaster/Lightweight.Caching</RepositoryUrl>
<PackageTags>Cache</PackageTags>
</PropertyGroup>

Expand Down
11 changes: 9 additions & 2 deletions Lightweight.Caching/Lru/LruItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ namespace Lightweight.Caching.Lru
public class LruItem<K, V>
{
private bool wasAccessed;
private bool wasRemoved;

public LruItem(K k, V v)
public LruItem(K k, V v)
{
this.Key = k;
this.Value = v;
Expand All @@ -25,5 +26,11 @@ public bool WasAccessed
get => this.wasAccessed;
set => this.wasAccessed = value;
}
}

public bool WasRemoved
{
get => this.wasRemoved;
set => this.wasRemoved = value;
}
}
}
Loading