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 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); }
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"); }
private Task Test_Stream_Churn_NumStreams( string streamProviderName, int pipelineSize, int numStreams, int numConsumers = 9, int numProducers = 1, bool warmUpPubSub = true, bool normalSubscribeCalls = true) { output.WriteLine("Testing churn with {0} Streams with {1} Consumers and {2} Producers per Stream NormalSubscribe={3}", numStreams, numConsumers, numProducers, normalSubscribeCalls); AsyncPipeline pipeline = new AsyncPipeline(pipelineSize); var promises = new List <Task>(); // Create streamId Guids Guid[] streamIds = new Guid[numStreams]; for (int i = 0; i < numStreams; i++) { streamIds[i] = Guid.NewGuid(); } 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" } int activeConsumerGrains = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName); Assert.Equal(0, activeConsumerGrains); // "Initial Consumer count should be zero" Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < numStreams; i++) { Task promise = SetupOneStream(streamIds[i], streamProviderName, pipeline, numConsumers, numProducers, normalSubscribeCalls); promises.Add(promise); } Task.WhenAll(promises).Wait(); sw.Stop(); int consumerCount = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName); Assert.Equal(activeConsumerGrains + (numStreams * numConsumers), consumerCount); // "The correct number of new Consumer grains are active" 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); }
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)); } }
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(); }
//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(); }
//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(); }
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); }
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)); }
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; }
private Task Test_Stream_Churn_NumStreams( string streamProviderName, int pipelineSize, int numStreams, int numConsumers = 9, int numProducers = 1, bool warmUpPubSub = true, bool normalSubscribeCalls = true) { Console.WriteLine("Testing churn with {0} Streams with {1} Consumers and {2} Producers per Stream NormalSubscribe={3}", numStreams, numConsumers, numProducers, normalSubscribeCalls); AsyncPipeline pipeline = new AsyncPipeline(pipelineSize); var promises = new List<Task>(); // Create streamId Guids Guid[] streamIds = new Guid[numStreams]; for (int i = 0; i < numStreams; i++) { streamIds[i] = Guid.NewGuid(); } 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"); } int activeConsumerGrains = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName); Assert.AreEqual(0, activeConsumerGrains, "Initial Consumer count should be zero"); Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < numStreams; i++) { Task promise = SetupOneStream(streamIds[i], streamProviderName, pipeline, numConsumers, numProducers, normalSubscribeCalls); promises.Add(promise); } Task.WhenAll(promises).Wait(); sw.Stop(); int consumerCount = ActiveGrainCount(typeof(StreamLifecycleConsumerGrain).FullName); Assert.AreEqual(activeConsumerGrains + (numStreams * numConsumers), consumerCount, "The correct number of new Consumer grains are active"); 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; }
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; }
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)); }
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; }
//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(); }