Пример #1
0
        public void AsyncPipelineSimpleTest()
        {
            int       step     = 2000;
            int       epsilon  = 200;
            var       pipeline = new AsyncPipeline(2);
            var       done     = TimedCompletions(step, step, step);
            Stopwatch watch    = Stopwatch.StartNew();

            pipeline.Add(done[0]);
            var elapsed0 = watch.ElapsedMilliseconds;

            Assert.True(elapsed0 < epsilon, $"{elapsed0}ms");
            pipeline.Add(done[2]);
            var elapsed1 = watch.ElapsedMilliseconds;

            Assert.True(elapsed1 < epsilon, $"{elapsed1}ms");
            pipeline.Add(done[1]);
            var elapsed2 = watch.ElapsedMilliseconds;

            Assert.True(step - epsilon <= elapsed2, $"{elapsed2}ms");
            Assert.True(elapsed2 <= step + epsilon, $"{elapsed2}ms");
            pipeline.Wait();
            watch.Stop();
            Assert.True(3 * step - epsilon <= watch.ElapsedMilliseconds, $"{watch.ElapsedMilliseconds}ms");
            Assert.True(watch.ElapsedMilliseconds <= 3 * step + epsilon, $"{watch.ElapsedMilliseconds}ms");
        }
Пример #2
0
        public void AsyncPipelineWaitTest()
        {
            Random rand = new Random(222);
            int started = 0;
            int finished1 = 0;
            int finished2 = 0;
            int numActions = 1000;
            Action action1 = (() => 
                {
                    lock (this) started++;
                    Thread.Sleep((int)(rand.NextDouble() * 100));
                    lock (this) finished1++;
                });
            Action action2 = (() =>
            {
                Thread.Sleep((int)(rand.NextDouble() * 100));
                lock (this) finished2++;
            });

            var pipeline = new AsyncPipeline(10);
            for (int i = 0; i < numActions; i++)
            {
                var async1 = Task.Run(action1);
                pipeline.Add(async1);
                var async2 = async1.ContinueWith(_ => action2());
                pipeline.Add(async2);
            }
            pipeline.Wait();
            Assert.AreEqual(numActions, started);
            Assert.AreEqual(numActions, finished1);
            Assert.AreEqual(numActions, finished2);
        }
Пример #3
0
        public void AsyncPipelineSimpleTest()
        {
            int       step     = 1000;
            var       done     = TimedCompletions(step, step, step);
            var       pipeline = new AsyncPipeline(2);
            Stopwatch watch    = new Stopwatch();

            watch.Start();
            pipeline.Add(done[0]);
            const int epsilon  = 100;
            var       elapsed0 = watch.ElapsedMilliseconds;

            Assert.IsTrue(elapsed0 < epsilon, elapsed0.ToString());
            pipeline.Add(done[2]);
            var elapsed1 = watch.ElapsedMilliseconds;

            Assert.IsTrue(elapsed1 < epsilon, elapsed1.ToString());
            pipeline.Add(done[1]);
            var elapsed2 = watch.ElapsedMilliseconds;

            Assert.IsTrue(step - epsilon <= elapsed2 && elapsed2 <= step + epsilon);
            pipeline.Wait();
            watch.Stop();
            Assert.IsTrue(3 * step - epsilon <= watch.ElapsedMilliseconds && watch.ElapsedMilliseconds <= 3 * step + epsilon);
        }
Пример #4
0
        public void AsyncPipelineWaitTest()
        {
            Random rand       = new Random(222);
            int    started    = 0;
            int    finished1  = 0;
            int    finished2  = 0;
            int    numActions = 1000;
            Action action1    = (() =>
            {
                lock (this) started++;
                Thread.Sleep((int)(rand.NextDouble() * 100));
                lock (this) finished1++;
            });
            Action action2 = (() =>
            {
                Thread.Sleep((int)(rand.NextDouble() * 100));
                lock (this) finished2++;
            });

            var pipeline = new AsyncPipeline(10);

            for (int i = 0; i < numActions; i++)
            {
                var async1 = Task.Run(action1);
                pipeline.Add(async1);
                var async2 = async1.ContinueWith(_ => action2());
                pipeline.Add(async2);
            }
            pipeline.Wait();
            Assert.AreEqual(numActions, started);
            Assert.AreEqual(numActions, finished1);
            Assert.AreEqual(numActions, finished2);
        }
Пример #5
0
        public List <Task> ProcessNodes(
            Func <ChirperUserInfo, Task> action,
            Action <long> intervalAction = null,
            AsyncPipeline pipeline       = null)
        {
            List <Task> promises = new List <Task>();
            long        i        = 0;

            foreach (XElement nodeData in Nodes)
            {
                ChirperUserInfo userData = ParseUserInfo(nodeData);

                // Call main processing action
                Task n = action(userData);
                if (n != null)
                {
                    if (pipeline != null)
                    {
                        pipeline.Add(n);
                    }
                    promises.Add(n);
                }
                // else skip this node

                if (intervalAction != null && ProgressInterval != 0)
                {
                    if ((++i % ProgressInterval) == 0)
                    {
                        // Call progress interval action
                        intervalAction(i);
                    }
                }
            }
            return(promises);
        }
Пример #6
0
        private IList <Task> SetupConsumers(Guid streamId, string streamNamespace, string streamProviderName, AsyncPipeline pipeline, int numConsumers, bool normalSubscribeCalls)
        {
            var consumers = new List <IStreamLifecycleConsumerGrain>();
            var promises  = new List <Task>();

            long consumerIdStart = random.Next();

            for (int loopCount = 0; loopCount < numConsumers; loopCount++)
            {
                var grain = this.GrainFactory.GetGrain <IStreamLifecycleConsumerGrain>(Guid.NewGuid());
                consumers.Add(grain);

                Task promise;
                if (normalSubscribeCalls)
                {
                    promise = grain.BecomeConsumer(streamId, streamNamespace, streamProviderName);
                }
                else
                {
                    promise = grain.TestBecomeConsumerSlim(streamId, streamNamespace, streamProviderName);
                }

                //if (loopCount == 0)
                //{
                //    // First call for this stream, so wait for call to complete successfully so we know underlying infrastructure is set up.
                //    promise.Wait();
                //}
                promises.Add(promise);
                pipeline.Add(promise);
            }

            return(promises);
        }
Пример #7
0
        public List<Task> ProcessNodes(
            Func<ChirperUserInfo, Task> action,
            Action<long> intervalAction = null,
            AsyncPipeline pipeline = null)
        {
            List<Task> promises = new List<Task>();
            long i = 0;
            foreach (XElement nodeData in Nodes)
            {
                ChirperUserInfo userData = ParseUserInfo(nodeData);

                // Call main processing action
                Task n = action(userData);
                if (n != null)
                {
                    if (pipeline != null) pipeline.Add(n);
                    promises.Add(n);
                }
                // else skip this node

                if (intervalAction != null && ProgressInterval != 0)
                {
                    if ((++i % ProgressInterval) == 0)
                    {
                        // Call progress interval action
                        intervalAction(i);
                    }
                }
            }
            return promises;
        }
Пример #8
0
        public void Add_AddTypeThatIsNotAMiddleware_ThrowsException()
        {
            var pipeline = new AsyncPipeline <PersonModel>(new ActivatorMiddlewareResolver());

            PipelineNetAssert.ThrowsException <ArgumentException>(() =>
            {
                pipeline.Add(typeof(AsyncPipelineTests));
            });
        }
Пример #9
0
 public void AsyncPipelineSimpleTest()
 {
     int step = 1000;
     var done = TimedCompletions(step, step, step);
     var pipeline = new AsyncPipeline(2);
     Stopwatch watch = new Stopwatch();
     watch.Start();
     pipeline.Add(done[0]);
     const int epsilon = 100;
     var elapsed0 = watch.ElapsedMilliseconds;
     Assert.IsTrue(elapsed0 < epsilon, elapsed0.ToString());
     pipeline.Add(done[2]);
     var elapsed1 = watch.ElapsedMilliseconds;
     Assert.IsTrue(elapsed1 < epsilon, elapsed1.ToString());
     pipeline.Add(done[1]);
     var elapsed2 = watch.ElapsedMilliseconds;
     Assert.IsTrue(step - epsilon <= elapsed2 && elapsed2 <= step + epsilon);
     pipeline.Wait();
     watch.Stop();
     Assert.IsTrue(3 * step - epsilon <= watch.ElapsedMilliseconds && watch.ElapsedMilliseconds <= 3 * step + epsilon);
 }
        public async Task DeactivateOnIdleTest_Stress_3_MayInterleave_With_TaskCompletionSource_UnderConstantLoad()
        {
            foreach (var i in Enumerable.Range(0, 100))
            {
                Initialize();

                output.WriteLine($"Running test #{i}");
                await RunTest();

                Dispose();
            }

            async Task RunTest()
            {
                var a = this.testCluster.GrainFactory.GetGrain <ICollectionTestGrain>(1, "UnitTests.Grains.MayInterleaveCollectionTestGrainWithTcs");

                var activated = await a.GetActivationTime();

                Assert.Equal(activated, await a.GetActivationTime());

                var pipeline     = new AsyncPipeline(20);
                var cts          = new CancellationTokenSource();
                var cancellation = cts.Token;

                var requests = new List <Task <int> >();
                var senders  = Task.Run(() =>
                {
                    while (!cancellation.IsCancellationRequested)
                    {
                        var request = a.IncrCounter();
                        requests.Add(request);
                        pipeline.Add(request);
                    }
                });

                // give it some time to fill the queue
                await Task.Delay(TimeSpan.FromSeconds(1));

                output.WriteLine($"Requests (before): {requests.Count}");
                await a.DeactivateSelf();

                cts.Cancel();
                pipeline.Wait();
                await senders;

                output.WriteLine("After deactivation");
                Assert.NotEqual(activated, await a.GetActivationTime());

                output.WriteLine($"Requests (total): {requests.Count}");
                Assert.All(requests, x => Assert.True(x.Status == TaskStatus.RanToCompletion));
            }
        }
Пример #11
0
        private void ForEachUser(Action <IChirperAccount> action)
        {
            List <Task> promises = new List <Task>();

            foreach (long userId in loader.Users.Keys)
            {
                IChirperAccount user = loader.Users[userId];
                Task            p    = Task.Factory.StartNew(() => action(user));
                pipeline.Add(p);
                promises.Add(p);
            }
            pipeline.Wait();
            Task.WhenAll(promises).Wait();
        }
Пример #12
0
        //private async Task Test_Stream_Churn_TimePeriod(
        //    string streamProviderName,
        //    int pipelineSize,
        //    TimeSpan duration,
        //    int numConsumers = 9,
        //    int numProducers = 1)
        //{
        //    output.WriteLine("Testing Subscription churn for duration {0} with {1} Consumers and {2} Producers per Stream",
        //        duration, numConsumers, numProducers);

        //    AsyncPipeline pipeline = new AsyncPipeline(pipelineSize);
        //    var promises = new List<Task>();

        //    Stopwatch sw = Stopwatch.StartNew();

        //    for (int i = 0; sw.Elapsed <= duration; i++)
        //    {
        //        Guid streamId = Guid.NewGuid();
        //        Task promise = SetupOneStream(streamId, streamProviderName, pipeline, numConsumers, numProducers);
        //        promises.Add(promise);
        //    }
        //    await Task.WhenAll(promises);
        //    sw.Stop();
        //    TimeSpan elapsed = sw.Elapsed;
        //    int totalSubscription = numSt* numConsumers);
        //    double rps = totalSubscription/elapsed.TotalSeconds;
        //    output.WriteLine("Subscriptions-per-second = {0} during period {1}", rps, elapsed);
        //    Assert.NotEqual(0.0, rps, "RPS greater than zero");
        //}

        private void WarmUpPubSub(string streamProviderName, Guid[] streamIds, AsyncPipeline pipeline)
        {
            int numStreams = streamIds.Length;

            // Warm up PubSub for the appropriate streams
            for (int i = 0; i < numStreams; i++)
            {
                Guid   streamId = streamIds[i];
                string extKey   = streamProviderName + "_" + this.StreamNamespace;

                IPubSubRendezvousGrain pubsub = this.GrainFactory.GetGrain <IPubSubRendezvousGrain>(streamId, extKey, null);

                Task promise = pubsub.Validate();

                pipeline.Add(promise);
            }
            pipeline.Wait();
        }
Пример #13
0
        //private async Task Test_Stream_Churn_TimePeriod(
        //    string streamProviderName,
        //    int pipelineSize,
        //    TimeSpan duration,
        //    int numConsumers = 9,
        //    int numProducers = 1)
        //{
        //    output.WriteLine("Testing Subscription churn for duration {0} with {1} Consumers and {2} Producers per Stream",
        //        duration, numConsumers, numProducers);

        //    AsyncPipeline pipeline = new AsyncPipeline(pipelineSize);
        //    var promises = new List<Task>();

        //    Stopwatch sw = Stopwatch.StartNew();

        //    for (int i = 0; sw.Elapsed <= duration; i++)
        //    {
        //        Guid streamId = Guid.NewGuid();
        //        Task promise = SetupOneStream(streamId, streamProviderName, pipeline, numConsumers, numProducers);
        //        promises.Add(promise);
        //    }
        //    await Task.WhenAll(promises);
        //    sw.Stop();
        //    TimeSpan elapsed = sw.Elapsed;
        //    int totalSubscription = numSt* numConsumers);
        //    double rps = totalSubscription/elapsed.TotalSeconds;
        //    output.WriteLine("Subscriptions-per-second = {0} during period {1}", rps, elapsed);
        //    Assert.NotEqual(0.0, rps, "RPS greater than zero");
        //}

        private void WarmUpPubSub(string streamProviderName, StreamId[] streamIds, AsyncPipeline pipeline)
        {
            int numStreams = streamIds.Length;

            // Warm up PubSub for the appropriate streams
            for (int i = 0; i < numStreams; i++)
            {
                var streamId = new InternalStreamId(streamProviderName, streamIds[i]);
                _ = streamProviderName + "_" + this.StreamNamespace;

                IPubSubRendezvousGrain pubsub = this.GrainFactory.GetGrain <IPubSubRendezvousGrain>(streamId.ToString());

                Task promise = pubsub.Validate();

                pipeline.Add(promise);
            }
            pipeline.Wait();
        }
Пример #14
0
        public List <Task> ProcessEdges(
            Func <long, long, Task> action,
            Action <long> intervalAction = null,
            AsyncPipeline pipeline       = null)
        {
            List <Task> promises = new List <Task>();
            long        i        = 0;

            foreach (XElement edgeData in Edges)
            {
                long fromUserId = Int64.Parse(edgeData.Attribute("source").Value);
                long toUserId   = Int64.Parse(edgeData.Attribute("target").Value);

                Task n = action(fromUserId, toUserId);
                if (n != null)
                {
                    if (pipeline != null)
                    {
                        pipeline.Add(n);
                    }
                    promises.Add(n);
                }
                else
                {
                    // skip this edge
                    continue;
                }


                if (intervalAction != null && ProgressInterval != 0)
                {
                    if ((++i % ProgressInterval) == 0)
                    {
                        // Call progress interval action
                        intervalAction(i);
                    }
                }
            }
            return(promises);
        }
Пример #15
0
        private IList <Task> SetupProducers(Guid streamId, string streamNamespace, string streamProviderName, AsyncPipeline pipeline, int numProducers)
        {
            var producers = new List <IStreamLifecycleProducerGrain>();
            var promises  = new List <Task>();

            for (int loopCount = 0; loopCount < numProducers; loopCount++)
            {
                var grain = this.GrainFactory.GetGrain <IStreamLifecycleProducerGrain>(Guid.NewGuid());
                producers.Add(grain);

                Task promise = grain.BecomeProducer(streamId, streamNamespace, streamProviderName);

                if (loopCount == 0)
                {
                    // First call for this stream, so wait for call to complete successfully so we know underlying infrastructure is set up.
                    promise.Wait();
                }
                promises.Add(promise);
                pipeline.Add(promise);
            }

            return(promises);
        }
Пример #16
0
        private static IList<Task> SetupProducers(Guid streamId, string streamNamespace, string streamProviderName, AsyncPipeline pipeline, int numProducers)
        {
            var producers = new List<IStreamLifecycleProducerGrain>();
            var promises = new List<Task>();

            for (int loopCount = 0; loopCount < numProducers; loopCount++)
            {
                var grain = GrainClient.GrainFactory.GetGrain<IStreamLifecycleProducerGrain>(Guid.NewGuid());
                producers.Add(grain);

                Task promise = grain.BecomeProducer(streamId, streamNamespace, streamProviderName);

                if (loopCount == 0)
                {
                    // First call for this stream, so wait for call to complete successfully so we know underlying infrastructure is set up.
                    promise.Wait();
                }
                promises.Add(promise);
                pipeline.Add(promise);
            }

            return promises;
        }
Пример #17
0
        private Task Test_Stream_Churn_NumStreams_FewPublishers(
            string streamProviderName,
            int pipelineSize,
            int numStreams,
            int numConsumers          = 9,
            int numProducers          = 4,
            bool warmUpPubSub         = true,
            bool warmUpProducers      = false,
            bool normalSubscribeCalls = true)
        {
            output.WriteLine("Testing churn with {0} Streams on {1} Producers with {2} Consumers per Stream",
                             numStreams, numProducers, numConsumers);

            AsyncPipeline pipeline = new AsyncPipeline(pipelineSize);

            // Create streamId Guids
            Guid[] streamIds = new Guid[numStreams];
            for (int i = 0; i < numStreams; i++)
            {
                streamIds[i] = Guid.NewGuid();
            }

            int activeConsumerGrains = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName);

            Assert.Equal(0, activeConsumerGrains);   //  "Initial Consumer count should be zero"
            int activeProducerGrains = ActiveGrainCount(typeof(StreamLifecycleProducerGrain).FullName);

            Assert.Equal(0, activeProducerGrains);   //  "Initial Producer count should be zero"

            if (warmUpPubSub)
            {
                WarmUpPubSub(streamProviderName, streamIds, pipeline);

                pipeline.Wait();

                int activePubSubGrains = ActiveGrainCount(typeof(PubSubRendezvousGrain).FullName);
                Assert.Equal(streamIds.Length, activePubSubGrains);   //  "Initial PubSub count -- should all be warmed up"
            }

            Guid[] producerIds = new Guid[numProducers];

            if (numProducers > 0 && warmUpProducers)
            {
                // Warm up Producers to pre-create grains
                for (int i = 0; i < numProducers; i++)
                {
                    producerIds[i] = Guid.NewGuid();
                    var  grain   = this.GrainFactory.GetGrain <IStreamLifecycleProducerGrain>(producerIds[i]);
                    Task promise = grain.Ping();

                    pipeline.Add(promise);
                }
                pipeline.Wait();

                int activePublisherGrains = this.ActiveGrainCount(typeof(StreamLifecycleProducerGrain).FullName);
                Assert.Equal(numProducers, activePublisherGrains);   //  "Initial Publisher count -- should all be warmed up"
            }

            var promises = new List <Task>();

            Stopwatch sw = Stopwatch.StartNew();

            if (numProducers > 0)
            {
                // Producers
                for (int i = 0; i < numStreams; i++)
                {
                    Guid streamId   = streamIds[i];
                    Guid producerId = producerIds[i % numProducers];
                    var  grain      = this.GrainFactory.GetGrain <IStreamLifecycleProducerGrain>(producerId);

                    Task promise = grain.BecomeProducer(streamId, this.StreamNamespace, streamProviderName);

                    promises.Add(promise);
                    pipeline.Add(promise);
                }
                pipeline.Wait();
                promises.Clear();
            }

            // Consumers
            for (int i = 0; i < numStreams; i++)
            {
                Guid streamId = streamIds[i];

                Task promise = SetupOneStream(streamId, streamProviderName, pipeline, numConsumers, 0, normalSubscribeCalls);
                promises.Add(promise);
            }
            pipeline.Wait();

            Task.WhenAll(promises).Wait();
            sw.Stop();

            int consumerCount = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName);

            Assert.Equal(activeConsumerGrains + (numStreams * numConsumers), consumerCount);   //  "The right number of Consumer grains are active"

            int producerCount = ActiveGrainCount(typeof(StreamLifecycleProducerGrain).FullName);

            Assert.Equal(activeProducerGrains + (numStreams * numProducers), producerCount);   //  "The right number of Producer grains are active"

            int pubSubCount = ActiveGrainCount(typeof(PubSubRendezvousGrain).FullName);

            Assert.Equal(streamIds.Length, pubSubCount);   //  "Final PubSub count -- no more started"

            TimeSpan elapsed            = sw.Elapsed;
            int      totalSubscriptions = numStreams * numConsumers;
            double   rps = totalSubscriptions / elapsed.TotalSeconds;

            output.WriteLine("Subscriptions-per-second = {0} during period {1}", rps, elapsed);
            Assert.NotEqual(0.0, rps);   // "RPS greater than zero"
            return(Task.CompletedTask);
        }
Пример #18
0
        private async Task AsyncPipelineBlackBoxConsistencyTest(int workerCount)
        {
            if (workerCount < 1)
                throw new ArgumentOutOfRangeException("You must specify at least one worker.", "workerCount");

            int loopCount = _iterationCount / workerCount;
            const double variance = 0.1;
            int expectedTasksCompleted = loopCount * workerCount;
            var delayLength = TimeSpan.FromSeconds(1);
            const int pipelineCapacity = _defaultPipelineCapacity;
            var pipeline = new AsyncPipeline(pipelineCapacity);
            int tasksCompleted = 0;
            // the following value is wrapped within an array to avoid a modified closure warning from ReSharper.
            int[] pipelineSize = { 0 };
            var capacityReached = new InterlockedFlag();

            Action workFunc =
                () =>
                {
                    var sz = Interlocked.Increment(ref pipelineSize[0]);
                    CheckPipelineState(sz, pipelineCapacity, capacityReached);
                    Task.Delay(delayLength).Wait();
                    Interlocked.Decrement(ref pipelineSize[0]);
                    Interlocked.Increment(ref tasksCompleted);
                };

            Action workerFunc =
                () =>
                {
                    for (var j = 0; j < loopCount; j++)
                    {
                        Task task = new Task(workFunc);
                        pipeline.Add(task, whiteBox: null);
                        task.Start();
                    }
                };

            Func<Task> monitorFunc =
                async () =>
                {
                    var delay = TimeSpan.FromSeconds(5);
                    while (tasksCompleted < expectedTasksCompleted)
                    {
                        output.WriteLine("test in progress: tasksCompleted = {0}.", tasksCompleted);
                        await Task.Delay(delay);
                    }
                };

            var workers = new Task[workerCount];
            var stopwatch = Stopwatch.StartNew();
            for (var i = 0; i < workerCount; ++i)
                workers[i] = Task.Run(workerFunc);
            Task.Run(monitorFunc).Ignore();
            await Task.WhenAll(workers);
            pipeline.Wait();
            stopwatch.Stop();
            Assert.AreEqual(expectedTasksCompleted, tasksCompleted, "The test did not complete the expected number of tasks.");

            var targetTimeSec = expectedTasksCompleted * delayLength.TotalSeconds / pipelineCapacity;
            var minTimeSec = (1.0 - variance) * targetTimeSec;
            var maxTimeSec = (1.0 + variance) * targetTimeSec;
            var actualSec = stopwatch.Elapsed.TotalSeconds;
            output.WriteLine(
                "Test finished in {0} sec, {1}% of target time {2} sec. Permitted variance is +/-{3}%",
                actualSec,
                actualSec / targetTimeSec * 100,
                targetTimeSec,
                variance * 100);

            Assert.IsTrue(capacityReached.IsSet, "Pipeline capacity not reached; the delay length probably is too short to be useful.");
            Assert.IsTrue(
                actualSec >= minTimeSec, 
                string.Format("The unit test completed too early ({0} sec < {1} sec).", actualSec, minTimeSec));
            Assert.IsTrue(
                actualSec <= maxTimeSec, 
                string.Format("The unit test completed too late ({0} sec > {1} sec).", actualSec, maxTimeSec));
        }
Пример #19
0
        private async Task<double> TestOneStream(Guid streamId, string streamProviderName,
            int numProducers, int numConsumers, int numMessages,
            bool useFanOut = true)
        {
            Console.WriteLine("Testing Stream {0} with Producers={1} Consumers={2} x {3} messages",
                streamId, numProducers, numConsumers, numMessages);

            Stopwatch sw = Stopwatch.StartNew();

            List<IStreamLifecycleConsumerGrain> consumers = new List<IStreamLifecycleConsumerGrain>();
            List<IStreamLifecycleProducerGrain> producers = new List<IStreamLifecycleProducerGrain>();

            await InitializeTopology(streamId, this.StreamNamespace, streamProviderName,
                numProducers, numConsumers,
                producers, consumers, useFanOut);

            var promises = new List<Task>();

            // Producers send M message each
            int item = 1;
            AsyncPipeline pipeline = new AsyncPipeline(MessagePipelineSize);
            foreach (var grain in producers)
            {
                for (int m = 0; m < numMessages; m++)
                {
                    Task promise = grain.SendItem(item++);

                    if (useFanOut)
                    {
                        pipeline.Add(promise);
                        promises.Add(promise);
                    }
                    else
                    {
                        await promise;
                    }
                }
            }
            if (useFanOut)
            {
                //Console.WriteLine("Test: Waiting for {0} producers to finish sending {1} messages", producers.Count, promises.Count);
                await Task.WhenAll(promises);
                promises.Clear();
            }

            var pubSub = StreamTestUtils.GetStreamPubSub();

            // Check Consumer counts
            int consumerCount = await pubSub.ConsumerCount(streamId, streamProviderName, StreamNamespace);
            Assert.AreEqual(numConsumers, consumerCount, "ConsumerCount for Stream {0}", streamId);

            // Check Producer counts
            int producerCount = await pubSub.ProducerCount(streamId, streamProviderName, StreamNamespace);
            Assert.AreEqual(numProducers, producerCount, "ProducerCount for Stream {0}", streamId);

            // Check message counts received by consumers
            int totalMessages = (numMessages + 1) * numProducers;
            foreach (var grain in consumers)
            {
                int count = await grain.GetReceivedCount();
                Assert.AreEqual(totalMessages, count, "ReceivedCount for Consumer grain {0}", grain.GetPrimaryKey());
            }

            double rps = totalMessages/sw.Elapsed.TotalSeconds;
            //Console.WriteLine("Sent {0} messages total from {1} Producers to {2} Consumers in {3} at {4} RPS",
            //    totalMessages, numProducers, numConsumers,
            //    sw.Elapsed, rps);

            return rps;
        }
Пример #20
0
        private static async Task InitializeTopology(Guid streamId, string streamNamespace, string streamProviderName,
            int numProducers, int numConsumers,
            List<IStreamLifecycleProducerGrain> producers, List<IStreamLifecycleConsumerGrain> consumers,
            bool useFanOut)
        {
            long nextGrainId = random.Next();

            //var promises = new List<Task>();
            AsyncPipeline pipeline = new AsyncPipeline(InitPipelineSize);

            // Consumers
            long consumerIdStart = nextGrainId;
            for (int loopCount = 0; loopCount < numConsumers; loopCount++)
            {
                var grain = GrainClient.GrainFactory.GetGrain<IStreamLifecycleConsumerGrain>(Guid.NewGuid());
                consumers.Add(grain);

                Task promise = grain.BecomeConsumer(streamId, streamNamespace, streamProviderName);

                if (useFanOut)
                {
                    pipeline.Add(promise);
                    //promises.Add(promise);

                    //if (loopCount%WaitBatchSize == 0)
                    //{
                    //    Console.WriteLine("InitializeTopology: Waiting for {0} consumers to initialize", promises.Count);
                    //    await Task.WhenAll(promises);
                    //    promises.Clear();
                    //}
                }
                else
                {
                    await promise;
                }
            }
            if (useFanOut)
            {
                //Console.WriteLine("InitializeTopology: Waiting for {0} consumers to initialize", promises.Count);
                //await Task.WhenAll(promises);
                //promises.Clear();
                //Console.WriteLine("InitializeTopology: Waiting for {0} consumers to initialize", pipeline.Count);
                pipeline.Wait();
            }
            nextGrainId += numConsumers;

            // Producers
            long producerIdStart = nextGrainId;
            pipeline = new AsyncPipeline(InitPipelineSize);
            for (int loopCount = 0; loopCount < numProducers; loopCount++)
            {
                var grain = GrainClient.GrainFactory.GetGrain<IStreamLifecycleProducerGrain>(Guid.NewGuid());
                producers.Add(grain);

                Task promise = grain.BecomeProducer(streamId, streamNamespace, streamProviderName);

                if (useFanOut)
                {
                    pipeline.Add(promise);
                    //promises.Add(promise);
                }
                else
                {
                    await promise;
                }
            }
            if (useFanOut)
            {
                //Console.WriteLine("InitializeTopology: Waiting for {0} producers to initialize", promises.Count);
                //await Task.WhenAll(promises);
                //promises.Clear();
                //Console.WriteLine("InitializeTopology: Waiting for {0} producers to initialize", pipeline.Count);
                pipeline.Wait();
            }
            //nextGrainId += numProducers;
        }
Пример #21
0
        public int Run()
        {
            this.perfCounters = new ChirperPerformanceCounters(this.GraphDataFile.FullName);
            perfCounters.ChirpsPerSecond.RawValue = 0;

            pipeline = new AsyncPipeline(PipelineLength);
            loader   = new ChirperNetworkLoader(pipeline);
            //if (this.Verbose) loader.SetVerbose();

            Console.WriteLine("Loading Chirper network data file " + this.GraphDataFile.FullName);
            loader.FileToLoad = this.GraphDataFile;
            loader.LoadData();
            loader.CreateUserNodes(); // Connect/create users

            Console.WriteLine(
                "Starting Chirper network traffic simulation for {0} users.\n"
                + "Chirp publication time base = {1}\n"
                + "Random time distribution = {2}\n"
                + "Rechirp rate = {3}",
                loader.Users.Count, this.ChirpPublishTimebase, this.ChirpPublishTimeRandom, this.ShouldRechirpRate);

            ForEachUser(user =>
            {
                SimulatedUser u          = new SimulatedUser(user);
                u.ShouldRechirpRate      = this.ShouldRechirpRate;
                u.ChirpPublishTimebase   = this.ChirpPublishTimebase;
                u.ChirpPublishTimeRandom = this.ChirpPublishTimeRandom;
                u.Verbose = this.Verbose;
                lock (activeUsers)
                {
                    activeUsers.Add(u);
                }
                u.Start();
            });

            Console.WriteLine("Starting sending chirps...");

            Random    rand      = new Random();
            int       count     = 0;
            Stopwatch stopwatch = Stopwatch.StartNew();

            do
            {
                int           i = rand.Next(activeUsers.Count);
                SimulatedUser u = activeUsers[i];
                if (u == null)
                {
                    Console.WriteLine("User {0} not found.", i);
                    return(-1);
                }

                string msg = fortune.GetFortune();

                pipeline.Add(u.PublishMessage(msg));
                count++;
                if (count % 10000 == 0)
                {
                    Console.WriteLine("{0:0.#}/sec: {1} in {2}ms.  Pipeline contains {3} items.",
                                      ((float)10000 / stopwatch.ElapsedMilliseconds) * 1000, count, stopwatch.ElapsedMilliseconds, pipeline.Count);
                    perfCounters.ChirpsPerSecond.RawValue = (int)(((float)10000 / stopwatch.ElapsedMilliseconds) * 1000);

                    stopwatch.Restart();
                }

                if (ChirpPublishTimebase > 0)
                {
                    Thread.Sleep(ChirpPublishTimebase * 1000);
                }
            } while (true);
        }
Пример #22
0
        private static IList<Task> SetupConsumers(Guid streamId, string streamNamespace, string streamProviderName, AsyncPipeline pipeline, int numConsumers, bool normalSubscribeCalls)
        {
            var consumers = new List<IStreamLifecycleConsumerGrain>();
            var promises = new List<Task>();

            long consumerIdStart = random.Next();
            for (int loopCount = 0; loopCount < numConsumers; loopCount++)
            {
                var grain = GrainClient.GrainFactory.GetGrain<IStreamLifecycleConsumerGrain>(Guid.NewGuid());
                consumers.Add(grain);

                Task promise; 
                if (normalSubscribeCalls)
                {
                    promise = grain.BecomeConsumer(streamId, streamNamespace, streamProviderName);
                }
                else
                {
                    promise = grain.TestBecomeConsumerSlim(streamId, streamNamespace, streamProviderName);
                }

                //if (loopCount == 0)
                //{
                //    // First call for this stream, so wait for call to complete successfully so we know underlying infrastructure is set up.
                //    promise.Wait();
                //}
                promises.Add(promise);
                pipeline.Add(promise);
            }

            return promises;
        }
Пример #23
0
        //private async Task Test_Stream_Churn_TimePeriod(
        //    string streamProviderName,
        //    int pipelineSize,
        //    TimeSpan duration,
        //    int numConsumers = 9,
        //    int numProducers = 1)
        //{
        //    Console.WriteLine("Testing Subscription churn for duration {0} with {1} Consumers and {2} Producers per Stream",
        //        duration, numConsumers, numProducers);

        //    AsyncPipeline pipeline = new AsyncPipeline(pipelineSize);
        //    var promises = new List<Task>();

        //    Stopwatch sw = Stopwatch.StartNew();

        //    for (int i = 0; sw.Elapsed <= duration; i++)
        //    {
        //        Guid streamId = Guid.NewGuid();
        //        Task promise = SetupOneStream(streamId, streamProviderName, pipeline, numConsumers, numProducers);
        //        promises.Add(promise);
        //    }
        //    await Task.WhenAll(promises);
        //    sw.Stop();
        //    TimeSpan elapsed = sw.Elapsed;
        //    int totalSubscription = numSt* numConsumers);
        //    double rps = totalSubscription/elapsed.TotalSeconds;
        //    Console.WriteLine("Subscriptions-per-second = {0} during period {1}", rps, elapsed);
        //    Assert.AreNotEqual(0.0, rps, "RPS greater than zero");
        //}

        private void WarmUpPubSub(string streamProviderName, Guid[] streamIds, AsyncPipeline pipeline)
        {
            int numStreams = streamIds.Length;
            // Warm up PubSub for the appropriate streams
            for (int i = 0; i < numStreams; i++)
            {
                Guid streamId = streamIds[i];
                string extKey = streamProviderName + "_" + StreamNamespace;

                IPubSubRendezvousGrain pubsub = GrainClient.GrainFactory.GetGrain<IPubSubRendezvousGrain>(streamId, extKey, null);

                Task promise = pubsub.Validate();

                pipeline.Add(promise);
            }
            pipeline.Wait();
        }
Пример #24
0
        public List<Task> ProcessEdges(
            Func<long, long, Task> action,
            Action<long> intervalAction = null,
            AsyncPipeline pipeline = null)
        {
            List<Task> promises = new List<Task>();
            long i = 0;
            foreach (XElement edgeData in Edges)
            {
                long fromUserId = Int64.Parse(edgeData.Attribute("source").Value);
                long toUserId = Int64.Parse(edgeData.Attribute("target").Value);

                Task n = action(fromUserId, toUserId);
                if (n != null)
                {
                    if (pipeline != null) pipeline.Add(n);
                    promises.Add(n);
                }
                else
                {
                    // skip this edge
                    continue;
                }


                if (intervalAction != null && ProgressInterval != 0)
                {
                    if ((++i % ProgressInterval) == 0)
                    {
                        // Call progress interval action
                        intervalAction(i);
                    }
                }
            }
            return promises;
        }
Пример #25
0
        private async Task <double> TestOneStream(Guid streamId, string streamProviderName,
                                                  int numProducers, int numConsumers, int numMessages,
                                                  bool useFanOut = true)
        {
            output.WriteLine("Testing Stream {0} with Producers={1} Consumers={2} x {3} messages",
                             streamId, numProducers, numConsumers, numMessages);

            Stopwatch sw = Stopwatch.StartNew();

            List <IStreamLifecycleConsumerGrain> consumers = new List <IStreamLifecycleConsumerGrain>();
            List <IStreamLifecycleProducerGrain> producers = new List <IStreamLifecycleProducerGrain>();

            await InitializeTopology(streamId, this.StreamNamespace, streamProviderName,
                                     numProducers, numConsumers,
                                     producers, consumers, useFanOut);

            var promises = new List <Task>();

            // Producers send M message each
            int           item     = 1;
            AsyncPipeline pipeline = new AsyncPipeline(MessagePipelineSize);

            foreach (var grain in producers)
            {
                for (int m = 0; m < numMessages; m++)
                {
                    Task promise = grain.SendItem(item++);

                    if (useFanOut)
                    {
                        pipeline.Add(promise);
                        promises.Add(promise);
                    }
                    else
                    {
                        await promise;
                    }
                }
            }
            if (useFanOut)
            {
                //output.WriteLine("Test: Waiting for {0} producers to finish sending {1} messages", producers.Count, promises.Count);
                await Task.WhenAll(promises);

                promises.Clear();
            }

            var pubSub = StreamTestUtils.GetStreamPubSub(this.InternalClient);

            // Check Consumer counts
            int consumerCount = await pubSub.ConsumerCount(streamId, streamProviderName, StreamNamespace);

            Assert.Equal(numConsumers, consumerCount);   //  "ConsumerCount for Stream {0}", streamId

            // Check Producer counts
            int producerCount = await pubSub.ProducerCount(streamId, streamProviderName, StreamNamespace);

            Assert.Equal(numProducers, producerCount);   //  "ProducerCount for Stream {0}", streamId

            // Check message counts received by consumers
            int totalMessages = (numMessages + 1) * numProducers;

            foreach (var grain in consumers)
            {
                int count = await grain.GetReceivedCount();

                Assert.Equal(totalMessages, count);  //  "ReceivedCount for Consumer grain {0}", grain.GetPrimaryKey());
            }

            double rps = totalMessages / sw.Elapsed.TotalSeconds;

            //output.WriteLine("Sent {0} messages total from {1} Producers to {2} Consumers in {3} at {4} RPS",
            //    totalMessages, numProducers, numConsumers,
            //    sw.Elapsed, rps);

            return(rps);
        }
Пример #26
0
        public int Run()
        {
            this.perfCounters = new ChirperPerformanceCounters(this.GraphDataFile.FullName);
            perfCounters.ChirpsPerSecond.RawValue = 0;

            pipeline = new AsyncPipeline(PipelineLength);
            loader = new ChirperNetworkLoader(pipeline);
            //if (this.Verbose) loader.SetVerbose();

            Console.WriteLine("Loading Chirper network data file " + this.GraphDataFile.FullName);
            loader.FileToLoad = this.GraphDataFile;
            loader.LoadData();
            loader.CreateUserNodes(); // Connect/create users

            Console.WriteLine(
                "Starting Chirper network traffic simulation for {0} users.\n"
                + "Chirp publication time base = {1}\n"
                + "Random time distribution = {2}\n"
                + "Rechirp rate = {3}", 
                loader.Users.Count, this.ChirpPublishTimebase, this.ChirpPublishTimeRandom, this.ShouldRechirpRate);

            ForEachUser(user =>
            {
                SimulatedUser u = new SimulatedUser(user);
                u.ShouldRechirpRate = this.ShouldRechirpRate;
                u.ChirpPublishTimebase = this.ChirpPublishTimebase;
                u.ChirpPublishTimeRandom = this.ChirpPublishTimeRandom;
                u.Verbose = this.Verbose;
                lock (activeUsers)
                {
                    activeUsers.Add(u);
                }
                u.Start();
            });

            Console.WriteLine("Starting sending chirps...");

            Random rand = new Random();
            int count = 0;
            Stopwatch stopwatch = Stopwatch.StartNew();
            do
            {
                int i = rand.Next(activeUsers.Count);
                SimulatedUser u = activeUsers[i];
                if (u == null)
                {
                    Console.WriteLine("User {0} not found.", i);
                    return -1;
                }

                string msg = fortune.GetFortune();

                pipeline.Add(u.PublishMessage(msg));
                count++;
                if (count % 10000 == 0)
                {
                    Console.WriteLine("{0:0.#}/sec: {1} in {2}ms.  Pipeline contains {3} items.",
                        ((float)10000 / stopwatch.ElapsedMilliseconds) * 1000, count, stopwatch.ElapsedMilliseconds, pipeline.Count);
                    perfCounters.ChirpsPerSecond.RawValue = (int) (((float) 10000 / stopwatch.ElapsedMilliseconds) * 1000);

                    stopwatch.Restart();
                }

                if (ChirpPublishTimebase > 0)
                {
                    Thread.Sleep(ChirpPublishTimebase * 1000);
                }
            } while (true);
        }
Пример #27
0
        private async Task AsyncPipelineBlackBoxConsistencyTest(int workerCount)
        {
            if (workerCount < 1)
            {
                throw new ArgumentOutOfRangeException("You must specify at least one worker.", "workerCount");
            }

            int          loopCount = _iterationCount / workerCount;
            const double variance  = 0.1;
            int          expectedTasksCompleted = loopCount * workerCount;
            var          delayLength            = TimeSpan.FromSeconds(1);
            const int    pipelineCapacity       = _defaultPipelineCapacity;
            var          pipeline       = new AsyncPipeline(pipelineCapacity);
            int          tasksCompleted = 0;

            // the following value is wrapped within an array to avoid a modified closure warning from ReSharper.
            int[] pipelineSize    = { 0 };
            var   capacityReached = new InterlockedFlag();

            Action workFunc =
                () =>
            {
                var sz = Interlocked.Increment(ref pipelineSize[0]);
                CheckPipelineState(sz, pipelineCapacity, capacityReached);
                Task.Delay(delayLength).Wait();
                Interlocked.Decrement(ref pipelineSize[0]);
                Interlocked.Increment(ref tasksCompleted);
            };

            Action workerFunc =
                () =>
            {
                for (var j = 0; j < loopCount; j++)
                {
                    Task task = new Task(workFunc);
                    pipeline.Add(task, whiteBox: null);
                    task.Start();
                }
            };

            Func <Task> monitorFunc =
                async() =>
            {
                var delay = TimeSpan.FromSeconds(5);
                while (tasksCompleted < expectedTasksCompleted)
                {
                    Console.WriteLine("test in progress: tasksCompleted = {0}.", tasksCompleted);
                    await Task.Delay(delay);
                }
            };

            var workers   = new Task[workerCount];
            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < workerCount; ++i)
            {
                workers[i] = Task.Run(workerFunc);
            }
            Task.Run(monitorFunc).Ignore();
            await Task.WhenAll(workers);

            pipeline.Wait();
            stopwatch.Stop();
            Assert.AreEqual(expectedTasksCompleted, tasksCompleted, "The test did not complete the expected number of tasks.");

            var targetTimeSec = expectedTasksCompleted * delayLength.TotalSeconds / pipelineCapacity;
            var minTimeSec    = (1.0 - variance) * targetTimeSec;
            var maxTimeSec    = (1.0 + variance) * targetTimeSec;
            var actualSec     = stopwatch.Elapsed.TotalSeconds;

            Console.WriteLine(
                "Test finished in {0} sec, {1}% of target time {2} sec. Permitted variance is +/-{3}%",
                actualSec,
                actualSec / targetTimeSec * 100,
                targetTimeSec,
                variance * 100);

            Assert.IsTrue(capacityReached.IsSet, "Pipeline capacity not reached; the delay length probably is too short to be useful.");
            Assert.IsTrue(
                actualSec >= minTimeSec,
                string.Format("The unit test completed too early ({0} sec < {1} sec).", actualSec, minTimeSec));
            Assert.IsTrue(
                actualSec <= maxTimeSec,
                string.Format("The unit test completed too late ({0} sec > {1} sec).", actualSec, maxTimeSec));
        }
Пример #28
0
        private async Task InitializeTopology(Guid streamId, string streamNamespace, string streamProviderName,
                                              int numProducers, int numConsumers,
                                              List <IStreamLifecycleProducerGrain> producers, List <IStreamLifecycleConsumerGrain> consumers,
                                              bool useFanOut)
        {
            long nextGrainId = random.Next();

            //var promises = new List<Task>();
            AsyncPipeline pipeline = new AsyncPipeline(InitPipelineSize);

            // Consumers
            long consumerIdStart = nextGrainId;

            for (int loopCount = 0; loopCount < numConsumers; loopCount++)
            {
                var grain = this.GrainFactory.GetGrain <IStreamLifecycleConsumerGrain>(Guid.NewGuid());
                consumers.Add(grain);

                Task promise = grain.BecomeConsumer(streamId, streamNamespace, streamProviderName);

                if (useFanOut)
                {
                    pipeline.Add(promise);
                    //promises.Add(promise);

                    //if (loopCount%WaitBatchSize == 0)
                    //{
                    //    output.WriteLine("InitializeTopology: Waiting for {0} consumers to initialize", promises.Count);
                    //    await Task.WhenAll(promises);
                    //    promises.Clear();
                    //}
                }
                else
                {
                    await promise;
                }
            }
            if (useFanOut)
            {
                //output.WriteLine("InitializeTopology: Waiting for {0} consumers to initialize", promises.Count);
                //await Task.WhenAll(promises);
                //promises.Clear();
                //output.WriteLine("InitializeTopology: Waiting for {0} consumers to initialize", pipeline.Count);
                pipeline.Wait();
            }
            nextGrainId += numConsumers;

            // Producers
            long producerIdStart = nextGrainId;

            pipeline = new AsyncPipeline(InitPipelineSize);
            for (int loopCount = 0; loopCount < numProducers; loopCount++)
            {
                var grain = this.GrainFactory.GetGrain <IStreamLifecycleProducerGrain>(Guid.NewGuid());
                producers.Add(grain);

                Task promise = grain.BecomeProducer(streamId, streamNamespace, streamProviderName);

                if (useFanOut)
                {
                    pipeline.Add(promise);
                    //promises.Add(promise);
                }
                else
                {
                    await promise;
                }
            }
            if (useFanOut)
            {
                //output.WriteLine("InitializeTopology: Waiting for {0} producers to initialize", promises.Count);
                //await Task.WhenAll(promises);
                //promises.Clear();
                //output.WriteLine("InitializeTopology: Waiting for {0} producers to initialize", pipeline.Count);
                pipeline.Wait();
            }
            //nextGrainId += numProducers;
        }
Пример #29
0
        private Task Test_Stream_Churn_NumStreams_FewPublishers(
            string streamProviderName,
            int pipelineSize,
            int numStreams,
            int numConsumers = 9,
            int numProducers = 4,
            bool warmUpPubSub = true,
            bool warmUpProducers = false,
            bool normalSubscribeCalls = true)
        {
            Console.WriteLine("Testing churn with {0} Streams on {1} Producers with {2} Consumers per Stream",
                numStreams, numProducers, numConsumers);

            AsyncPipeline pipeline = new AsyncPipeline(pipelineSize);

            // Create streamId Guids
            Guid[] streamIds = new Guid[numStreams];
            for (int i = 0; i < numStreams; i++)
            {
                streamIds[i] = Guid.NewGuid();
            }

            int activeConsumerGrains = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName);
            Assert.AreEqual(0, activeConsumerGrains, "Initial Consumer count should be zero");
            int activeProducerGrains = ActiveGrainCount(typeof(StreamLifecycleProducerGrain).FullName);
            Assert.AreEqual(0, activeProducerGrains, "Initial Producer count should be zero");

            if (warmUpPubSub)
            {
                WarmUpPubSub(streamProviderName, streamIds, pipeline);

                pipeline.Wait();

                int activePubSubGrains = ActiveGrainCount(typeof(PubSubRendezvousGrain).FullName);
                Assert.AreEqual(streamIds.Length, activePubSubGrains, "Initial PubSub count -- should all be warmed up");
            }

            Guid[] producerIds = new Guid[numProducers];

            if (numProducers > 0 && warmUpProducers)
            {
                // Warm up Producers to pre-create grains
                for (int i = 0; i < numProducers; i++)
                {
                    producerIds[i] = Guid.NewGuid();
                    var grain = GrainClient.GrainFactory.GetGrain<IStreamLifecycleProducerGrain>(producerIds[i]);
                    Task promise = grain.Ping();

                    pipeline.Add(promise);
                }
                pipeline.Wait();

                int activePublisherGrains = ActiveGrainCount(typeof(StreamLifecycleProducerGrain).FullName);
                Assert.AreEqual(numProducers, activePublisherGrains, "Initial Publisher count -- should all be warmed up");
            }

            var promises = new List<Task>();

            Stopwatch sw = Stopwatch.StartNew();

            if (numProducers > 0)
            {
                // Producers
                for (int i = 0; i < numStreams; i++)
                {
                    Guid streamId = streamIds[i];
                    Guid producerId = producerIds[i % numProducers];
                    var grain = GrainClient.GrainFactory.GetGrain<IStreamLifecycleProducerGrain>(producerId);

                    Task promise = grain.BecomeProducer(streamId, this.StreamNamespace, streamProviderName);

                    promises.Add(promise);
                    pipeline.Add(promise);
                }
                pipeline.Wait();
                promises.Clear();
            }

            // Consumers
            for (int i = 0; i < numStreams; i++)
            {
                Guid streamId = streamIds[i];

                Task promise = SetupOneStream(streamId, streamProviderName, pipeline, numConsumers, 0, normalSubscribeCalls);
                promises.Add(promise);
            }
            pipeline.Wait();

            Task.WhenAll(promises).Wait();
            sw.Stop();

            int consumerCount = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName);
            Assert.AreEqual(activeConsumerGrains + (numStreams * numConsumers), consumerCount, "The right number of Consumer grains are active");

            int producerCount = ActiveGrainCount(typeof(StreamLifecycleProducerGrain).FullName);
            Assert.AreEqual(activeProducerGrains + (numStreams * numProducers), producerCount, "The right number of Producer grains are active");

            int pubSubCount = ActiveGrainCount(typeof(PubSubRendezvousGrain).FullName);
            Assert.AreEqual(streamIds.Length, pubSubCount, "Final PubSub count -- no more started");

            TimeSpan elapsed = sw.Elapsed;
            int totalSubscriptions = numStreams * numConsumers;
            double rps = totalSubscriptions / elapsed.TotalSeconds;
            Console.WriteLine("Subscriptions-per-second = {0} during period {1}", rps, elapsed);
            Assert.AreNotEqual(0.0, rps, "RPS greater than zero");
            return TaskDone.Done;
        }