Skip to content

Instantly share code, notes, and snippets.

@JCKodel
Last active November 5, 2023 20:23
Show Gist options
  • Save JCKodel/d3467a66350af98ee61c74f5ebd804be to your computer and use it in GitHub Desktop.
Save JCKodel/d3467a66350af98ee61c74f5ebd804be to your computer and use it in GitHub Desktop.
6 methods of multithread Dictionary manipulation benchmark
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