@@ -64,7 +64,7 @@ public class Signals
6464 public int noSignals ;
6565 private int foundSignals ;
6666
67- private static int updatecount ;
67+ private static int UpdateIndex ;
6868
6969 public List < TrackCircuitSection > TrackCircuitList ;
7070 private Dictionary < int , CrossOverItem > CrossoverList = new Dictionary < int , CrossOverItem > ( ) ;
@@ -553,6 +553,11 @@ private void BuildSignalWorld(Simulator simulator, SignalConfigurationFile sigcf
553553
554554 } //BuildSignalWorld
555555
556+ Stopwatch UpdateTimer = new Stopwatch ( ) ;
557+ long UpdateCounter = 0 ;
558+ long UpdateTickTarget = 10000 ;
559+ // long DebugUpdateCounter = 0;
560+
556561 /// <summary>
557562 /// Update : perform signal updates
558563 /// </summary>
@@ -562,30 +567,41 @@ public void Update(bool preUpdate)
562567
563568 if ( foundSignals > 0 )
564569 {
565-
566- // loop through all signals
567- // update required part
568- // in preupdate, process all
569-
570- int totalSignal = SignalObjects . Length - 1 ;
571-
572- int updatestep = ( totalSignal / 20 ) + 1 ;
573- if ( preUpdate )
574- {
575- updatestep = totalSignal ;
576- }
577-
578- for ( int icount = updatecount ; icount < Math . Min ( totalSignal , updatecount + updatestep ) ; icount ++ )
579- {
580- SignalObject signal = SignalObjects [ icount ] ;
570+ // loop through all the signals, but only one batch of signals with every call to this method.
571+ // update one batch of signals. Batch ends when time taken exceeds 1/20th of time for all signals.
572+ // Processing 1/20th of signals in each batch gave a jerky result as processing time varies greatly.
573+ // Smoother results now that equal time is given to each batch and let the batch size vary.
574+ var updates = 0 ;
575+ var updateStep = 0 ;
576+ var targetTicks = Stopwatch . GetTimestamp ( ) + UpdateTickTarget ;
577+ UpdateTimer . Start ( ) ;
578+ while ( updateStep < foundSignals )
579+ {
580+ var signal = SignalObjects [ ( UpdateIndex + updateStep ) % foundSignals ] ;
581581 if ( signal != null && ! signal . noupdate ) // to cater for orphans, and skip signals which do not require updates
582582 {
583583 signal . Update ( ) ;
584+ updates ++ ;
584585 }
586+ updateStep ++ ;
587+
588+ // in preupdate, process all
589+ if ( ! preUpdate && updates % 10 == 0 && Stopwatch . GetTimestamp ( ) >= targetTicks ) break ;
585590 }
591+ UpdateCounter += updates ;
592+ UpdateTimer . Stop ( ) ;
586593
587- updatecount += updatestep ;
588- updatecount = updatecount > totalSignal ? 0 : updatecount ;
594+ if ( UpdateIndex + updateStep >= foundSignals )
595+ {
596+ // Calculate how long it takes to update all signals and target 1/20th of that
597+ // Slow adjustment using clamp stops it jumping around too much
598+ var ticksPerSignal = ( double ) UpdateTimer . ElapsedTicks / UpdateCounter ;
599+ UpdateTickTarget = ( long ) MathHelper . Clamp ( ( float ) ( ticksPerSignal * foundSignals / 20 ) , UpdateTickTarget - 100 , UpdateTickTarget + 100 ) ;
600+ // if (++DebugUpdateCounter % 10 == 0) Trace.WriteLine($"Signal update for {UpdateCounter,5} signals took {(double)UpdateTimer.ElapsedTicks * 1000 / Stopwatch.Frequency,9:F6} ms ({ticksPerSignal * 1000 / Stopwatch.Frequency,9:F6} ms/signal); new {(double)UpdateTickTarget * 1000 / Stopwatch.Frequency,6:F6} ms target");
601+ UpdateTimer . Reset ( ) ;
602+ UpdateCounter = 0 ;
603+ }
604+ UpdateIndex = ( UpdateIndex + updateStep ) % foundSignals ;
589605 }
590606 }
591607
0 commit comments