private static void PerformSmokeTest(int capacity, int parallelism, TimeSpan duration, Action payload) { var semaphore = new LifoSemaphore(capacity); var tasks = new List <Task>(); var observedParallelism = 0; for (var i = 0; i < parallelism; i++) { tasks.Add( Task.Run( async() => { var watch = Stopwatch.StartNew(); while (watch.Elapsed < duration) { await semaphore.WaitAsync(); if (Interlocked.Increment(ref observedParallelism) > capacity) { throw new Exception($"Violated max allowed parallelism of {parallelism} (observed {observedParallelism})"); } payload(); Interlocked.Decrement(ref observedParallelism); semaphore.Release(); } })); } Task.WhenAll(tasks).GetAwaiter().GetResult(); semaphore.CurrentCount.Should().Be(capacity); semaphore.CurrentQueue.Should().Be(0); Console.Out.WriteLine($"Success: capacity = {capacity}, parallelism = {parallelism}, duration = {duration}."); }
public void Benchmark_multi_threaded_speed_vs_SemaphoreSlim(int capacity, int parallelism, int iterations) { var slimTimes = new List <double>(); var lifoTimes = new List <double>(); var slimSemaphore = new SemaphoreSlim(capacity, capacity); var lifoSemaphore = new LifoSemaphore(capacity); for (var i = 0; i < 5; i++) { var watch = Stopwatch.StartNew(); var tasks = new List <Task>(); for (var j = 0; j < parallelism; j++) { tasks.Add( Task.Run( async() => { for (var k = 0; k < iterations; k++) { await slimSemaphore.WaitAsync(); slimSemaphore.Release(); } })); } Task.WhenAll(tasks).GetAwaiter().GetResult(); slimTimes.Add(watch.Elapsed.TotalMilliseconds); Console.Out.WriteLine($"Slim: {watch.Elapsed.TotalMilliseconds:F2} ms"); } var avgSlimTime = slimTimes.Average(); Console.Out.WriteLine(); Console.Out.WriteLine($"Slim avg: {avgSlimTime:F2} ms"); Console.Out.WriteLine(); for (var i = 0; i < 5; i++) { var watch = Stopwatch.StartNew(); var tasks = new List <Task>(); for (var j = 0; j < parallelism; j++) { tasks.Add( Task.Run( async() => { for (var k = 0; k < iterations; k++) { await lifoSemaphore.WaitAsync(); lifoSemaphore.Release(); } })); } Task.WhenAll(tasks).GetAwaiter().GetResult(); lifoTimes.Add(watch.Elapsed.TotalMilliseconds); Console.Out.WriteLine($"Lifo: {watch.Elapsed.TotalMilliseconds:F2} ms"); } var avgLifoTime = lifoTimes.Average(); Console.Out.WriteLine(); Console.Out.WriteLine($"Lifo avg: {avgLifoTime:F2} ms"); Console.Out.WriteLine(); if (avgLifoTime < avgSlimTime) { Console.Out.WriteLine($"Winner is LifoSemaphore ({avgSlimTime / avgLifoTime:F2}x)!"); Assert.Pass(); } else { Console.Out.WriteLine($"Winner is SemaphoreSlim ({avgLifoTime / avgSlimTime:F2}x)!"); Assert.Inconclusive(); } }
public void WaitAsync_should_return_completed_tasks_immediately_until_count_goes_negative() { semaphore.WaitAsync().IsCompleted.Should().BeTrue(); semaphore.WaitAsync().IsCompleted.Should().BeTrue(); semaphore.WaitAsync().IsCompleted.Should().BeTrue(); }
public void Lifo() { lifoSemaphore.WaitAsync().GetAwaiter().GetResult(); lifoSemaphore.Release(); }