Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Refactored ConsoleTitler (#2237)
  • Loading branch information
albahari committed Jan 3, 2023
commit f888bc06fa595c3e3f6bf791e698f6c17ebce99c
15 changes: 4 additions & 11 deletions src/BenchmarkDotNet/Running/BenchmarkRunnerClean.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
Expand Down Expand Up @@ -167,15 +167,13 @@ private static Summary Run(BenchmarkRunInfo benchmarkRunInfo,
var cultureInfo = config.CultureInfo ?? DefaultCultureInfo.Instance;
var reports = new List<BenchmarkReport>();
string title = GetTitle(new[] { benchmarkRunInfo });
using var consoleTitler = new ConsoleTitler("");
using var consoleTitler = new ConsoleTitler($"{benchmarksToRunCount}/{totalBenchmarkCount} Remaining");

logger.WriteLineInfo($"// Found {benchmarks.Length} benchmarks:");
foreach (var benchmark in benchmarks)
logger.WriteLineInfo($"// {benchmark.DisplayInfo}");
logger.WriteLine();

UpdateTitle(totalBenchmarkCount, benchmarksToRunCount, consoleTitler);

using (var powerManagementApplier = new PowerManagementApplier(logger))
{
bool stop = false;
Expand Down Expand Up @@ -646,11 +644,6 @@ private static void Cleanup(HashSet<string> artifactsToCleanup)
}
}

private static void UpdateTitle(int totalBenchmarkCount, int benchmarksToRunCount, ConsoleTitler consoleTitler)
{
consoleTitler.UpdateTitle(() => $"{benchmarksToRunCount}/{totalBenchmarkCount} Remaining");
}

private static void LogProgress(ILogger logger, in StartedClock runsChronometer, int totalBenchmarkCount, int benchmarksToRunCount, ConsoleTitler consoleTitler, TaskbarProgress taskbarProgress)
{
int executedBenchmarkCount = totalBenchmarkCount - benchmarksToRunCount;
Expand All @@ -660,7 +653,7 @@ private static void LogProgress(ILogger logger, in StartedClock runsChronometer,
$" Estimated finish {estimatedEnd:yyyy-MM-dd H:mm} ({(int)fromNow.TotalHours}h {fromNow.Minutes}m from now) **";
logger.WriteLineHeader(message);

consoleTitler.UpdateTitle (() => $"{benchmarksToRunCount}/{totalBenchmarkCount} Remaining - {(int)fromNow.TotalHours}h {fromNow.Minutes}m to finish");
consoleTitler.UpdateTitle ($"{benchmarksToRunCount}/{totalBenchmarkCount} Remaining - {(int)fromNow.TotalHours}h {fromNow.Minutes}m to finish");

taskbarProgress.SetProgress((float) executedBenchmarkCount / totalBenchmarkCount);
}
Expand Down Expand Up @@ -717,4 +710,4 @@ private static int GetIdToResume(string rootArtifactsFolderPath, string currentL
return -1;
}
}
}
}
47 changes: 20 additions & 27 deletions src/BenchmarkDotNet/Running/ConsoleTitler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,37 @@ internal class ConsoleTitler : IDisposable

private string oldConsoleTitle;

/// <summary>
/// Constructs a ConsoleTitler
/// </summary>
/// <param name="fallbackTitle">What to restore Console.Title to upon disposal (for platforms with write-only Console.Title)</param>
public ConsoleTitler(string fallbackTitle)
public ConsoleTitler(string initialTitle)
{
// Return without enabling if Console output is redirected, or if we're not on a platform that supports Console retitling.
if (Console.IsOutputRedirected || !PlatformSupportsTitleWrite())
// Return without enabling if Console output is redirected.
if (Console.IsOutputRedirected)
{
return;
}

try
{
oldConsoleTitle = PlatformSupportsTitleRead() ? Console.Title : fallbackTitle;
IsEnabled = true;
oldConsoleTitle = PlatformSupportsTitleRead() ? Console.Title : "";
}
catch (IOException)
{
// We're unable to read Console.Title on a platform that supports it. This can happen when no console
// window is available due to the application being Windows Forms, WPF, Windows Service or a daemon.
// Because we won't be able to write Console.Title either, return without enabling the titler.
oldConsoleTitle = "";
}

try
{
// Enable ConsoleTitler if and only if we can successfully set the Console.Title property.
Console.Title = initialTitle;
IsEnabled = true;
}
catch (IOException)
{
}
catch (PlatformNotSupportedException)
{
// As of .NET 7, platforms other than Windows, Linux and MacOS do not support Console retitling.
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Write the passed in title here. This is where you need the flag to check in UpdateTitle if it is writable. The flag you have now only checks if it's readable.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need a separate try/catch for the write instead of a platform check. We'd want to catch IOException and PlatformNotSupportedException. Let other exceptions propagate.

try
{
   Console.Title = title;
   IsEnabled = true;
}
catch (IOException) { }
catch (PlatformNotSupportedException) { }

}

Expand All @@ -48,11 +57,6 @@ public ConsoleTitler(string fallbackTitle)
#endif
private static bool PlatformSupportsTitleRead() => RuntimeInformation.IsWindows();

private static bool PlatformSupportsTitleWrite() =>
RuntimeInformation.IsWindows() ||
RuntimeInformation.IsLinux() ||
RuntimeInformation.IsMacOS();

/// <summary>
/// Updates Console.Title if enabled.
/// </summary>
Expand All @@ -64,20 +68,9 @@ public void UpdateTitle(string title)
}
}

/// <summary>
/// Updates Console.Title if enabled, using a Func to avoid potential string-building cost.
/// </summary>
public void UpdateTitle(Func<string> title)
{
if (IsEnabled)
{
Console.Title = title();
}
}

public void Dispose()
{
if (IsEnabled && oldConsoleTitle != null)
if (IsEnabled)
{
Console.Title = oldConsoleTitle;
IsEnabled = false;
Expand Down