@@ -64,7 +64,7 @@ public class Signals
64
64
public int noSignals ;
65
65
private int foundSignals ;
66
66
67
- private static int updatecount ;
67
+ private static int UpdateIndex ;
68
68
69
69
public List < TrackCircuitSection > TrackCircuitList ;
70
70
private Dictionary < int , CrossOverItem > CrossoverList = new Dictionary < int , CrossOverItem > ( ) ;
@@ -553,6 +553,11 @@ private void BuildSignalWorld(Simulator simulator, SignalConfigurationFile sigcf
553
553
554
554
} //BuildSignalWorld
555
555
556
+ Stopwatch UpdateTimer = new Stopwatch ( ) ;
557
+ long UpdateCounter = 0 ;
558
+ long UpdateTickTarget = 10000 ;
559
+ // long DebugUpdateCounter = 0;
560
+
556
561
/// <summary>
557
562
/// Update : perform signal updates
558
563
/// </summary>
@@ -562,30 +567,41 @@ public void Update(bool preUpdate)
562
567
563
568
if ( foundSignals > 0 )
564
569
{
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 ] ;
581
581
if ( signal != null && ! signal . noupdate ) // to cater for orphans, and skip signals which do not require updates
582
582
{
583
583
signal . Update ( ) ;
584
+ updates ++ ;
584
585
}
586
+ updateStep ++ ;
587
+
588
+ // in preupdate, process all
589
+ if ( ! preUpdate && updates % 10 == 0 && Stopwatch . GetTimestamp ( ) >= targetTicks ) break ;
585
590
}
591
+ UpdateCounter += updates ;
592
+ UpdateTimer . Stop ( ) ;
586
593
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 ;
589
605
}
590
606
}
591
607
0 commit comments