Last active
November 5, 2023 20:23
-
-
Save JCKodel/d3467a66350af98ee61c74f5ebd804be to your computer and use it in GitHub Desktop.
6 methods of multithread Dictionary manipulation benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.VisualStudio.TestTools.UnitTesting; | |
using System; | |
using System.Collections.Concurrent; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Threading.Tasks; | |
// 66ms: Dictionary with lock() | |
// 78ms: Dictionary with ReaderWriterLockSlim | |
// 128ms: ConcurrentDictionary (with Add if not exists) | |
// 137ms: ConcurrentDictionary (always setting) | |
// 434ms: DictionaryWithReaderWriterLock | |
// 535ms: DictionaryWithSemaphoreSlim (no-slim version is system wide... no, thank you) | |
namespace WebScaleFX.UnitTest | |
{ | |
[TestClass] | |
public class DictionaryPerformance | |
{ | |
[TestMethod] | |
public void DictionaryWithLock() // 66ms | |
{ | |
var dictionary = new Dictionary<int, int>(); | |
var random = new Random(); | |
Parallel.For(0, 1000000, c => | |
{ | |
var index = random.Next(0, 1000); | |
lock(dictionary) | |
{ | |
dictionary.TryGetValue(index, out var value); | |
value++; | |
dictionary[index] = value; | |
} | |
}); | |
} | |
[TestMethod] | |
public void DictionaryWithReaderWriterLockSlim() // 78ms | |
{ | |
var dictionary = new Dictionary<int, int>(); | |
var locker = new ReaderWriterLockSlim(); | |
var random = new Random(); | |
Parallel.For(0, 1000000, c => | |
{ | |
var index = random.Next(0, 1000); | |
locker.EnterWriteLock(); | |
dictionary.TryGetValue(index, out var value); | |
value++; | |
dictionary[index] = value; | |
locker.ExitWriteLock(); | |
}); | |
} | |
[TestMethod] | |
public void ConcurrentDictionaryAdd() // 128ms | |
{ | |
var dictionary = new ConcurrentDictionary<int, int>(); | |
var random = new Random(); | |
Parallel.For(0, 1000000, c => | |
{ | |
var index = random.Next(0, 1000); | |
var exists = dictionary.TryGetValue(index, out var value); | |
value++; | |
if(exists) | |
{ | |
dictionary[index] = value; | |
} | |
else | |
{ | |
dictionary.TryAdd(index, value); | |
} | |
}); | |
} | |
[TestMethod] | |
public void ConcurrentDictionarySet() // 137ms | |
{ | |
var dictionary = new ConcurrentDictionary<int, int>(); | |
var random = new Random(); | |
Parallel.For(0, 1000000, c => | |
{ | |
var index = random.Next(0, 1000); | |
dictionary.TryGetValue(index, out var value); | |
value++; | |
dictionary[index] = value; | |
}); | |
} | |
[TestMethod] | |
public void DictionaryWithReaderWriterLock() // 434ms | |
{ | |
var dictionary = new Dictionary<int, int>(); | |
var locker = new ReaderWriterLock(); | |
var random = new Random(); | |
Parallel.For(0, 1000000, c => | |
{ | |
var index = random.Next(0, 1000); | |
locker.AcquireWriterLock(1000); | |
dictionary.TryGetValue(index, out var value); | |
value++; | |
dictionary[index] = value; | |
locker.ReleaseWriterLock(); | |
}); | |
} | |
[TestMethod] | |
public void DictionaryWithSemaphoreSlim() // 535ms | |
{ | |
var dictionary = new Dictionary<int, int>(); | |
var semaphore = new SemaphoreSlim(1, 1); | |
var random = new Random(); | |
Parallel.For(0, 1000000, async c => | |
{ | |
var index = random.Next(0, 1000); | |
await semaphore.WaitAsync(); | |
dictionary.TryGetValue(index, out var value); | |
value++; | |
dictionary[index] = value; | |
semaphore.Release(); | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment