BenchmarkDotNet
BenchmarkDotNet copied to clipboard
Add benchmarking progress to console title
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?
I only just realized that there is this block in the output.

So, why not display some of this information in the console title?
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
I will work on this issue!
@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
Fixed by #2140
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
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