private static void CoroutineWaitTriggersTest() { const int WaitNum = 1000000; const float AverageWaitTime = 1000; var eventQueue = new EventQueue(); var scheduler = new EventCoroutineScheduler(eventQueue); var coroutine = new SimpleCoroutine(WaitNum); scheduler.Execute(coroutine); var random = new Random(23132); DateTime start = DateTime.UtcNow; int coroutinesSpawned = 0; int coroutinesUpdated = 0; while (true) { while (true) { if (!eventQueue.TryDequeue(out IEvent ev)) { break; } coroutinesUpdated++; scheduler.Update((ICoroutineEvent)ev); } scheduler.NewFrame(1f); eventQueue.NewFrame(); // Enqueue new coroutine if (coroutinesSpawned < WaitNum) { ++coroutinesSpawned; scheduler.Execute( new WaitForSecondsCoroutine((float)random.NextDouble() * 2.0f * AverageWaitTime) ); } else { // Each coroutine is two event updates if (coroutinesUpdated >= WaitNum * 2) { break; } } } DateTime end = DateTime.UtcNow; Console.WriteLine($"Time to process {WaitNum:n0} trigger coroutine with average wait time {AverageWaitTime:n} by event scheduler: {(end - start).TotalSeconds} s"); }
private static void CoroutinePollTimersTest() { const int WaitNum = 10000; const float AverageWaitTime = 1000; var eventQueue = new EventQueue(); var scheduler = new EventCoroutineScheduler(eventQueue); var coroutine = new SimpleCoroutine(WaitNum); scheduler.Execute(coroutine); var random = new Random(23132); DateTime start = DateTime.UtcNow; int coroutinesSpawned = 0; int coroutinesUpdated = 0; while (true) { while (true) { if (!eventQueue.TryDequeue(out IEvent ev)) { break; } coroutinesUpdated++; scheduler.Update((ICoroutineEvent)ev); } scheduler.NewFrame(1f); eventQueue.NewFrame(); // Enqueue new coroutine if (coroutinesSpawned < WaitNum) { ++coroutinesSpawned; scheduler.Execute( new PollWaitForSecondsCoroutine((float)random.NextDouble() * 2.0f * AverageWaitTime) ); } else { // This timing is not correct as "A LOT" of coroutines are still not finished but it shows the differenct break; } } DateTime end = DateTime.UtcNow; Console.WriteLine($"Time to process {WaitNum:n0} *polling wait* coroutine with average wait time {AverageWaitTime:n} by event scheduler: {(end - start).TotalSeconds} s"); }
public void NextFrame() { var eventQueue = new EventQueue(); var scheduler = new EventCoroutineScheduler(eventQueue); var coroutine = new NextFrameCoroutine(); Assert.Equal(CoroutineStatus.WaitingForStart, coroutine.Status); scheduler.Execute(coroutine); Assert.Equal(CoroutineStatus.Running, coroutine.Status); // Start event Assert.Equal(1, eventQueue.Count); scheduler.Update(eventQueue.DequeueEvent()); Assert.Equal(0, eventQueue.CountCurrentFrame); Assert.Equal(1, eventQueue.Count); scheduler.NewFrame(0.1f); eventQueue.NewFrame(); scheduler.Update(eventQueue.DequeueEvent()); Assert.Equal(CoroutineStatus.CompletedNormal, coroutine.Status); }
private static void CoroutineUpdateTest() { const int LoopsNum = 10000000; { var scheduler = new InterleavedCoroutineScheduler(); var coroutine = new SimpleCoroutine(LoopsNum); scheduler.Execute(coroutine); DateTime start = DateTime.UtcNow; while (coroutine.Status != CoroutineStatus.CompletedNormal) { scheduler.Update(0); } DateTime end = DateTime.UtcNow; Console.WriteLine($"Time to process {LoopsNum:n0} coroutine updates by interleved scheduler: {(end - start).TotalSeconds} s"); } { var eventQueue = new EventQueue(); var scheduler = new EventCoroutineScheduler(eventQueue); var coroutine = new SimpleCoroutine(LoopsNum); scheduler.Execute(coroutine); DateTime start = DateTime.UtcNow; while (true) { if (!eventQueue.TryDequeue(out IEvent ev)) { break; } scheduler.Update((ICoroutineEvent)ev); scheduler.NewFrame(0); eventQueue.NewFrame(); } DateTime end = DateTime.UtcNow; Console.WriteLine($"Time to process {LoopsNum:n0} coroutine updates by event scheduler: {(end - start).TotalSeconds} s"); } }
public int Update(float deltaTime, int maxEvents = int.MaxValue, bool startNewEvents = true) { if (criticalException != null) { throw criticalException; } int eventsProcessed = 0; eventQueue.NewFrame(); scheduler.NewFrame(deltaTime); try { for (int i = 0; i < maxEvents; i++) { if (!eventQueue.TryDequeue(out IEvent ev)) { break; } switch (ev) { case ICoroutineEvent cev: { eventsProcessed++; Exception ex = scheduler.Update(cev); if (ex != null) { throw ex; } } break; case FullReactorEvent rev: { if (rev.ReplyID != 0) { eventsProcessed++; if (pendingRPCWaits.TryGetValue(rev.ReplyID, out RPCWait value)) { pendingRPCWaits.Remove(rev.ReplyID); value.Trigger(rev); continue; } listener?.OnMissedReplyEvent(rev.Source, rev.Event, rev.ReplyID); continue; } if (startNewEvents) { currentEvent = rev; currentInCriticalSection = false; try { OnEvent(rev.Event); } catch (Exception ex) { if (currentInCriticalSection) { throw ex; } else { listener?.OnValidationException(ex); } } currentInCriticalSection = true; currentEvent = null; } else { eventQueue.EnqueueNextFrame(rev); } } break; default: throw new ReactorException("Invalid event type"); } } } catch (Exception ex) { listener?.OnCriticalException(ex); criticalException = ex; throw ex; } return(eventsProcessed); }