Add benchmarks for rendering

This commit is contained in:
Patrik Svensson
2026-01-20 18:03:49 +01:00
committed by Patrik Svensson
parent 86abe0cc12
commit 0a692bc743
7 changed files with 145 additions and 0 deletions

4
.gitignore vendored
View File

@@ -17,6 +17,10 @@
dotnet-install.sh* dotnet-install.sh*
*.lock.json *.lock.json
# Benchmarks
**/BenchmarkDotNet.Artifacts/**/*.*
!**/BenchmarkDotNet.Artifacts/**/*.md
# Visual Studio # Visual Studio
.vs/ .vs/
.vscode/ .vscode/

View File

@@ -0,0 +1,17 @@
```
BenchmarkDotNet v0.15.8, macOS Tahoe 26.2 (25C56) [Darwin 25.2.0]
Apple M3 Pro, 1 CPU, 11 logical and 11 physical cores
.NET SDK 10.0.101
[Host] : .NET 10.0.1 (10.0.1, 10.0.125.57005), Arm64 RyuJIT armv8.0-a
.NET 10.0 : .NET 10.0.1 (10.0.1, 10.0.125.57005), Arm64 RyuJIT armv8.0-a
.NET 8.0 : .NET 8.0.17 (8.0.17, 8.0.1725.26602), Arm64 RyuJIT armv8.0-a
.NET 9.0 : .NET 9.0.10 (9.0.10, 9.0.1025.47515), Arm64 RyuJIT armv8.0-a
```
| Method | Job | Runtime | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|----------------- |---------- |---------- |---------:|---------:|---------:|-------:|-------:|----------:|
| RenderableToAnsi | .NET 10.0 | .NET 10.0 | 12.33 μs | 0.054 μs | 0.045 μs | 5.3558 | 0.1831 | 43.87 KB |
| RenderableToAnsi | .NET 8.0 | .NET 8.0 | 14.12 μs | 0.100 μs | 0.094 μs | 5.7068 | 0.1831 | 46.73 KB |
| RenderableToAnsi | .NET 9.0 | .NET 9.0 | 14.12 μs | 0.052 μs | 0.049 μs | 5.6458 | 0.1984 | 46.17 KB |

View File

@@ -0,0 +1,17 @@
```
BenchmarkDotNet v0.15.8, macOS Tahoe 26.2 (25C56) [Darwin 25.2.0]
Apple M3 Pro, 1 CPU, 11 logical and 11 physical cores
.NET SDK 10.0.101
[Host] : .NET 10.0.1 (10.0.1, 10.0.125.57005), Arm64 RyuJIT armv8.0-a
.NET 10.0 : .NET 10.0.1 (10.0.1, 10.0.125.57005), Arm64 RyuJIT armv8.0-a
.NET 8.0 : .NET 8.0.17 (8.0.17, 8.0.1725.26602), Arm64 RyuJIT armv8.0-a
.NET 9.0 : .NET 9.0.10 (9.0.10, 9.0.1025.47515), Arm64 RyuJIT armv8.0-a
```
| Method | Job | Runtime | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|------- |---------- |---------- |---------:|---------:|---------:|-------:|-------:|----------:|
| Render | .NET 10.0 | .NET 10.0 | 12.45 μs | 0.130 μs | 0.101 μs | 5.4169 | 0.0916 | 44.34 KB |
| Render | .NET 8.0 | .NET 8.0 | 21.74 μs | 0.033 μs | 0.031 μs | 5.7678 | 0.0916 | 47.2 KB |
| Render | .NET 9.0 | .NET 9.0 | 14.37 μs | 0.070 μs | 0.065 μs | 5.7068 | 0.0916 | 46.64 KB |

View File

@@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net10.0;net9.0;net8.0</TargetFrameworks>
<IsPackable>true</IsPackable>
<IsAotCompatible>true</IsAotCompatible>
<IsPackable>false</IsPackable>
<ImplicitUsings>true</ImplicitUsings>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

84
src/Benchmarks/Program.cs Normal file
View File

@@ -0,0 +1,84 @@
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using Spectre.Console;
using Spectre.Console.Rendering;
namespace Benchmarks;
public static class Program
{
public static int Main(string[] args)
{
BenchmarkRunner.Run(typeof(Program).Assembly);
return 0;
}
}
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net80)]
[SimpleJob(RuntimeMoniker.Net90)]
[SimpleJob(RuntimeMoniker.Net10_0)]
public class RenderBenchmarks
{
private IAnsiConsole _console = null!;
private IRenderable _renderable = null!;
[GlobalSetup]
public void Setup()
{
_console =
AnsiConsole.Create(new AnsiConsoleSettings
{
Ansi = AnsiSupport.Detect,
ColorSystem = ColorSystemSupport.TrueColor,
Out = new AnsiConsoleOutput(new StringWriter()),
Interactive = InteractionSupport.No,
EnvironmentVariables = null
});
_renderable = new Table()
.AddColumns("Foo", "Bar")
.AddRow(new Text("1"), new Table()
.AddColumns("Baz", "Qux")
.AddRow("1", "2")
.AddRow("3", "4"));
}
[Benchmark]
public void Render() => _console.Write(_renderable);
}
[MemoryDiagnoser]
[SimpleJob(RuntimeMoniker.Net80)]
[SimpleJob(RuntimeMoniker.Net90)]
[SimpleJob(RuntimeMoniker.Net10_0)]
public class AnsiBenchmarks
{
private IAnsiConsole _console = null!;
private IRenderable _renderable = null!;
[GlobalSetup]
public void Setup()
{
_console =
AnsiConsole.Create(new AnsiConsoleSettings
{
Ansi = AnsiSupport.Detect,
ColorSystem = ColorSystemSupport.TrueColor,
Out = new AnsiConsoleOutput(new StringWriter()),
Interactive = InteractionSupport.No,
EnvironmentVariables = null
});
_renderable = new Table()
.AddColumns("Foo", "Bar")
.AddRow(new Text("1"), new Table()
.AddColumns("Baz", "Qux")
.AddRow("1", "2")
.AddRow("3", "4"));
}
[Benchmark]
public void RenderableToAnsi() => _console.ToAnsi(_renderable);
}

View File

@@ -3,6 +3,7 @@
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageVersion Include="BenchmarkDotNet" Version="0.15.8" />
<PackageVersion Include="IsExternalInit" Version="1.0.3" /> <PackageVersion Include="IsExternalInit" Version="1.0.3" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" /> <PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="8.0.0" /> <PackageVersion Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="8.0.0" />

View File

@@ -19,6 +19,7 @@
<Project Path="Extensions/Spectre.Console.ImageSharp/Spectre.Console.ImageSharp.csproj" /> <Project Path="Extensions/Spectre.Console.ImageSharp/Spectre.Console.ImageSharp.csproj" />
<Project Path="Extensions/Spectre.Console.Json/Spectre.Console.Json.csproj" /> <Project Path="Extensions/Spectre.Console.Json/Spectre.Console.Json.csproj" />
</Folder> </Folder>
<Project Path="Benchmarks/Benchmarks.csproj" />
<Project Path="Spectre.Console.SourceGenerator/Spectre.Console.SourceGenerator.csproj" /> <Project Path="Spectre.Console.SourceGenerator/Spectre.Console.SourceGenerator.csproj" />
<Project Path="Spectre.Console.Testing/Spectre.Console.Testing.csproj" /> <Project Path="Spectre.Console.Testing/Spectre.Console.Testing.csproj" />
<Project Path="Spectre.Console.Tests/Spectre.Console.Tests.csproj" /> <Project Path="Spectre.Console.Tests/Spectre.Console.Tests.csproj" />