Skip to content

Commit 198ddd3

Browse files
committed
Add some basic benchmark tests to measure synchronization primitives
1 parent b9dabaf commit 198ddd3

File tree

2 files changed

+136
-0
lines changed

2 files changed

+136
-0
lines changed
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using BenchmarkDotNet.Attributes;
5+
using SixLabors.ImageSharp.Web.Synchronization;
6+
7+
namespace SixLabors.ImageSharp.Web.Benchmarks.Synchronization
8+
{
9+
/// <summary>
10+
/// Each of these tests obtains a lock (which completes synchronously as nobody else is holding the lock)
11+
/// and then releases that lock.
12+
/// </summary>
13+
[Config(typeof(MemoryConfig))]
14+
public class AsyncLockBenchmarks
15+
{
16+
private readonly AsyncLock asyncLock = new();
17+
private readonly AsyncReaderWriterLock asyncReaderWriterLock = new();
18+
private readonly AsyncKeyLock<string> asyncKeyLock = new();
19+
private readonly AsyncKeyReaderWriterLock<string> asyncKeyReaderWriterLock = new();
20+
21+
[Benchmark]
22+
public void AsyncLock() => this.asyncLock.LockAsync().Result.Dispose();
23+
24+
[Benchmark]
25+
public void AsyncReaderWriterLock_Reader() => this.asyncReaderWriterLock.ReaderLockAsync().Result.Dispose();
26+
27+
[Benchmark]
28+
public void AsyncReaderWriterLock_Writer() => this.asyncReaderWriterLock.WriterLockAsync().Result.Dispose();
29+
30+
[Benchmark]
31+
public void AsyncKeyLock() => this.asyncKeyLock.LockAsync("key").Result.Dispose();
32+
33+
[Benchmark]
34+
public void AsyncKeyReaderWriterLock_Reader() => this.asyncKeyReaderWriterLock.ReaderLockAsync("key").Result.Dispose();
35+
36+
[Benchmark]
37+
public void AsyncKeyReaderWriterLock_Writer() => this.asyncKeyReaderWriterLock.WriterLockAsync("key").Result.Dispose();
38+
39+
/*
40+
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1348 (21H1/May2021Update)
41+
Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical cores
42+
.NET SDK=6.0.100
43+
[Host] : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT
44+
DefaultJob : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT
45+
46+
47+
| Method | Mean | Error | StdDev | Gen 0 | Allocated |
48+
|-------------------------------- |----------:|---------:|---------:|-------:|----------:|
49+
| AsyncLock | 34.93 ns | 0.144 ns | 0.135 ns | - | - |
50+
| AsyncReaderWriterLock_Reader | 28.45 ns | 0.117 ns | 0.109 ns | - | - |
51+
| AsyncReaderWriterLock_Writer | 28.66 ns | 0.125 ns | 0.117 ns | - | - |
52+
| AsyncKeyLock | 276.48 ns | 5.379 ns | 5.031 ns | 0.0210 | 176 B |
53+
| AsyncKeyReaderWriterLock_Reader | 261.96 ns | 1.522 ns | 1.423 ns | 0.0210 | 176 B |
54+
| AsyncKeyReaderWriterLock_Writer | 266.35 ns | 1.661 ns | 1.554 ns | 0.0210 | 176 B |
55+
*/
56+
}
57+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System.Collections.Concurrent;
5+
using BenchmarkDotNet.Attributes;
6+
using SixLabors.ImageSharp.Web.Synchronization;
7+
8+
namespace SixLabors.ImageSharp.Web.Benchmarks.Synchronization
9+
{
10+
[Config(typeof(MemoryConfig))]
11+
public class RefCountedConcurrentDictionaryBenchmarks
12+
{
13+
private readonly object testObj;
14+
private readonly RefCountedConcurrentDictionary<string, object> refCountedDictionary;
15+
16+
private readonly ConcurrentDictionary<string, object> dictionary;
17+
18+
public RefCountedConcurrentDictionaryBenchmarks()
19+
{
20+
this.testObj = new object();
21+
this.refCountedDictionary = new RefCountedConcurrentDictionary<string, object>((_) => this.testObj, null);
22+
23+
this.dictionary = new ConcurrentDictionary<string, object>();
24+
25+
this.refCountedDictionary.Get("foo");
26+
this.dictionary.TryAdd("foo", this.testObj);
27+
}
28+
29+
[Benchmark]
30+
public void RefCountedConcurrentDictionary_ExistingKey()
31+
{
32+
this.refCountedDictionary.Get("foo");
33+
this.refCountedDictionary.Release("foo");
34+
}
35+
36+
[Benchmark]
37+
public void RefCountedConcurrentDictionary_ExistingKey_JustGet()
38+
{
39+
this.refCountedDictionary.Get("foo");
40+
}
41+
42+
[Benchmark]
43+
public void ConcurrentDictionary_ExistingKey_JustGet()
44+
{
45+
this.dictionary.GetOrAdd("foo", this.testObj);
46+
}
47+
48+
[Benchmark]
49+
public void RefCountedConcurrentDictionary_NewKey()
50+
{
51+
this.refCountedDictionary.Get("bar");
52+
this.refCountedDictionary.Release("bar");
53+
}
54+
55+
[Benchmark]
56+
public void ConcurrentDictionary_NewKey()
57+
{
58+
this.dictionary.GetOrAdd("bar", this.testObj);
59+
this.dictionary.TryRemove("bar", out _);
60+
}
61+
62+
/*
63+
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19043.1348 (21H1/May2021Update)
64+
Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical cores
65+
.NET SDK=6.0.100
66+
[Host] : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT
67+
DefaultJob : .NET Core 3.1.21 (CoreCLR 4.700.21.51404, CoreFX 4.700.21.51508), X64 RyuJIT
68+
69+
70+
| Method | Mean | Error | StdDev | Gen 0 | Allocated |
71+
|--------------------------------------------------- |----------:|---------:|---------:|-------:|----------:|
72+
| RefCountedConcurrentDictionary_ExistingKey | 138.65 ns | 1.077 ns | 1.007 ns | 0.0076 | 64 B |
73+
| RefCountedConcurrentDictionary_ExistingKey_JustGet | 68.00 ns | 0.372 ns | 0.310 ns | 0.0038 | 32 B |
74+
| ConcurrentDictionary_ExistingKey_JustGet | 16.54 ns | 0.117 ns | 0.104 ns | - | - |
75+
| RefCountedConcurrentDictionary_NewKey | 131.50 ns | 0.253 ns | 0.237 ns | 0.0095 | 80 B |
76+
| ConcurrentDictionary_NewKey | 83.55 ns | 0.375 ns | 0.351 ns | 0.0057 | 48 B |
77+
*/
78+
}
79+
}

0 commit comments

Comments
 (0)