Windows system timer granularity

While running one of my apps on a Windows 10 VM I noticed that the timing was much different to that seen on the host PC. After lots of digging I finally found that the granularity of the system timer on the VM was around 16ms versus around 0.5ms on the host PC. My app is using some 1-5 millisecond sleeps but when the granularity is 16ms then 1ms becomes 16! (The actual granularity is 15.6ms due to a default 64Hz timer frequency).

Some cool resources on the web related to this:

Solved my problems by setting the granularity to the minimum supported by the PC; this setting remains in place until the application exits. So it just seems that my VM doesn’t have anything running that would otherwise cause the timer to run more quickly than the default (of 64Hz), whereas my development PC must have all sorts that are running the timer flat out; probably one reason my battery goes down more quickly than expected!

To query and change the granularity I used theses methods via C#:

I then wrote a little wrapper class to let me play with the timings using the .Net TimeSpan. Note: this is a frustrating struct to use because it really doesn’t want to use fractions of a millisecond without more than a bit of persuasion, specifically because FromMilliseconds will only consider the requested value to the nearest millisecond.

/// <summary>
/// Utility to query the timer resolution
/// </summary>
class TimerResolution
{
    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern int NtQueryTimerResolution(out int MinimumResolution, out int MaximumResolution, out int CurrentResolution);


    [DllImport("ntdll.dll", SetLastError = true)]
    private static extern int NtSetTimerResolution(int DesiredResolution, bool SetResolution, out int CurrentResolution);


    private static TimeSpan TimeSpanFrom100nsUnits(int valueIn100nsUnits)
    {
        var nanoseconds = (double)valueIn100nsUnits * 100.0;
        var seconds = nanoseconds / 1000000000.0;
        var ticks = seconds * System.Diagnostics.Stopwatch.Frequency;
        var timeSpan = TimeSpan.FromTicks((long)ticks);
        return timeSpan;
    }


    private static (TimeSpan min, TimeSpan max, TimeSpan cur) Query()
    {
        NtQueryTimerResolution(out var min, out var max, out var cur);
        return (min: TimeSpanFrom100nsUnits(min), max: TimeSpanFrom100nsUnits(max), cur: TimeSpanFrom100nsUnits(cur));
    }


    /// <summary>Gets the minimum timer resolution</summary>
    public static TimeSpan MinResolution => Query().min;


    /// <summary>Gets the maximum timer resolution</summary>
    public static TimeSpan MaxResolution => Query().max;


    /// <summary>Gets/sets the current timer resolution</summary>
    public static TimeSpan CurrentResolution
    {
        get { return Query().cur; }

        set
        {
            var valueInSeconds = value.TotalMilliseconds / 1000.0;
            var valueInNanoseconds = valueInSeconds * 1000000000.0;
            var valueIn100Nanoseconds = (int)(valueInNanoseconds / 100.0);
            NtSetTimerResolution(DesiredResolution: valueIn100Nanoseconds, SetResolution: true, out _);
        }
    }
}

A little test app on my VM produced these results…

Minimum resolution:   15.6ms
Maximum resolution:   0.5ms
Current resolution:   15.6ms

Attempt to change to 2ms
Current resolution:   00:00:00.0020000
DateTime granularity: 00:00:00.0020970
Sleep 0:              00:00:00.0000009
Sleep 1:              00:00:00.0020053

Attempt to change to 5ms
Current resolution:   00:00:00.0050000
DateTime granularity: 00:00:00.0050328
Sleep 0:              00:00:00.0000012
Sleep 1:              00:00:00.0049719

Attempt to change to 0.5ms
Current resolution:   00:00:00.0005000
DateTime granularity: 00:00:00.0005471
Sleep 0:              00:00:00.0000008
Sleep 1:              00:00:00.0011774

Attempt to change to 15.6ms
Current resolution:   00:00:00.0156250
DateTime granularity: 00:00:00.0156280
Sleep 0:              00:00:00.0000011
Sleep 1:              00:00:00.0155707

C# from clause vs nested foreach loops

Short story: writing a unit test for an image processing function, I had the following key parameters for each test:

enum Algorithm {  A, B, C }; 
enum ImageFormat {  Gray, Color }; 
enum ImageSize {  Small, Medium, Large };

I wrote a core test function that worked on just one combination of the 3 parameters. E.g.

void Test(
    Algorithm algorithm, 
    ImageFormat imageFormat, 
    ImageSize imageSize)
{
    Console.WriteLine($"Testing algorithm {algorithm} for " +
        {imageFormat} image with {imageSize} size");

    // the test...
}

Next, I wrote a utility to make iterating the values of an enumeration a little easier.. still not sure why this isn’t part of .Net yet:

class EnumHelper<T>
{
    static public T[] Values
    {
        get { return (T[])Enum.GetValues(typeof(T)); }
    }
}

Then, I wrote the nested loops that built each combination and sent them for testing:

void TestAllV1()
{
    foreach (var algorithm in EnumHelper<Algorithm>.Values)
    {
        foreach (var imageFormat in EnumHelper<ImageFormat>.Values)
        {
            foreach (var imageSize in EnumHelper<ImageSize>.Values)
            {
                Test(algorithm, imageFormat, imageSize);
            }
        }
    }
}

Now there’s nothing really wrong with the above, but it looked like something that should be able to be written more simply. So I came up with this:

void TestAllV2()
{
    var tests =
        from algorithm in EnumHelper<Algorithm>.Values
        from imageFormat in EnumHelper<ImageFormat>.Values
        from imageSize in EnumHelper<ImageSize>.Values
        select (algorithm, imageFormat, imageSize);


    foreach (var test in tests)
    {
        Test(test.algorithm, test.imageFormat, test.imageSize);
    }
}

The use of the from clause seems better, mainly due to the reduced level of nesting. The Visual Studio 2019 code analysis metrics are interesting:

MemberMICycC
ClsC
TestAllV1() 76 4 7
TestAllV2()69 2 18

Where:

  • MI: Maintainability Index
  • CycC: Cyclomatic Complexity
  • ClsC: Class coupling

So the foreach approach is (allegedly!) more maintainable, while the from clause method has a lower cyclomatic complexity. This latter metric reinforces the idea that this is slightly simpler than the foreach technique.

It’s also quite easy to add specific filtering inside the tests generator. For example, to quickly stop testing the B algorithm:

var tests =
    from algorithm in EnumHelper<Algorithm>.Values
    where algorithm != Algorithm.B
    from imageFormat in EnumHelper<ImageFormat>.Values
    from imageSize in EnumHelper<ImageSize>.Values
    select (algorithm, imageFormat, imageSize);

Food for thought šŸ™‚

Edit: actually found another way to do this using the Linq SelectMany method, but I’m not keen on this:

void TestAllV3()
{
    var tests =
        EnumHelper<Algorithm>.Values.SelectMany(
            algorithm => EnumHelper<ImageFormat>.Values.SelectMany(
                imageFormat => EnumHelper<ImageSize>.Values.Select(
                    imageSize => (algorithm, imageFormat, imageSize))));

    foreach(var test in tests)
    {
        Test(test.algorithm, test.imageFormat, test.imageSize);
    }
}

Apple Trackpad on Windows with 3-finger drag!

A month ago, when I needed to get a new laptop for work, I switched from a MacBook Pro to a Dell XPS 9750, saving Ā£100’s of pounds for what on paper is an almost identical laptop. Except it isn’t. Dell’s XPS is astonishingly good, and it’s a priviledge to own one, but I’ve become an Apple devotee over the years and can’t change it. My days are spent programming for Windows so I need a fast PC development environment and therefore the XPS makes sense. With the MBP I need to use VMWare Fusion or Parallels, and Apple are really pushing my (and other people’s) limits by charging so much money for memory and SSD upgrades. So I went for the XPS.Ā 

Of all the little things I miss, 3 finger dragging is way up there. To be fair, the XPS’s trackpad is one of the best out there for Windows laptops, and with Windows 10 there is a double-tap to drag gesture which is fantastic. But the trackpad is too small and two taps (versus a single 3-finger drag) are one tap too many.

After a bit of Googling, I found Magic Utilities, a company that make drivers and utilities for Apple wireless keyboards, the magic mouse, and the Magic Trackpad. When I used Windows as a virtual machine on the MBP I got used to a particular mapping of the Alt and Cmd keys; the keyboard utility app lets me restore these mapping. Also, I’ve just discovered that the Eject key now becomes delete, although my fingers have 5 years of muscle memory which means that delete = Function + Backspace.

(Now, with the Apple keyboard, the function and control keys are where they should be IMO! There are loads of people asking Dell whether it’s possible to swap these keys on the Dell keyboards but it really can’t be done.)

Apple’s wireless Magic Trackpad performs terribly on Windows 10 by default. There are few (if any) gestures, and the whole feel of the cursor on the screen is terrible. Magic Utilities Trackpad app changes this completely:

Now I can scroll, drag, single-finder tap, and not a mechanical click in sight.Ā 

I’ve now bought a one year licence after trialling this for a couple of weeks without any problems. Now I work with the XPS lid closed and just the wireless mouse and keyboard in front of an external 4K monitor.Ā 

For the odd occasional where I might work 12 hours a day the little things, both positive and negative, soon accumulate, so the ~Ā£20 cost of this bundle is really a bargain.Ā 

Now if I could just find a similar utility to turn Windows 10 into Mac OS… šŸ˜€

Scanning receipts from iPhone to OneNote (App Store)

There are many ways to scan a document, such as a receipt, and import it into OneNote. I’m now using the App Store version of OneNote on Windows10 and one of the (many) limiations is the inability to resize large images without having to cut them out, edit, and paste back in.

I’ve tried a bunch of scanning apps on the iPhone and one of the main issues is finding something than can scan, including auto-detection of document borders, adjust brightness and contrast, and send to OneNote. The Adobe Scanner app for the iPhone is awesome but the PDF appears in OneNote as an icon and doesn’t appear to want to change into a readable document!

So for now the fastest way I’ve found is to use the Microsoft Office Lens iPhone app – this does a great job of scanning and although I can’t change the image resolution I can set it as a simple black and white image and send directly to OneNote.

First, run Office Lens.

1

 

Then let it find your document – it helps to have some natural contrast between the edges of the document and the background.Ā 

Make sure that the Document option is selected:

Display the filters after scanning the document – just slide your finger up to view them:

I’m choosing the black and white option as it seems to help keep the file size down and also makes the receipt more readable:

After applying the filter click on the Done button at the bottom and go through the export options:

Enter a title for the note and choose which section on OneNote to save it to:

 

It would be a great improvement if the Office Lens app could have a quality or file size option to reduce the amount of data stored in ON. There are already suggestions for this on the Office Lens feedback hub going back to 2015 – not sure if anyone’s listening tho!

TimeSpan.FromMilliseconds rounding!

Today’s fairly brutal gotcha:Ā TimeSpan.FromMilliseconds accepts a double but internally rounds the value to a long before converting to ticks (multiplying by 10000).

For example, using C# interactive in VS2017:

> TimeSpan.FromMilliseconds(1.5)
[00:00:00.0020000]

> TimeSpan.FromMilliseconds(1234.5678)
[00:00:01.2350000]

Using .FromTicks works as expected:


> TimeSpan.FromTicks(15000)
[00:00:00.0015000]

To be fair this is the documented behavior:

The value parameter is converted to ticks, and that number of ticks is used to initialize the new TimeSpan. Therefore, value will only be considered accurate to the nearest millisecond.

But really, it isn’tĀ expected since the input is a double!

This all came to light because a camera system I’m involved with started overexposing –Ā  the integration time was programmed as 2ms instead of the desired 1.5ms. Hmmph!

So a little alternative:

> TimeSpan TimeSpanFromMillisecondsEx(double ms) =>
    TimeSpan.FromTicks((long)(ms * 10000.0))

> TimeSpanFromMillisecondsEx(1.5)
[00:00:00.0015000]

 

Note: the FromMilliseconds method delegates to an internal Interval method, passing the milliseconds value and 1 as the scale:


private static TimeSpan Interval(double value, int scale)
{
    if (double.IsNaN(value))
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_CannotBeNaN"));
    }
    double num = value * scale;
    double num2 = num + ((value >= 0.0) ? 0.5 : -0.5);
    if ((num2 > 922337203685477) || (num2 = 0.0) ? 0.5 : -0.5);
    if ((num2 > 922337203685477) || (num2 < -922337203685477))
    {
        throw new OverflowException(Environment.GetResourceString("Overflow_TimeSpanTooLong"));
    }
    return new TimeSpan(((long) num2) * 0x2710L);
}

 

 

VS2017 and NuGet for C++/CLI

At the time of writing it still isn’t possible to use the NuGet package manager for C++/CLI projects. My workaround is to:

  1. Add a new C# class library project to the solution.
  2. Add any NuGet packages to this new project.
  3. Configure the C# project so it always builds in Release configuration.
  4. Use the Build Dependencies dialog to ensure that the new C# project is builtĀ beforeĀ the C++/CLI project.
  5. Add to the C++/CLI project a reference to the NuGet packages by using the output folder of the C# project.

Example

Create a new solution with a C++/CLI class library…

Add a C# class library (.Net Framework), delete Class1.cs, then go to the solution’s NuGet package manager:

2018-09-05 12_19_13-.png

Install the Newtonsoft.Json package for the C# project:2018-09-05 12_29_01-Solution3 - Microsoft Visual Studio.png

Change the C# build configuration so that the Release configuration builds for both DebugĀ and Release:2018-09-05 12_31_24-Configuration Manager.png

Then delete the unused Debug configuration:2018-09-05 12_31_42-Configuration Manager.png

2018-09-05 12_32_14-Configuration Manager.png

Make C++/CLI project dependent on the C# project:2018-09-05 12_34_09-Solution3 - Microsoft Visual Studio.png

(Note: I use the above for this dependency rather than adding a reference to the project to avoid copying the unused C# project to the C++/CLI’s output folders.)

Build the solution.

Add a reference to the Newtonsoft library by using the Browse option in the Add References dialog and locating the C# project’s bin/Release folder:

2018-09-05 12_38_57-Select the files to reference....png

Build the solution again. The Newtonsoft library will now be copied to the C++/CLI build folder:

2018-09-05 12_40_59-Debug.png

First test: add some code to the C++/CLI class to demonstrate basic JSON serialisation:

#pragma once

using namespace System;

namespace CppCliDemo {

	using namespace Newtonsoft::Json;

	public ref class Class1
	{
	private:

		String^ test = "I am the walrus";

	public:

		property String^ Test
		{
			String^ get() { return this->test; }
			void set(String^ value) { this->test = value; }
		}

		String^ SerialiseToJson()
		{
			auto json = JsonConvert::SerializeObject(this, Formatting::Indented);
			return json;
		}
	};
}

Then add a simple C# console app, reference just the C++/CLI project, and test the class:2018-09-05 12_50_22-Reference Manager - CSharpConsoleTest.png

static void Main(string[] args)
{
var test = new CppCliDemo.Class1();
var json = test.SerialiseToJson();
Console.Write(json);
}

 

The output – nicely formatted JSON šŸ™‚

2018-09-05 12_51_48-C__Users_Jon_Source_Repos_Solution3_CSharpConsoleTest_bin_Debug_CSharpConsoleTes.png

Second test, make sure a clean rebuild works as expected:

  1. Close the solution
  2. Manually delete all binaries and downloaded packages
  3. Re-open solution and build
  4. Verify that the build order is:
    1. CSharpNuGetHelper
    2. CppCliDemo
    3. CSharpConsoleTest (my console test demo app)
  5. Run the console app and verify the serialisation works as before

 

 

Associate VS2017 with JSON files

Double-clicking a JSON file to try and open it in Visual Studio 2017 Professional doesn’t work; VS2015 worked fine.Ā This link explains how to fix for the Community edition. The same principle applies for VS2017.

Using regedt32 first find the Visual Studio magic number:

Key:Ā Computer\HKEY_CLASSES_ROOT\.json\OpenWithProgids
Value:Ā VisualStudio.json.a8eb385c

2017-10-19 08_32_54-Registry Editor

 

Then find the associated shell key and create a new sub-key ‘Command’ with the path to devenv.exe as the default value:

Key: Computer\HKEY_CLASSES_ROOT\VisualStudio.json.a8eb385c\shell\Open\Command
Value:Ā "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE\devenv.exe"

2017-10-19 08_34_27-Registry Editor

 

Right-clicking a JSON file and selected Open with now looks like this:

2017-10-19 08_37_22-Sphere