private static void RunSingleTestSet(TestConfiguration config, string fileName, Func <TestConfiguration, Qoollo.Turbo.Threading.ThreadPools.ThreadPoolBase> poolConstructor, bool waitForCompletion = true, bool doDispose = true) { Qoollo.Turbo.Threading.ThreadPools.ThreadPoolBase pool = null; try { pool = poolConstructor(config); { var testRes = RunTestOnPool(pool, config, waitForCompletion); string msg = pool.GetType().Name + config.ToString() + " == " + testRes.TotalMilliseconds.ToString() + "ms"; Console.WriteLine(msg); if (fileName != null) { File.AppendAllLines(fileName, new string[] { msg }); } } } finally { if (doDispose && pool != null) { pool.Dispose(); } } }
private static TimeSpan RunTestOnPool(Qoollo.Turbo.Threading.ThreadPools.ThreadPoolBase pool, TestConfiguration config, bool waitForCompletion = true) { var taskActiveTimeDev = (int)(config.ActiveTaskAvgTime.Ticks / 4); var taskPassiveTimeDev = (int)(config.PassiveTaskAvgTime.Ticks / 4); Random rndGenerator = new Random(); int executedTaskCounter = 0; int completedTaskCount = 0; Action taskAction = null; taskAction = () => { if (config.PassiveTaskAvgTime > TimeSpan.Zero) { TimeSpan taskTime = config.PassiveTaskAvgTime; if (config.UseDeviance) { lock (rndGenerator) taskTime += TimeSpan.FromTicks(rndGenerator.Next(-taskPassiveTimeDev, taskPassiveTimeDev)); } int taskTimeMs = CalcRandSleep(rndGenerator, taskTime.TotalMilliseconds); if (taskTimeMs > 0) { Thread.Sleep(taskTimeMs); } else if (taskTimeMs == 0) { Thread.Yield(); } } // ---- if (config.ActiveTaskAvgTime > TimeSpan.Zero) { TimeSpan taskTime = config.ActiveTaskAvgTime; if (config.UseDeviance) { lock (rndGenerator) taskTime += TimeSpan.FromTicks(rndGenerator.Next(-taskActiveTimeDev, taskActiveTimeDev)); } int taskTimeMs = CalcRandSleep(rndGenerator, taskTime.TotalMilliseconds); if (taskTimeMs > 0) { Stopwatch sw111 = Stopwatch.StartNew(); while (sw111.ElapsedMilliseconds < taskTimeMs) { SpinWaitHelper.SpinWait(2000); } } else if (taskTimeMs == 0) { Thread.Yield(); } } // ---- if (config.SpawnFromPool) { if (Interlocked.Increment(ref executedTaskCounter) <= config.TaskCount) { //pool.RunAsTask(taskAction); pool.Run(taskAction); } } Interlocked.Increment(ref completedTaskCount); }; Barrier bar = new Barrier(config.SpawnThreadCount + 1); Random spawnRndGenerator = new Random(); int spawnTimeDev = (int)(config.SpawnPeriod.Ticks / 4); Thread[] spawnThreads = new Thread[config.SpawnThreadCount]; ThreadStart spawnAction = () => { bar.SignalAndWait(); long expectedSleep = 0; long realSleep = 0; int curSpawned = 0; while ((curSpawned = Interlocked.Increment(ref executedTaskCounter)) <= config.TaskCount) { //pool.RunAsTask(taskAction); pool.Run(taskAction); TimeSpan spawnSleep = config.SpawnPeriod; if (config.UseDeviance) { lock (spawnRndGenerator) spawnSleep += TimeSpan.FromTicks(spawnRndGenerator.Next(-spawnTimeDev, spawnTimeDev)); } int spawnSleepMs = CalcRandSleep(spawnRndGenerator, spawnSleep.TotalMilliseconds); if (spawnSleepMs > 0) { expectedSleep += spawnSleepMs; int startTick = Environment.TickCount; if (realSleep <= expectedSleep) { Thread.Sleep(spawnSleepMs); } realSleep += (Environment.TickCount - startTick); } } }; for (int i = 0; i < spawnThreads.Length; i++) { spawnThreads[i] = new Thread(spawnAction); } for (int i = 0; i < spawnThreads.Length; i++) { spawnThreads[i].Start(); } bar.SignalAndWait(); Stopwatch sw = Stopwatch.StartNew(); if (waitForCompletion) { SpinWait.SpinUntil(() => Volatile.Read(ref completedTaskCount) >= config.TaskCount); } else { SpinWait.SpinUntil(() => Volatile.Read(ref executedTaskCounter) >= config.TaskCount); } sw.Stop(); if (waitForCompletion && completedTaskCount != config.TaskCount) { throw new Exception("completedTaskCount != config.TaskCount"); } return(sw.Elapsed); }