Beispiel #1
0
        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");
            }
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #3
0
        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();
            }
        }
Beispiel #4
0
        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
                    );
            }
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        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);
            }
        }
Beispiel #7
0
        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
                    );
            }
        }
Beispiel #8
0
        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
                    );
            }
        }