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"); }
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 = 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 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); }
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); }
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; }
public void Add_AddTypeThatIsNotAMiddleware_ThrowsException() { var pipeline = new AsyncPipeline <PersonModel>(new ActivatorMiddlewareResolver()); PipelineNetAssert.ThrowsException <ArgumentException>(() => { pipeline.Add(typeof(AsyncPipelineTests)); }); }
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, 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 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(); }
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); }
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); }
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; }
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 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; }
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; }
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); }
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; }
//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(); }
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; }
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); }
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); }
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 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; }