Created
February 5, 2019 16:14
-
-
Save filipnavara/8e6aa10131e68d313934b006aea82abd to your computer and use it in GitHub Desktop.
This file contains hidden or 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 System; | |
| using System.Threading; | |
| namespace ThreadPoolBenchmark | |
| { | |
| static class DelayHelper | |
| { | |
| public static uint RandomShortDelay(Random rng) => (uint)rng.Next(4, 10); | |
| public static uint RandomMediumDelay(Random rng) => (uint)rng.Next(10, 15); | |
| public static uint RandomLongDelay(Random rng) => (uint)rng.Next(15, 20); | |
| private static int[] s_delayValues = new int[32]; | |
| public static void Delay(uint n) | |
| { | |
| Interlocked.MemoryBarrier(); | |
| s_delayValues[16] += (int)Fib(n); | |
| } | |
| private static uint Fib(uint n) | |
| { | |
| if (n <= 1) | |
| return n; | |
| return Fib(n - 2) + Fib(n - 1); | |
| } | |
| } | |
| } |
This file contains hidden or 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 System; | |
| using BenchmarkDotNet.Analysers; | |
| using BenchmarkDotNet.Attributes; | |
| using BenchmarkDotNet.Columns; | |
| using BenchmarkDotNet.Configs; | |
| using BenchmarkDotNet.Diagnosers; | |
| using BenchmarkDotNet.Environments; | |
| using BenchmarkDotNet.Exporters; | |
| using BenchmarkDotNet.Exporters.Csv; | |
| using BenchmarkDotNet.Jobs; | |
| using BenchmarkDotNet.Loggers; | |
| using BenchmarkDotNet.Running; | |
| using BenchmarkDotNet.Toolchains.CoreRt; | |
| using BenchmarkDotNet.Toolchains.CsProj; | |
| using BenchmarkDotNet.Toolchains.CustomCoreClr; | |
| using BenchmarkDotNet.Toolchains.DotNetCli; | |
| namespace ThreadPoolBenchmark | |
| { | |
| class Program | |
| { | |
| static void Main(string[] args) | |
| { | |
| var config = DefaultConfig.Instance | |
| .With(Job.CoreRT | |
| .With(CoreRtToolchain.CreateBuilder() | |
| .UseCoreRtLocal(@"/Volumes/TRANSCEND1/Projects/corert/bin/OSX.x64.Release") // IlcPath | |
| .DisplayName("Base") | |
| .ToToolchain())) | |
| .With(Job.CoreRT | |
| .With(CoreRtToolchain.CreateBuilder() | |
| .UseCoreRtLocal(@"/Volumes/TRANSCEND1/Projects/corert.lls/bin/OSX.x64.Release") // IlcPath | |
| .DisplayName("PR") | |
| .ToToolchain())); | |
| BenchmarkRunner.Run<ThreadPoolTest>(config); | |
| /*var dotnetCli = NetCoreAppSettings | |
| .NetCoreApp30 | |
| .WithCustomDotNetCliPath(@"C:\Program Files (x86)\dotnet\dotnet.exe", "32 bit cli"); | |
| BenchmarkRunner.Run<ThreadPoolTest>( | |
| ManualConfig.Create(DefaultConfig.Instance). | |
| With(Job.RyuJitX86.With(CsProjCoreToolchain.From(dotnetCli))));*/ | |
| } | |
| } | |
| } |
This file contains hidden or 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 BenchmarkDotNet.Attributes; | |
| using System; | |
| using System.Collections.Generic; | |
| using System.Text; | |
| using System.Threading; | |
| namespace ThreadPoolBenchmark | |
| { | |
| public class ThreadPoolTest | |
| { | |
| [ThreadStatic] | |
| private static Random t_rng; | |
| [ThreadStatic] | |
| private static int t_rngGeneration; | |
| private static int s_rngGeneration = 0; | |
| //[Params(1, 2, 4)] | |
| //public int ThreadCount { get; set; } | |
| [Params(100000)] | |
| public int Operations { get; set; } | |
| /*[GlobalSetup] | |
| public void GlobalSetup() | |
| { | |
| ThreadPool.SetMinThreads(ThreadCount, ThreadCount); | |
| ThreadPool.SetMaxThreads(ThreadCount, ThreadCount); | |
| }*/ | |
| [Benchmark] | |
| public void ThreadPoolSustainedWorkThroughput() | |
| { | |
| var endTest = new ManualResetEvent(false); | |
| var operationsToDo = Operations; | |
| // Ensure consistent random seeds | |
| s_rngGeneration++; | |
| WaitCallback workItemStart = null; | |
| workItemStart = data => | |
| { | |
| if (Interlocked.Decrement(ref operationsToDo) <= 0) | |
| { | |
| endTest.Set(); | |
| return; | |
| } | |
| ThreadPool.QueueUserWorkItem(workItemStart); | |
| var rng = t_rng; | |
| if (rng == null || t_rngGeneration != s_rngGeneration) | |
| { | |
| t_rng = rng = new Random(0); | |
| t_rngGeneration = s_rngGeneration; | |
| } | |
| DelayHelper.Delay(DelayHelper.RandomShortDelay(rng)); | |
| }; | |
| var localWorkItemStart = workItemStart; | |
| int initialWorkItemCount = Environment.ProcessorCount /*+ ThreadCount*/; | |
| for (int i = 0; i < initialWorkItemCount; ++i) | |
| ThreadPool.QueueUserWorkItem(localWorkItemStart); | |
| endTest.WaitOne(); | |
| } | |
| [Benchmark] | |
| [Arguments(1)] | |
| [Arguments(10)] | |
| [Arguments(100)] | |
| public void ThreadPoolBurstWorkThroughput(int maxWorkItemCount) | |
| { | |
| var workComplete = new AutoResetEvent(false); | |
| int workItemCountToQueue = 0; | |
| int workItemCountToComplete = 0; | |
| var operationsToDo = Operations; | |
| // Ensure consistent random seeds | |
| s_rngGeneration++; | |
| WaitCallback workItemStart = null; | |
| workItemStart = data => | |
| { | |
| if (Interlocked.Decrement(ref operationsToDo) <= 0) | |
| { | |
| workComplete.Set(); | |
| return; | |
| } | |
| if (Interlocked.Decrement(ref workItemCountToQueue) >= 0) | |
| ThreadPool.QueueUserWorkItem(workItemStart); | |
| var rng = t_rng; | |
| if (rng == null || t_rngGeneration != s_rngGeneration) | |
| { | |
| t_rng = rng = new Random(0); | |
| t_rngGeneration = s_rngGeneration; | |
| } | |
| DelayHelper.Delay(DelayHelper.RandomShortDelay(rng)); | |
| if (Interlocked.Decrement(ref workItemCountToComplete) == 0) | |
| workComplete.Set(); | |
| }; | |
| var localMaxWorkItemCount = maxWorkItemCount; | |
| var localWorkItemStart = workItemStart; | |
| int initialWorkItemCount = Math.Min(Environment.ProcessorCount, localMaxWorkItemCount); | |
| while (Thread.VolatileRead(ref operationsToDo) >= 0) | |
| { | |
| workItemCountToQueue = localMaxWorkItemCount - initialWorkItemCount; | |
| workItemCountToComplete = localMaxWorkItemCount; | |
| for (int i = 0; i < initialWorkItemCount; ++i) | |
| ThreadPool.QueueUserWorkItem(localWorkItemStart); | |
| workComplete.WaitOne(); | |
| } | |
| } | |
| /*[Benchmark] | |
| public void ThreadPoolSetMinThreads() | |
| { | |
| ThreadPool.SetMinThreads(1, 1); | |
| ThreadPool.SetMaxThreads(2, 2); | |
| }*/ | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment