High Resolution Clock in C#

Clocks in computers have (among others) the following three properties: accuracy, precision, and resolution.

People generally agree on what’s the difference between accuracy and precision/resolution but there seem to be lots of opinions on what’s the difference between precision and resolution and which is which. So I’m going to shamelessly copy a definition I found on Stack Overflow that I’m agreeing with.

  • Precision: the amount of information, i.e. the number of significant digits you report. (E.g. I’m 2m, 1.8m, 1.83m, 1.8322m tall. All those measurements are accurate, but increasingly precise.)
  • Accuracy: the relation between the reported information and the truth. (E.g. “I’m 1.70m tall” is more precise than “1.8m”, but not actually accurate.)
  • Resolution (or Granularity): the smallest time interval that a clock can measure. For example, if you have 1 ms resolution, there’s little point reporting the result with nanosecond precision, since the clock cannot possibly be accurate to that level of precision.

This article will be mainly about resolution (and precision and accuracy to some extend).

DateTime

C# provides the DateTime type (MSDN) that allows to:

  • store a certain point in time
  • get the current date and time (via Now or UtcNow)

First, lets take a look at precision: The DateTime type is basically just a 64 bit integer that counts “ticks”. One tick is 100 nanoseconds (or 0.0001 milliseconds) long (MSDN). So DateTime‘s precision can be up to 0.0001 milliseconds.

Next, resolution. Basically, we’re asking: “How long does it take for value of DateTime.UtcNow to change?” Lets find out.

The following C# code measures the resolution of DateTime.UtcNow:

Console.WriteLine("Running for 5 seconds...");

var distinctValues = new HashSet<DateTime>();
var sw = Stopwatch.StartNew();

while (sw.Elapsed.TotalSeconds < 5)
{
    distinctValues.Add(DateTime.UtcNow);
}

sw.Stop();

Console.WriteLine("Precision: {0:0.000000} ms ({1} samples)",
                  sw.Elapsed.TotalMilliseconds / distinctValues.Count,
                  distinctValues.Count);

This program records all the different values DateTime.UtcNow returns over the course of 5 seconds. This way, we know how often this value changes per second (or millisecond in this example) and that’s the resolution.

According to MSDN the resolution depends on the operating system but in my tests I found out that the resolution also seems to depend on the hardware (unless newer OS versions have a worse resolution).

Machine OS Resolution
Dev Box Windows 7 x64 1 ms
Laptop Windows 8 x64 16 ms

High Resolution Clock

On Windows 8 (or Windows Server 2012) or higher there’s a new API that returns the current time with a much higher resolution:

GetSystemTimePreciseAsFileTime()

Here’s how to use it in C#:

using System;
using System.Runtime.InteropServices;

public static class HighResolutionDateTime
{
    public static bool IsAvailable { get; private set; }

    [DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi)]
    private static extern void GetSystemTimePreciseAsFileTime(out long filetime);

    public static DateTime UtcNow
    {
        get
        {
            if (!IsAvailable)
            {
                throw new InvalidOperationException(
                    "High resolution clock isn't available.");
            }

            long filetime;
            GetSystemTimePreciseAsFileTime(out filetime);

            return DateTime.FromFileTimeUtc(filetime);
        }
    }

    static HighResolutionDateTime()
    {
        try
        {
            long filetime;
            GetSystemTimePreciseAsFileTime(out filetime);
            IsAvailable = true;
        }
        catch (EntryPointNotFoundException)
        {
            // Not running Windows 8 or higher.
            IsAvailable = false;
        }
    }
}

Using the same test code as above but using HighResolutionDateTime.UtcNow as input (instead of DateTime.UtcNow) leads to:

Machine OS Resolution
Dev Box Windows 7 x64 n/a
Laptop Windows 8 x64 0.0004 ms

So, on my laptop the resolution increased by a factor of 40000.

Note: The resolution can never be better/smaller than 0.0001 ms because this is the highest precision supported by DateTime (see above).

Accuracy

To complete this article, lets also talk about accuracy.

DateTime.UtcNow and HighResolutionDateTime.UtcNow are both very accurate. The first one has lower resolution, the second one has higher resolution.

There’s also Stopwatch in C#. Stopwatch has a high resolution. Using Stopwatch.ElapsedTicks as input for resolution measure code from above, I got these results:

Machine OS Resolution
Dev Box Windows 7 x64 0.0004 ms
Laptop Windows 8 x64 0.0004 ms

However, Stopwatch is not very accurate. On my laptop it drifts by 0.2 ms per second, i.e. it gets less accurate over time.

Here’s how to measure the drift/accuracy loss:

var start = HighResolutionDateTime.UtcNow;
var sw = Stopwatch.StartNew();

while (sw.Elapsed.TotalSeconds < 10)
{
    DateTime nowBasedOnStopwatch = start + sw.Elapsed;
    TimeSpan diff = HighResolutionDateTime.UtcNow - nowBasedOnStopwatch;

    Console.WriteLine("Diff: {0:0.000} ms", diff.TotalMilliseconds);

    Thread.Sleep(1000);
}

This gives me an output like this:

Diff: 0,075 ms
Diff: 0,414 ms
Diff: 0,754 ms
Diff: 0,924 ms
Diff: 1,084 ms
Diff: 1,247 ms
Diff: 1,409 ms
Diff: 1,571 ms
Diff: 1,734 ms
Diff: 1,898 ms

As you can see, the difference increases over time. Thus, Stopwatch becomes less accurate over time.

BahnCard 25 besser als BahnCard 50

Bin heute mal wieder über den Fakt gestolpert, dass die BahnCard 25 besser ist als die BahnCard 50 – wenn es um Sparpreise bei der Bahn geht.

Beispiel: Einfache Fahrt von Stuttgart nach Magdeburg mit BahnCard 50: 59,00€

Sparpreis für einfach Fahrt mit BahnCard 50

Gleiche Fahrt mit BahnCard 25: 44,25€

Sparpreis mit BahnCard 25

Das sind immerhin 14,75€ Ersparnis.

Noch krasser wird es, wenn man die Kosten pro Jahr vergleicht (2. Klasse; basierend auf dem Preis von oben):

6 Fahrten/Jahr 8 Fahrten/Jahr 12 Fahrten/Jahr
BC50 (62€/Jahr) 609€ 727€ 963€
BC25 (255€/Jahr) 327,50€ 416€ 593€
Ersparnis 281,50€ (~ 46%) 311€ (~ 43%) 370€ (~ 38%)

Ich denke, diese Zahlen sprechen für sich.

Spaß mit C

Was macht diese Codezeile (sz ist ein TCHAR*)?

_tcsrchr(sz, '\\')[1] = '\0';

C ist einfach toll

Dann begannen Dennis und Brian an einer wirklich verzerrten Version von Pascal zu arbeiten, genannt ‘A’. Als wir merkten, daß andere tatsächlich vorhatten, Programme mit ‘A’ zu entwerfen, fügten wir rasch zusätzliche kryptische Eigenschaften hinzu, und entwickelten daraufhin B, BCPL und schließlich C. Wir hörten auf, als es uns gelang, den Ausdruck

for(;P("\\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("| "+(*u/4)%2);

fehlerfrei zu kompilieren.

Quelle

Switch Azure Development Storage to SQL Server Express – Step by Step

While developing for Windows Azure, I recently got lots of StorageExceptions reading “(500) Internal Server Error.”.

After some googling I found an article that says I should switch to SQL Server Express. So far, so good. But how do I do this?

  1. Download SQL Server Express. (If you’re using Visual Studio, chances are that you’ve already installed SQL Server Express.) You may also want to down SQL Server Management Studio (same download link).
  2. Make sure SQL Server is running. Go to All Programs -> Microsoft SQL Server 2012 -> Configuration Tools -> SQL Server Configuration Manager. Under SQL Server Services make sure SQL Server (SQLEXPRESS) is running. (Otherwise start it by right-clicking on it and clicking on Start.)
  3. (Optional) Open SQL Server Management Studio.

    • In Connect to Server under Server Name click on the dropdown button and choose <Browse for more...>. You can then select your local SQL server instance. It should by named like COMPUTERNAME\SQLEXPRESS. (For Authentication keep Windows Authentication.)
    • Under Databases later something like DevelopmentStorageDb22 will appear, once we switched the development storage to SQL Sever.
  4. Open All Programs -> Windows Azure SDK, right-click on Windows Azure Storage command line and choose Run as administrator.

That’s it.

Update: The Azure Development Table Storage’s size seems to be limited to 4 GB (even though since SQL Server Express 2012 it should be 10 GB). You can see the size of your database (or of the PRIMARY file group, to be more precise) in the database properties in SQL Server Configuration Manager:

full-database.png

As you can see in the image, my database is already full. (Initially the size is about 3 MB.) Once you get there, you’ll see error messages like these in your Development Storage logs:

Could not allocate space for object ‘dbo.TableRow’.’PK_dbo.TableRow’ in database ‘DevelopmentStorageDb22′ because the ‘PRIMARY’ filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.

To “fix” this problem, you can only delete the database or delete Table Storage tables to decrease the database’s size.