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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
<PackageReference Include="MathNet.Numerics" Version="4.11.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.1.5" />
<PackageReference Include="System.Runtime.Caching" Version="4.7.0" />
</ItemGroup>

Expand Down
40 changes: 30 additions & 10 deletions BitFaster.Caching.Benchmarks/Lru/LruJustGet.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using BenchmarkDotNet.Attributes;
using BitFaster.Caching;
using BitFaster.Caching.Benchmarks.Lru;
using BitFaster.Caching.Lru;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading.Tasks;

Expand All @@ -23,60 +24,79 @@ public class LruJustGet
private static readonly FastConcurrentTLru<int, int> fastConcurrentTLru = new FastConcurrentTLru<int, int>(8, 9, EqualityComparer<int>.Default, TimeSpan.FromMinutes(1));

private static readonly int key = 1;
private static MemoryCache memoryCache = MemoryCache.Default;
private static System.Runtime.Caching.MemoryCache memoryCache = System.Runtime.Caching.MemoryCache.Default;

Microsoft.Extensions.Caching.Memory.MemoryCache exMemoryCache
= new Microsoft.Extensions.Caching.Memory.MemoryCache(new MemoryCacheOptionsAccessor());

[GlobalSetup]
public void GlobalSetup()
{
memoryCache.Set(key.ToString(), "test", new CacheItemPolicy());
memoryCache.Set(key.ToString(), "test", new System.Runtime.Caching.CacheItemPolicy());
exMemoryCache.Set(key, "test");
}

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

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

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

[Benchmark()]
public void FastConcurrentTLruGetOrAdd()
public void FastConcurrentTLru()
{
Func<int, int> func = x => x;
fastConcurrentTLru.GetOrAdd(1, func);
}

[Benchmark()]
public void ConcurrentTLruGetOrAdd()
public void ConcurrentTLru()
{
Func<int, int> func = x => x;
concurrentTlru.GetOrAdd(1, func);
}

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

[Benchmark()]
public void MemoryCacheGetStringKey()
public void RuntimeMemoryCacheGet()
{
memoryCache.Get("1");
}

[Benchmark()]
public void ExtensionsMemoryCacheGet()
{
exMemoryCache.Get(1);
}

public class MemoryCacheOptionsAccessor
: Microsoft.Extensions.Options.IOptions<MemoryCacheOptions>
{
private readonly MemoryCacheOptions options = new MemoryCacheOptions();

public MemoryCacheOptions Value => this.options;

}
}
}
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,16 @@ In this test the same items are fetched repeatedly, no items are evicted. Repres

FastConcurrentLru does not allocate and is approximately 10x faster than MemoryCache.

| Method | Mean | Error | StdDev | Ratio | Gen 0 | Allocated |
|--------------------- |----------:|---------:|---------:|------:|-------:|----------:|
| ConcurrentDictionary | 15.06 ns | 0.286 ns | 0.307 ns | 1.00 | - | - |
| FastConcurrentLru | 20.70 ns | 0.276 ns | 0.258 ns | 1.37 | - | - |
| ConcurrentLru | 24.09 ns | 0.270 ns | 0.253 ns | 1.60 | - | - |
| FastConcurrentTLru | 49.57 ns | 0.619 ns | 0.517 ns | 3.30 | - | - |
| ConcurrentTLru | 64.82 ns | 2.547 ns | 7.391 ns | 4.50 | - | - |
| ClassicLru | 76.78 ns | 1.412 ns | 3.039 ns | 5.25 | - | - |
| MemoryCache | 278.37 ns | 3.887 ns | 3.035 ns | 18.50 | 0.0153 | 32 B |

| Method | Mean | Error | StdDev | Ratio | Gen 0 | Allocated |
|---------------------- |----------:|---------:|---------:|------:|-------:|----------:|
| ConcurrentDictionary | 16.88 ns | 0.276 ns | 0.245 ns | 1.00 | - | - |
| FastConcurrentLru | 23.27 ns | 0.491 ns | 0.565 ns | 1.38 | - | - |
| ConcurrentLru | 26.77 ns | 0.512 ns | 0.666 ns | 1.60 | - | - |
| FastConcurrentTLru | 54.35 ns | 0.650 ns | 0.576 ns | 3.22 | - | - |
| ConcurrentTLru | 60.10 ns | 1.024 ns | 1.501 ns | 3.53 | - | - |
| ClassicLru | 68.04 ns | 1.400 ns | 2.221 ns | 4.12 | - | - |
| RuntimeMemoryCache | 280.16 ns | 5.607 ns | 7.486 ns | 16.59 | 0.0153 | 32 B |
| ExtensionsMemoryCache | 342.72 ns | 3.729 ns | 3.114 ns | 20.29 | 0.0114 | 24 B |

## Meta-programming using structs for JIT dead code removal and inlining

Expand Down