Exemplo n.º 1
0
        public async Task RoundRobinDistributesFairlyWhenCalledConcurrently(string[] partitions)
        {
            var concurrentCount         = 4;
            var assignmentsPerPartition = 20;
            var iterationCount          = partitions.Length * assignmentsPerPartition;
            var resolver    = new PartitionResolver();
            var assigned    = new List <string>();
            var activeTasks = new List <Task>();

            // Create a function that assigns partitions in a loop and track them.

            Task roundRobin()
            {
                for (var index = 0; index < iterationCount; index++)
                {
                    assigned.Add(resolver.AssignRoundRobin(partitions));
                }

                return(Task.CompletedTask);
            }

            // Run assignment concurrently.

            for (var concurrentIndex = 0; concurrentIndex < concurrentCount; ++concurrentIndex)
            {
                activeTasks.Add(roundRobin());
            }

            await Task.WhenAll(activeTasks);

            // When grouped, the count of each partition should equal the iteration count for each
            // concurrent invocation.

            var partitionAssignments = assigned
                                       .GroupBy(item => item)
                                       .Select(group => new { Key = group.Key, Count = group.Count() });

            var assignmentHash          = new HashSet <string>();
            var expectedAssignmentCount = (concurrentCount * assignmentsPerPartition);

            // Verify that each assignment is for a valid partition and has the expected distribution.

            foreach (var partitionAssignment in partitionAssignments)
            {
                Assert.That(partitionAssignment.Count, Is.EqualTo(expectedAssignmentCount), $"The count for key: [{ partitionAssignment.Key}] should match the total number of iterations.");
                assignmentHash.Add(partitionAssignment.Key);
            }

            // Verify that all partitions were assigned.

            foreach (var partition in partitions)
            {
                Assert.That(assignmentHash.Contains(partition), Is.True, $"Partition: [{ partition }] should have had assignments.");
            }
        }
Exemplo n.º 2
0
        public void RoundRobinDistributesFairly(string[] partitions)
        {
            var resolver = new PartitionResolver();

            for (var index = 0; index < 100; index++)
            {
                var expected = partitions[index % partitions.Length];
                var assigned = resolver.AssignRoundRobin(partitions);

                Assert.That(assigned, Is.EqualTo(expected), $"The assignment was unexpected for index: [{ index }].");
            }
        }
Exemplo n.º 3
0
        public void RoundRobinRollsOverFairly(string[] partitions)
        {
            var assignmentsPerPartition = 20;
            var iterationCount          = partitions.Length * assignmentsPerPartition;
            var resolver = new PartitionResolver();
            var assigned = new List <string>();

            // Set the starting index for the resolver to something just below the
            // rollover point.

            SetPartitionIndex(resolver, (int.MaxValue - 4));

            for (var index = 0; index < iterationCount; index++)
            {
                assigned.Add(resolver.AssignRoundRobin(partitions));
            }

            // When grouped, the count of each partition should equal the iteration count for each
            // concurrent invocation.

            var partitionAssignments = assigned
                                       .GroupBy(item => item)
                                       .Select(group => new { Key = group.Key, Count = group.Count() });

            var assignmentHash = new HashSet <string>();

            // Verify that each assignment is for a valid partition and has the expected distribution.  Because
            // rollover can cause a small bit of assignment overlap due to the sequence change, allow for a small degree
            // of variance from the perfect fair distribution.

            foreach (var partitionAssignment in partitionAssignments)
            {
                Assert.That(partitionAssignment.Count, Is.EqualTo(assignmentsPerPartition).Within(2), $"The count for key: [{ partitionAssignment.Key}] should match the total number of iterations.");
                assignmentHash.Add(partitionAssignment.Key);
            }

            // Verify that all partitions were assigned.

            foreach (var partition in partitions)
            {
                Assert.That(assignmentHash.Contains(partition), Is.True, $"Partition: [{ partition }] should have had assignments.");
            }
        }
Exemplo n.º 4
0
        public async Task RoundRobinRollsOverFairlyWhenCalledConcurrently(string[] partitions)
        {
            var concurrentCount         = 4;
            var assignmentsPerPartition = 20;
            var iterationCount          = partitions.Length * assignmentsPerPartition;
            var resolver    = new PartitionResolver();
            var assigned    = new List <string>();
            var activeTasks = new List <Task>();

            // Set the starting index for the resolver to something just below the
            // rollover point.

            SetPartitionIndex(resolver, (int.MaxValue - 4));

            // Create a function that assigns partitions in a loop and track them.

            Task roundRobin()
            {
                for (var index = 0; index < iterationCount; index++)
                {
                    assigned.Add(resolver.AssignRoundRobin(partitions));
                }

                return(Task.CompletedTask);
            }

            // Run assignment concurrently.

            for (var concurrentIndex = 0; concurrentIndex < concurrentCount; ++concurrentIndex)
            {
                activeTasks.Add(roundRobin());
            }

            await Task.WhenAll(activeTasks);

            // When grouped, the count of each partition should equal the iteration count for each
            // concurrent invocation.

            var partitionAssignments = assigned
                                       .GroupBy(item => item)
                                       .Select(group => new { Key = group.Key, Count = group.Count() });

            var assignmentHash          = new HashSet <string>();
            var expectedAssignmentCount = (concurrentCount * assignmentsPerPartition);

            // Verify that each assignment is for a valid partition and has the expected distribution.  Because
            // rollover can cause a small bit of assignment overlap due to the sequence change, allow for a small degree
            // of variance from the perfect fair distribution.

            foreach (var partitionAssignment in partitionAssignments)
            {
                Assert.That(partitionAssignment.Count, Is.EqualTo(expectedAssignmentCount).Within(2), $"The count for key: [{ partitionAssignment.Key}] should match the total number of iterations.");
                assignmentHash.Add(partitionAssignment.Key);
            }

            // Verify that all partitions were assigned.

            foreach (var partition in partitions)
            {
                Assert.That(assignmentHash.Contains(partition), Is.True, $"Partition: [{ partition }] should have had assignments.");
            }
        }