Skip to content

Commit 0a53611

Browse files
authored
valuetask (#162)
* test * valuetask * proj * dead code
1 parent 49cd731 commit 0a53611

15 files changed

+66
-32
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
using BenchmarkDotNet.Attributes;
7+
using BenchmarkDotNet.Jobs;
8+
using BitFaster.Caching.Lru;
9+
10+
namespace BitFaster.Caching.Benchmarks.Lru
11+
{
12+
/// <summary>
13+
/// Verify 0 allocs for GetOrAddAsync cache hits.
14+
/// </summary>
15+
[SimpleJob(RuntimeMoniker.Net48)]
16+
[SimpleJob(RuntimeMoniker.Net60)]
17+
[DisassemblyDiagnoser(printSource: true, maxDepth: 5)]
18+
[MemoryDiagnoser]
19+
public class LruAsyncGet
20+
{
21+
// if the cache value is a value type, value task has no effect - so use string to repro.
22+
private static readonly IAsyncCache<int, string> concurrentLru = new ConcurrentLruBuilder<int, string>().AsAsyncCache().Build();
23+
private static readonly IAsyncCache<int, string> atomicConcurrentLru = new ConcurrentLruBuilder<int, string>().AsAsyncCache().WithAtomicCreate().Build();
24+
25+
private static Task<string> returnTask = Task.FromResult("1");
26+
27+
[Benchmark()]
28+
public async ValueTask<string> GetOrAddAsync()
29+
{
30+
Func<int, Task<string>> func = x => returnTask;
31+
32+
return await concurrentLru.GetOrAddAsync(1, func);
33+
}
34+
35+
[Benchmark()]
36+
public async ValueTask<string> AtomicGetOrAddAsync()
37+
{
38+
Func<int, Task<string>> func = x => returnTask;
39+
40+
return await atomicConcurrentLru.GetOrAddAsync(1, func);
41+
}
42+
}
43+
}

BitFaster.Caching.UnitTests/Synchronized/AsyncAtomicFactoryTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public async Task WhenCallersRunConcurrentlyResultIsFromWinner()
7070
var result = 0;
7171
var winnerCount = 0;
7272

73-
Task<int> first = atomicFactory.GetValueAsync(1, async k =>
73+
var first = atomicFactory.GetValueAsync(1, async k =>
7474
{
7575
enter.SetResult(true);
7676
await resume.Task;
@@ -80,7 +80,7 @@ public async Task WhenCallersRunConcurrentlyResultIsFromWinner()
8080
return 1;
8181
});
8282

83-
Task<int> second = atomicFactory.GetValueAsync(1, async k =>
83+
var second = atomicFactory.GetValueAsync(1, async k =>
8484
{
8585
enter.SetResult(true);
8686
await resume.Task;

BitFaster.Caching.UnitTests/Synchronized/AtomicFactoryCacheTests.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,6 @@ public void WhenKeyDoesNotExistGetOrAddAddsValue()
106106
value.Should().Be(1);
107107
}
108108

109-
[Fact]
110-
public async Task GetOrAddAsyncThrows()
111-
{
112-
Func<Task> getOrAdd = async () => { await this.cache.GetOrAddAsync(1, k => Task.FromResult(k)); };
113-
114-
await getOrAdd.Should().ThrowAsync<NotImplementedException>();
115-
}
116-
117109
[Fact]
118110
public void WhenCacheContainsValuesTrim1RemovesColdestValue()
119111
{

BitFaster.Caching.UnitTests/Synchronized/ScopedAsyncAtomicFactoryTests.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public async Task WhenCallersRunConcurrentlyResultIsFromWinner()
9898
var winningNumber = 0;
9999
var winnerCount = 0;
100100

101-
Task<(bool r, Lifetime<IntHolder> l)> first = atomicFactory.TryCreateLifetimeAsync(1, async k =>
101+
ValueTask<(bool r, Lifetime<IntHolder> l)> first = atomicFactory.TryCreateLifetimeAsync(1, async k =>
102102
{
103103
enter.SetResult(true);
104104
await resume.Task;
@@ -108,7 +108,7 @@ public async Task WhenCallersRunConcurrentlyResultIsFromWinner()
108108
return new Scoped<IntHolder>(new IntHolder() { actualNumber = 1 });
109109
});
110110

111-
Task<(bool r, Lifetime<IntHolder> l)> second = atomicFactory.TryCreateLifetimeAsync(1, async k =>
111+
ValueTask<(bool r, Lifetime<IntHolder> l)> second = atomicFactory.TryCreateLifetimeAsync(1, async k =>
112112
{
113113
enter.SetResult(true);
114114
await resume.Task;
@@ -142,7 +142,7 @@ public async Task WhenDisposedWhileInitResultIsDisposed()
142142
var atomicFactory = new ScopedAsyncAtomicFactory<int, IntHolder>();
143143
var holder = new IntHolder() { actualNumber = 1 };
144144

145-
Task<(bool r, Lifetime<IntHolder> l)> first = atomicFactory.TryCreateLifetimeAsync(1, async k =>
145+
ValueTask<(bool r, Lifetime<IntHolder> l)> first = atomicFactory.TryCreateLifetimeAsync(1, async k =>
146146
{
147147
enter.SetResult(true);
148148
await resume.Task;
@@ -171,7 +171,7 @@ public async Task WhenDisposedWhileThrowingNextInitIsDisposed()
171171
var atomicFactory = new ScopedAsyncAtomicFactory<int, IntHolder>();
172172
var holder = new IntHolder() { actualNumber = 1 };
173173

174-
Task<(bool r, Lifetime<IntHolder> l)> first = atomicFactory.TryCreateLifetimeAsync(1, async k =>
174+
ValueTask<(bool r, Lifetime<IntHolder> l)> first = atomicFactory.TryCreateLifetimeAsync(1, async k =>
175175
{
176176
enter.SetResult(true);
177177
await resume.Task;

BitFaster.Caching/BitFaster.Caching.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,8 @@
3939
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
4040
</ItemGroup>
4141

42+
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' or '$(TargetFramework)' == 'net48' or '$(TargetFramework)' == 'netstandard2.0'">
43+
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
44+
</ItemGroup>
45+
4246
</Project>

BitFaster.Caching/IAsyncCache.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public interface IAsyncCache<K, V>
4848
/// <param name="key">The key of the element to add.</param>
4949
/// <param name="valueFactory">The factory function used to asynchronously generate a value for the key.</param>
5050
/// <returns>A task that represents the asynchronous GetOrAdd operation.</returns>
51-
Task<V> GetOrAddAsync(K key, Func<K, Task<V>> valueFactory);
51+
ValueTask<V> GetOrAddAsync(K key, Func<K, Task<V>> valueFactory);
5252

5353
/// <summary>
5454
/// Attempts to remove the value that has the specified key.

BitFaster.Caching/IScopedAsyncCache.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public interface IScopedAsyncCache<K, V> where V : IDisposable
5353
/// <param name="key">The key of the element to add.</param>
5454
/// <param name="valueFactory">The factory function used to asynchronously generate a scoped value for the key.</param>
5555
/// <returns>A task that represents the asynchronous ScopedGetOrAdd operation.</returns>
56-
Task<Lifetime<V>> ScopedGetOrAddAsync(K key, Func<K, Task<Scoped<V>>> valueFactory);
56+
ValueTask<Lifetime<V>> ScopedGetOrAddAsync(K key, Func<K, Task<Scoped<V>>> valueFactory);
5757

5858
/// <summary>
5959
/// Attempts to remove the value that has the specified key.

BitFaster.Caching/Lru/ClassicLru.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public V GetOrAdd(K key, Func<K, V> valueFactory)
149149
}
150150

151151
///<inheritdoc/>
152-
public async Task<V> GetOrAddAsync(K key, Func<K, Task<V>> valueFactory)
152+
public async ValueTask<V> GetOrAddAsync(K key, Func<K, Task<V>> valueFactory)
153153
{
154154
if (this.TryGet(key, out var value))
155155
{

BitFaster.Caching/Lru/TemplateConcurrentLru.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public V GetOrAdd(K key, Func<K, V> valueFactory)
184184
}
185185

186186
///<inheritdoc/>
187-
public async Task<V> GetOrAddAsync(K key, Func<K, Task<V>> valueFactory)
187+
public async ValueTask<V> GetOrAddAsync(K key, Func<K, Task<V>> valueFactory)
188188
{
189189
while (true)
190190
{

BitFaster.Caching/ScopedAsyncCache.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public void Clear()
5353
}
5454

5555
///<inheritdoc/>
56-
public async Task<Lifetime<V>> ScopedGetOrAddAsync(K key, Func<K, Task<Scoped<V>>> valueFactory)
56+
public async ValueTask<Lifetime<V>> ScopedGetOrAddAsync(K key, Func<K, Task<Scoped<V>>> valueFactory)
5757
{
5858
int c = 0;
5959
var spinwait = new SpinWait();

0 commit comments

Comments
 (0)