BenchmarkDotNet icon indicating copy to clipboard operation
BenchmarkDotNet copied to clipboard

Add benchmarking progress to console title

Open Khaos66 opened this issue 3 years ago • 1 comments
trafficstars

Benchmarks run quite long to get accurate results. This time multiplies by params and benchmarks defined. It would be nice to have a progress indicator for the running benchmarking process.

As most benchmarks run in a console app, it is possible to use the consoles title bar as a place to display this progress.

At a minimum it should display: Running 5/10 Or maybe: Running: 5/10 - MyMethod(Param1,Param2) - ... configs like Framework,Runtime and such

What do you think?

Khaos66 avatar Sep 12 '22 06:09 Khaos66

I only just realized that there is this block in the output. image

So, why not display some of this information in the console title?

Khaos66 avatar Sep 12 '22 09:09 Khaos66

Sure, we can add that. My requirements:

  • the title needs to be short, so the most important information is always visible
  • it should never throw:
    • if some platforms don't support it, we should not call this property for them
    • same for the redirected output

adamsitnik avatar Oct 04 '22 18:10 adamsitnik

I will work on this issue!

franciscomoloureiro avatar Oct 04 '22 20:10 franciscomoloureiro

@franciscomoloureiro to check the current platform you can use helper methods exposed by RuntimeInformation class:

https://github.com/dotnet/BenchmarkDotNet/blob/a78c2e6a6e3db79069fb5bbbd6da6e5cbea8c029/src/BenchmarkDotNet/Portability/RuntimeInformation.cs#L80

The current progress logging happens here:

https://github.com/dotnet/BenchmarkDotNet/blob/8ec00dd53ff1ed6d8f9a8720857599474c8c36c1/src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs#L617

adamsitnik avatar Oct 05 '22 10:10 adamsitnik

Fixed by #2140

adamsitnik avatar Oct 12 '22 18:10 adamsitnik

As a followup, it might be nice to display the progress in the taskbar, but I only see the API available in .Net Framework. Not sure if there's an equivalent in .Net Core/Standard. https://learn.microsoft.com/en-us/dotnet/api/system.windows.shell.taskbariteminfo.progressvalue?view=windowsdesktop-7.0

[Edit] Looks like it can be done with a Nuget package https://www.nuget.org/packages/Microsoft-WindowsAPICodePack-Shell. I'm going to give it a shot.

[Edit2] #2158

timcassell avatar Oct 18 '22 01:10 timcassell

Funny. I did this in another project some time ago. You don't need another NuGet. Just some good old PInvoke ;)

public static class TaskbarProgress
    {
        public enum TaskbarStates
        {
            NoProgress = 0,
            Indeterminate = 0x1,
            Normal = 0x2,
            Error = 0x4,
            Paused = 0x8
        }

        [ComImportAttribute()]
        [GuidAttribute("ea1afb91-9e28-4b86-90e9-9e9f8a5eefaf")]
        [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
        private interface ITaskbarList3
        {
            // ITaskbarList
            [PreserveSig]
            void HrInit();
            [PreserveSig]
            void AddTab(IntPtr hwnd);
            [PreserveSig]
            void DeleteTab(IntPtr hwnd);
            [PreserveSig]
            void ActivateTab(IntPtr hwnd);
            [PreserveSig]
            void SetActiveAlt(IntPtr hwnd);

            // ITaskbarList2
            [PreserveSig]
            void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);

            // ITaskbarList3
            [PreserveSig]
            void SetProgressValue(IntPtr hwnd, UInt64 ullCompleted, UInt64 ullTotal);
            [PreserveSig]
            void SetProgressState(IntPtr hwnd, TaskbarStates state);
        }

        [GuidAttribute("56FDF344-FD6D-11d0-958A-006097C9A090")]
        [ClassInterfaceAttribute(ClassInterfaceType.None)]
        [ComImportAttribute()]
        private class TaskbarInstance
        {
        }

        private static ITaskbarList3 taskbarInstance = (ITaskbarList3)new TaskbarInstance();
        private static bool taskbarSupported = Environment.OSVersion.Version >= new Version(6, 1);

        public static void SetState(IntPtr windowHandle, TaskbarStates taskbarState)
        {
            if (taskbarSupported) taskbarInstance.SetProgressState(windowHandle, taskbarState);
        }

        public static void SetValue(IntPtr windowHandle, double progressValue, double progressMax)
        {
            if (taskbarSupported) taskbarInstance.SetProgressValue(windowHandle, (ulong)progressValue, (ulong)progressMax);
        }
    }

With this you can call SetState and SetValue easily. Have fun 🎉

Edit: This code is Windows only OC

Khaos66 avatar Oct 18 '22 11:10 Khaos66