24. Performance, diagnostics, and DevTools

Goal

Why this matters

Prerequisites

1. Measure before changing anything

2. Logging

Enable logging per area using AppBuilder extensions (see LoggingExtensions.cs).

AppBuilder.Configure<App>()
    .UsePlatformDetect()
    .LogToTrace(LogEventLevel.Information, new[] { LogArea.Binding, LogArea.Layout, LogArea.Render, LogArea.Property })
    .StartWithClassicDesktopLifetime(args);

3. DevTools (F12)

Attach DevTools after app initialization:

public override void OnFrameworkInitializationCompleted()
{
    // configure windows/root view
    this.AttachDevTools();
    base.OnFrameworkInitializationCompleted();
}

Supports options: AttachDevTools(new DevToolsOptions { StartupScreenIndex = 1 }) for multi-monitor setups.

DevTools tour

Use the target picker to select elements on screen and inspect descendants/ancestors.

4. Renderer diagnostics API

using System.Diagnostics;

if (TopLevel is { Renderer: { } renderer })
{
    renderer.SceneInvalidated += (_, e) =>
    {
        Debug.WriteLine($"Invalidated {e.Rect}");
    };

    renderer.Diagnostics.PropertyChanged += (_, e) =>
    {
        if (e.PropertyName == nameof(RendererDiagnostics.DebugOverlays))
        {
            Debug.WriteLine($"Overlays now: {renderer.Diagnostics.DebugOverlays}");
        }
    };
}

5. Debug overlays (RendererDebugOverlays)

Access via DevTools "Diagnostics" pane or programmatically:

if (this.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
    desktop.MainWindow.AttachedToVisualTree += (_, __) =>
    {
        if (desktop.MainWindow?.Renderer is { } renderer)
            renderer.DebugOverlays = RendererDebugOverlays.Fps | RendererDebugOverlays.DirtyRects;
    };
}

Overlays include:

Interpretation:

6. Remote diagnostics (Avalonia.Remote.Protocol)

7. Performance checklist

Lists & templates

Layout & binding

Rendering

Async & threading

Profiling

8. Considerations per platform

9. Automation & CI

10. Workflow summary

  1. Reproduce in Release with logging disabled -> measure baseline.
  2. Enable DevTools overlays (FPS, dirty rects, layout/render graphs) -> identify pattern.
  3. Enable targeted logging (Binding/Layout/Render) -> correlate with overlays.
  4. Apply fix (virtualization, caching, reducing layout churn)
  5. Re-measure with overlays/logs to confirm improvements.
  6. Capture notes and, if beneficial, automate tests for future regressions.

11. Practice exercises

  1. Attach DevTools, toggle RendererDebugOverlays.Fps | LayoutTimeGraph, and record metrics before/after enabling virtualization in a long list.
  2. Capture binding noise by raising LogArea.Binding to Debug, then fix the source and verify the log stream quiets down.
  3. Spin up a RemoteServer with BsonTcpTransport, connect using an Avalonia DevTools client (dotnet avalonia tool or IDE integration), and confirm overlays/logging data mirror the local session.
  4. Profile the same interaction with dotnet-trace and align CPU spikes with render diagnostics to validate the chosen fix.

Look under the hood (source bookmarks)

Check yourself

What's next