public void PriorityTest() { using (var group = new ThreadGroup(2, createBackgroundThreads: true, name: "PriorityTest") { DefaultConcurrencyPadding = 0 }) { var queue = group.GetQueueForType <HighPriorityBlockingWorkItem>(); var barrier1 = new HighPriorityBlockingWorkItem { Signal = new AutoResetEvent(false) }; queue.Enqueue(barrier1); var barrier2 = new HighPriorityBlockingWorkItem { Signal = new AutoResetEvent(false) }; queue.Enqueue(barrier2); var barrier3 = new HighPriorityBlockingWorkItem { Signal = new AutoResetEvent(false) }; queue.Enqueue(barrier3); group.NotifyQueuesChanged(); // HACK: Give the thread group time to start processing high priority items while (queue.ItemsInFlight < group.ThreadCount) { Thread.Sleep(1); } var voidQueue = group.GetQueueForType <VoidWorkItem>(); var testItem = new VoidWorkItem(); for (int i = 0; i < 10; i++) { voidQueue.Enqueue(testItem); } group.NotifyQueuesChanged(); var ok = voidQueue.WaitUntilDrained(50); Assert.IsFalse(ok, "wait for low priority queue to drain while threads are blocked on high priority"); barrier1.Signal.Set(); Assert.IsFalse(voidQueue.WaitUntilDrained(50), "ensure new high priority item is claimed by thread that finished previous one"); barrier2.Signal.Set(); barrier3.Signal.Set(); ok = voidQueue.WaitUntilDrained(500); Assert.IsTrue(ok, "once high priority items are done the low priority ones should run"); } }
public void ManuallyStep() { using (var group = new ThreadGroup(0, 0)) { var queue = group.GetQueueForType <TestWorkItem>(); var item = new TestWorkItem(); Assert.IsFalse(item.Ran); queue.Enqueue(item); bool exhausted; queue.Step(out exhausted, 1); Assert.IsTrue(exhausted); Assert.IsTrue(item.Ran); } }
public void AutoSpawnMoreThreads() { using (var group = new ThreadGroup(0, 2)) { var queue = group.GetQueueForType <SleepyWorkItem>(); queue.Enqueue(new SleepyWorkItem()); group.NotifyQueuesChanged(); Assert.GreaterOrEqual(1, group.Count); queue.Enqueue(new SleepyWorkItem()); group.NotifyQueuesChanged(); Assert.GreaterOrEqual(2, group.Count); queue.WaitUntilDrained(); } }
public void MultipleThreadPerformanceTest() { const int count = 800; var timeProvider = Time.DefaultTimeProvider; using (var group = new ThreadGroup(4, createBackgroundThreads: true, name: "MultipleThreadPerformanceTest") { DefaultConcurrencyPadding = 0 }) { var queue = group.GetQueueForType <SlightlySlowWorkItem>(); var item = new SlightlySlowWorkItem(); var beforeEnqueue = timeProvider.Ticks; for (int i = 0; i < count; i++) { queue.Enqueue(ref item, notifyChanged: false); // Notify the group periodically that we've added new work items. // This ensures it spins up a reasonable number of threads. if ((i % 500) == 0) { group.NotifyQueuesChanged(); } } var afterEnqueue = timeProvider.Ticks; var beforeWait = timeProvider.Ticks; queue.WaitUntilDrained(10000); var afterWait = timeProvider.Ticks; var perItem = (afterWait - beforeWait) / (double)count / Time.MillisecondInTicks; Console.WriteLine( "Enqueue took {0:0000.00}ms, Wait took {1:0000.00}ms. Est speed {3:0.000000}ms/item Final thread count: {2}", TimeSpan.FromTicks(afterEnqueue - beforeEnqueue).TotalMilliseconds, TimeSpan.FromTicks(afterWait - beforeWait).TotalMilliseconds, group.Count, perItem ); } }
public void ManuallyStep() { using (var group = new ThreadGroup(0, createBackgroundThreads: true, name: "ManuallyStep") { DefaultConcurrencyPadding = 0 }) { var queue = group.GetQueueForType <TestWorkItem>(); var item = new TestWorkItem(); Assert.IsFalse(item.Ran); queue.Enqueue(item); bool exhausted; queue.Step(out exhausted, 1); Assert.IsTrue(exhausted); Assert.IsTrue(item.Ran); } }
public void AutoSpawnThread() { using (var group = new ThreadGroup(0, 1)) { var queue = group.GetQueueForType <TestWorkItem>(); var item = new TestWorkItem(); Assert.IsFalse(item.Ran); queue.Enqueue(item); Assert.AreEqual(0, group.Count); Assert.IsFalse(item.Ran); group.NotifyQueuesChanged(); Assert.AreEqual(1, group.Count); queue.WaitUntilDrained(); Assert.IsTrue(item.Ran); } }
public void MultipleThreadPerformanceTest() { const int count = 500000; var timeProvider = Time.DefaultTimeProvider; using (var group = new ThreadGroup(1)) { var queue = group.GetQueueForType <VoidWorkItem>(); queue.DefaultStepCount = 1024; var item = new VoidWorkItem(); var beforeEnqueue = timeProvider.Ticks; for (int i = 0; i < count; i++) { queue.Enqueue(ref item); // Notify the group periodically that we've added new work items. // This ensures it spins up a reasonable number of threads. if ((i % 20000) == 0) { group.NotifyQueuesChanged(); } } var afterEnqueue = timeProvider.Ticks; var beforeWait = timeProvider.Ticks; queue.WaitUntilDrained(); var afterWait = timeProvider.Ticks; Console.WriteLine( "Enqueue took {0:0000.00}ms, Wait took {1:0000.00}ms. Final thread count: {2}", TimeSpan.FromTicks(afterEnqueue - beforeEnqueue).TotalMilliseconds, TimeSpan.FromTicks(afterWait - beforeWait).TotalMilliseconds, group.Count ); } }
public void MainThreadPerformanceTest() { const int count = 200; var timeProvider = Time.DefaultTimeProvider; using (var group = new ThreadGroup(1, createBackgroundThreads: true, name: "MainThreadPerformanceTest") { DefaultConcurrencyPadding = 0 }) { var queue = group.GetQueueForType <SlightlySlowWorkItem>(forMainThread: true); var item = new SlightlySlowWorkItem(); var beforeEnqueue = timeProvider.Ticks; for (int i = 0; i < count; i++) { queue.Enqueue(ref item, notifyChanged: false); } var afterEnqueue = timeProvider.Ticks; var beforeWait = timeProvider.Ticks; while (!queue.IsEmpty) { group.StepMainThread(); } var afterWait = timeProvider.Ticks; var perItem = (afterWait - beforeWait) / (double)count / Time.MillisecondInTicks; Console.WriteLine( "Enqueue took {0:0000.00}ms, Wait took {1:0000.00}ms. Est speed {3:0.000000}ms/item Final thread count: {2}", TimeSpan.FromTicks(afterEnqueue - beforeEnqueue).TotalMilliseconds, TimeSpan.FromTicks(afterWait - beforeWait).TotalMilliseconds, group.Count, perItem ); } }