0

I am implementing some diagnostics for an application where the user can see how quickly the graphics are updating and I have encountered some seemingly strange behavior. My graphic update function is called using a Timer, and it looks like this:

private void RefreshScreen(object sender, EventArgs e)
{
    DateTime begin = DateTime.Now;

    // Do some updating...

    DateTime end = DateTime.Now;
    graphicsUpdateRate = (end - begin).TotalMilliseconds;
}

When I display the graphicsUpdateRate to a separate window later in another function, it is almost always 0. Occasionally it will actually be ~0.5, but I've never seen it below ~0.48. Is there some reason why it would clamp it to 0 if it were below this? Is there anything I'm missing when using TimeSpan.TotalMilliseconds? I'm rather confused by this since it seems so random.

RichardJones
  • 149
  • 1
  • 10
  • 3
    `DateTime.Now` is just not that accurate, if you want to measure a time between a start and a end use `Stopwatch` instead. – Scott Chamberlain Jan 03 '17 at 21:25
  • Is it possible that when you display it you are rounding or truncating? – Theo Jan 03 '17 at 21:25
  • 1
    Possibly a duplciate of http://stackoverflow.com/questions/2143140/c-sharp-datetime-now-precision – Scott Chamberlain Jan 03 '17 at 21:25
  • couldn't you just access `(end - begin).Ticks` each of these is 100 nanoseconds, which is 1e-4 milliseconds. Update: this won't work, ignore – abc123 Jan 03 '17 at 21:28
  • @abc123 no, you would still get 0 ticks because the value of `.Ticks` may be returned twice for two calls very close to each other. – Scott Chamberlain Jan 03 '17 at 21:29
  • @ScottChamberlain lol, i didn't look at their code...which is using DateTime as a StopWatch...I was thinking about this purely from a stored datetime standpoint...woops – abc123 Jan 03 '17 at 21:30
  • @abc123 I wanted the result to be displayed in Milliseconds, which is why I chose that. I suppose I could use Ticks, but then I would need to do an extra calculation that I assumed was built into TotalMilliseconds. – RichardJones Jan 03 '17 at 21:32
  • @RichardJones i understand what you want but 0.1 milliseconds is 0 milliseconds. if you look at DateTime as an Object the millisecond property is `int` not a floating point – abc123 Jan 03 '17 at 21:33
  • 2
    @abc123 he does not have a `DateTime` doing `(end - begin)` returns a `TimeSpan` and TimeSpan's `TotalMilliseconds` property returns a double. @Richard, you still will get 0 as a result if you use ticks. Both calls to `DateTime.Now` are returning the same `DateTime` value because `.Now` is not updated that often. – Scott Chamberlain Jan 03 '17 at 21:35

1 Answers1

5

You should be using a StopWatch for this.

Something like:

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
// Do something.
stopwatch.Stop();
graphicsUpdateRate  = stopwatch.ElapsedMilliseconds;

You could read about reasons to use StopWatch here:

Is DateTime.Now the best way to measure a function's performance?

Community
  • 1
  • 1
Maksim Simkin
  • 9,561
  • 4
  • 36
  • 49
  • I have nothing against Stopwatch other than the fact I had never heard of it when I implemented this. I assume it is more accurate than DateTime/TimeSpan? – RichardJones Jan 03 '17 at 21:25
  • 1
    @RichardJones "What time is it" and "How long does it take" are two very different questions. Don't use a tool designed for one to do the other (AKA, for measuring the time between two events it is a lot more accurate) – Scott Chamberlain Jan 03 '17 at 21:27
  • 1
    While correct, this answer doesn't actually address the asked question (why does it clamp). –  Jan 03 '17 at 21:29
  • When using a Stopwatch, the result is always 0. – RichardJones Jan 03 '17 at 21:31
  • @RichardJones then you likely didn't start/stop it. Or your event is quicker than 1 millisecond. check `Stopwatch.ElapsedTicks` to see if you are using it right. – abc123 Jan 03 '17 at 21:32
  • @abc123 I'm pretty sure I used it correctly. My event is definitely quicker than 1 millisecond. And the answer used ElapsedMilliseconds, not ElapsedTicks. – RichardJones Jan 03 '17 at 21:34
  • @RichardJones, i merely stated that to verify that you are using it correctly please check the ElapsedTicks. If that event is 0 then you aren't using it correctly. Simply because Starting the stop watch then immediately topping the stop watch will not be 0. https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.elapsedticks(v=vs.110).aspx – abc123 Jan 03 '17 at 21:36
  • @abc123 I am using it correctly, ElapsedTicks is returning ~150. I suppose it is too fast to record and display in Milliseconds? – RichardJones Jan 03 '17 at 21:37
  • 1
    @RichardJones Use the [Frequency](https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.frequency(v=vs.110).aspx) property to determine how long 150 ticks is on your system with the current timer frequency. – Quantic Jan 03 '17 at 21:47