Goal
Why this matters
Prerequisites
dotnet run -c Release). JIT optimizations affect responsiveness.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);
Avalonia.Logging.LogArea (Binding, Layout, Render, Property, Control, etc.).Warning) or limiting areas once you identify culprit.LogToTextWriter.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.
Use the target picker to select elements on screen and inspect descendants/ancestors.
TopLevel exposes IRenderer Diagnostics. Subscribe to PropertyChanged to stream overlay toggles or other diagnostics to logs, counters, or dashboards.renderer.Diagnostics.DebugOverlays from code or configuration.SceneInvalidated when you need per-frame insight into which rectangles triggered redraws. Pair this with your own timers to understand long layout/render passes.LogArea.Composition in logging when you need to correlate compositor operations (scene graph updates, render thread work) with on-screen symptoms.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}");
}
};
}
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:
Fps -- frames per second.DirtyRects -- regions redrawn each frame.LayoutTimeGraph -- layout duration per frame.RenderTimeGraph -- render duration per frame.Interpretation:
Avalonia.Remote.Protocol)Avalonia.Remote.Protocol (BSON/TCP by default).Avalonia.Controls.Remote.RemoteServer with a BsonTcpTransport to expose an interactive surface when debugging devices without a local inspector (mobile, kiosk). Connect using an Avalonia DevTools client (dotnet avalonia tool or IDE integration) pointing at tcp-bson://host:port.TransportMessages.cs describe the payloads (frame buffers, input, diagnostics). Extend them if you build custom tooling.RendererDebugOverlays locally will surface in the remote stream as well.TcpTransportBase in an authenticated tunnel (SSH port forward, reverse proxy) and disable remote servers in production builds.Lists & templates
VirtualizingStackPanel) for list controls.Layout & binding
LogArea.Binding). Debounce or use state flags.Rendering
RenderOptions.BitmapInterpolationMode for scaling to avoid blurry or overly expensive scaling.StreamGeometry), FormattedText, etc.Async & threading
Task.Run for CPU-bound tasks).IProgress<T> to report progress instead of manual UI thread dispatch.Profiling
.NET profilers (dotTrace, PerfView, dotnet-trace) to capture CPU/memory.RendererDebugOverlays.Fps | LayoutTimeGraph, and record metrics before/after enabling virtualization in a long list.LogArea.Binding to Debug, then fix the source and verify the log stream quiets down.RemoteServer with BsonTcpTransport, connect using an Avalonia DevTools client (dotnet avalonia tool or IDE integration), and confirm overlays/logging data mirror the local session.dotnet-trace and align CPU spikes with render diagnostics to validate the chosen fix.DevToolsExtensions.csMainViewModel.csRendererDiagnostics.csRendererDebugOverlays.csLogAreaRenderOptions.csLayoutHelperTransportMessages.csRemoteServer.csWhat's next