Skip to content

Analysis of the .NET timers with 1ms tick size

Notifications You must be signed in to change notification settings

nikvoronin/timers-are-not-what-they-seem

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Timers Are Not What They Seem

Analysis of the .NET timers with 1ms tick size:

If you don't have Jupiter Notebooks installed locally, just use online Jupyter NBViewer

Results

  • System.Timers.Timer and System.Threading.Timer are limited with 15.6 ms by default.
  • Multimedia Timer. Always stable but legacy.
  • TwinCAT3 notifications. Not good at client side.
  • Independed threads. Not stable at heavy load.

Conclusion. Should use legacy Multimedia Timer or modern real-time systems like TC3.

Goodreads

CPU Burner

Loads all cpu's cores w/ 100%

while (!token.IsCancellationRequested) {
    Parallel.For( 0, Environment.ProcessorCount, ( i ) => {
        double a = 1000.0;
        for (int j = 0; j < 10_000_000; j++) {
            if (token.IsCancellationRequested)
                break;

            a /= j * (i + 1);
        }
    } );
}

See CpuBurner.cs

Multimedia Timer

Legacy functions from early versions of Windows

[DllImport( "winmm.dll", SetLastError = true, EntryPoint = "timeSetEvent" )]
internal static extern UInt32 TimeSetEvent( UInt32 msDelay, UInt32 msResolution, MultimediaTimerCallback callback, ref UInt32 userCtx, UInt32 eventType );

[DllImport( "winmm.dll", SetLastError = true, EntryPoint = "timeKillEvent" )]
internal static extern void TimeKillEvent( UInt32 uTimerId );

See MultimediaTimer.cs

TwinCAT 3. Soft Real-Time System

RT-system Side

System tick and PLC-Runtime both are 1 millisecond.

PROGRAM MAIN
VAR
    tick: BOOL;
END_VAR

tick := NOT tick;

END_PROGRAM

Client Side

AdsClient client = new AdsClient();
client.Connect( AmsPort.R0_RTS + 1 );

client.AdsNotification += (s,e) => DoTick();
var notiSets = new NotificationSettings( AdsTransMode.OnChange, 1, 0 );
var h_tick = client.AddDeviceNotification( "MAIN.tick", 1, notiSets, null );