Files
Terminal.Gui/Tests/Benchmarks/README.md
Copilot b43390a070 Fixes #4677 - Refactors DimAuto for less coupling and improves performance (#4678)
* Phase 5: Add IsFixed and RequiresTargetLayout categorization properties

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Further simplify DimAuto.Calculate using IsFixed property

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Refactor for-loops to foreach and clarify DimFill logic

Refactored multiple for-loops iterating over view lists to use foreach loops for improved readability and reduced boilerplate. Removed unused variables such as viewsNeedingLayout and index counters. Clarified DimFill handling by continuing early if the DimFill is not valid or lacks a To property, reducing nesting and improving intent. Made minor formatting and code style improvements for consistency.

* Refactor subview filtering and sizing logic

Refactored repeated LINQ queries for subview filtering into reusable helper methods (`GetViewsThatMatch`, `GetViewsThatHavePos<TPos>`, `GetViewsThatHaveDim<TDim>`), reducing duplication and improving readability. Moved max content size calculations for various subview types into new helper methods (`GetMaxSizePos<TPos>`, `GetMaxSizeDim<TDim>`). Updated main logic to use these helpers. Adornment thickness calculation now uses a switch expression. These changes improve modularity and maintainability.

* Refactor subview categorization for layout calculation

Refactored layout calculation to use a single-pass CategorizeSubViews method, grouping subviews by relevant Pos/Dim types into a new CategorizedViews struct. This replaces multiple helper methods and reduces redundant iterations. Updated main logic to use these categorized lists, and unified size calculation helpers to further reduce code duplication. Improves performance and maintainability by consolidating subview processing and removing obsolete methods.

* Revert perf POC commits and add missing overrides to Combine types

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Add helper methods and simplify DimAuto.Calculate with foreach loops

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Refactor layout calculation in DimAuto.cs

Removed commented-out code and unnecessary list declarations to clean up the layout calculation logic.

* removed old plan file

* Code cleanup

* Add performance analysis and improvement plan for DimAuto.Calculate

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Add DimAuto benchmarks and benchmark documentation

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Implement Phase 1 & 2 performance optimizations for DimAuto.Calculate

Co-authored-by: tig <585482+tig@users.noreply.github.com>

* Code cleanup

* Delete plans/dimauto-perf-plan.md

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: tig <585482+tig@users.noreply.github.com>
Co-authored-by: Tig <tig@users.noreply.github.com>
2026-02-06 12:33:47 -07:00

3.1 KiB

Terminal.Gui Benchmarks

This project contains performance benchmarks for Terminal.Gui using BenchmarkDotNet.

Running Benchmarks

Run All Benchmarks

cd Tests/Benchmarks
dotnet run -c Release

Run Specific Benchmark Category

# Run only DimAuto benchmarks
dotnet run -c Release -- --filter '*DimAuto*'

# Run only TextFormatter benchmarks
dotnet run -c Release -- --filter '*TextFormatter*'

Run Specific Benchmark Method

# Run only the ComplexLayout benchmark
dotnet run -c Release -- --filter '*DimAutoBenchmark.ComplexLayout*'

Quick Run (Shorter but Less Accurate)

For faster iteration during development:

dotnet run -c Release -- --filter '*DimAuto*' -j short

List Available Benchmarks

dotnet run -c Release -- --list flat

DimAuto Benchmarks

The DimAutoBenchmark class tests layout performance with Dim.Auto() in various scenarios:

  • SimpleLayout: Baseline with 3 subviews using basic positioning
  • ComplexLayout: 20 subviews with mixed Pos/Dim types (tests iteration overhead)
  • DeeplyNestedLayout: 5 levels of nested views with DimAuto (tests recursive performance)

Example Output

BenchmarkDotNet v0.14.0, Windows 11 (10.0.22631.4602/23H2/2023Update/SunValley3)
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK 10.0.102
  [Host]     : .NET 10.0.1 (10.0.125.52708), X64 RyuJIT AVX2
  DefaultJob : .NET 10.0.1 (10.0.125.52708), X64 RyuJIT AVX2

| Method              | Mean       | Error     | StdDev    | Ratio | RatioSD | Gen0   | Allocated | Alloc Ratio |
|-------------------- |-----------:|----------:|----------:|------:|--------:|-------:|----------:|------------:|
| SimpleLayout        |   5.234 μs | 0.0421 μs | 0.0394 μs |  1.00 |    0.01 | 0.3586 |   3.03 KB |        1.00 |
| ComplexLayout       |  42.561 μs | 0.8234 μs | 0.7701 μs |  8.13 |    0.17 | 2.8076 |  23.45 KB |        7.74 |
| DeeplyNestedLayout  |  25.123 μs | 0.4892 μs | 0.4577 μs |  4.80 |    0.10 | 1.7090 |  14.28 KB |        4.71 |

Adding New Benchmarks

  1. Create a new class in an appropriate subdirectory (e.g., Layout/, Text/)
  2. Add the [MemoryDiagnoser] attribute to measure allocations
  3. Add [BenchmarkCategory("CategoryName")] to group related benchmarks
  4. Mark baseline scenarios with [Benchmark(Baseline = true)]
  5. Use [GlobalSetup] and [GlobalCleanup] for initialization/cleanup

Best Practices

  • Always run benchmarks in Release configuration
  • Run multiple iterations for accurate results (default is better than -j short)
  • Use [ArgumentsSource] for parametrized benchmarks
  • Include baseline scenarios for comparison
  • Document what each benchmark measures

Continuous Integration

Benchmarks are not run automatically in CI. Run them locally when:

  • Making performance-critical changes
  • Implementing performance optimizations
  • Before releasing a new version

Resources