Samuel Ricky Samuel Ricky - 4 months ago 18 Question

Ticks are inconsistent and are fluctuating

I have a sub and a button. And the code is like this :

Private Sub plus(ByRef a As Integer)
For i = 0 To a
a = a + a
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim i As Integer = 19
Dim sw As New Stopwatch
End Sub

when I run the sub is by clicking the "button1" the program to output 310 thats means 310 is sw.elapsedticks

When I run the sub again by clicking the "button1" again, the program to output 1 << JUST ONE ellapsedticks

how can it be like that ?

I tried to stop my program and I run it again, and then I click its button again, it happened the same, which is worth 272 stopwatch elapsedticks then after I click again stopwatch , elapsedticks instead be 1 again

please explain why it could happen?


The StopWatch class will fallback to using DateTime class and uses ticks for the measurements if your hardware doesn't support high-performance counter. Most computer's now day's, at least from Windows 2000 and later, have high-performance counters. With this in mind, the .NET Stopwatch class is based on this high frequency timer. In general, calling Start queries the performance counter and stores the value. When you Stop, it queries the performance counter again. Then the elapsed time is a simple subtraction of those two values to give you your ElapsedTicks.

Here are a few items to have a look at for further explanation...

This property just makes a call to GetRawElapsedTicks()

  public long ElapsedTicks { 
        get { return GetRawElapsedTicks(); }

The below function returns the actual time that has elapsed from the time the stopwatch was started to when the stopwatch Stop method was called. As mentioned above, the elapsed time is a simple subtraction of those two values you can see that below: currentTimeStamp - startTimeStamp.

 // Get the elapsed ticks.        
        public long GetRawElapsedTicks() {
        private long GetRawElapsedTicks() {
            long timeElapsed = elapsed;

            if( isRunning) {
                // If the StopWatch is running, add elapsed time since
                // the Stopwatch is started last time. 
                long currentTimeStamp = GetTimestamp();                 
                long elapsedUntilNow = currentTimeStamp - startTimeStamp;
                timeElapsed += elapsedUntilNow;
            return timeElapsed;

Above you may notice the #if FEATURE_NETCORE and wonder what it is. These are called preprocessor commands. Basically they work like if-else statements except that if the condition isn't met it will not include the code at compile time as it's a pre-compile decision and not runtime...

With this all said, it was mentioned above already by Hans Passant about just in time (JIT) compiling. All of this I mentioned above breaks this down further for explanation. The real reason for the difference is the time it is taking for it to compile and run the first time.

Another thing to mention. The stopwatch class uses a long variable type to store what they call frequency. Frequency" stores the frequency of the high-resolution performance counter if one exists, otherwise it will store TicksPerSecond. The frequency cannot change while the system is running, so it's only initialized once.

Below are other constants that have a great deal with frequency and how it's calculated as well.

 private const long TicksPerMillisecond = 10000;
 private const long TicksPerSecond = TicksPerMillisecond * 1000;

When you create a new instance of the StopWatch class this is what is ran.

bool succeeded = SafeNativeMethods.QueryPerformanceFrequency(out Frequency);            
            if(!succeeded) {
                IsHighResolution = false; 
                Frequency = TicksPerSecond;
                tickFrequency = 1;
            else {
                IsHighResolution = true;
                tickFrequency = TicksPerSecond;
                tickFrequency /= Frequency;

Frequency as you can now see , has a big role in setting up how the elapsed time is going to be calculated and how often the tick is going to occur. Even when you stop your application it doesn't matter as the frequency is stored at this time. The only way to reset the frequency is to reboot your machine.