Skip to content
Nuvyntra Labs

Install

dotnet add package Plugin.Maui.Performance
dotnet tool install -g Plugin.Maui.Performance.Cli

Package ID: Plugin.Maui.Performance. Current NuGet is 1.0.7. The CLI tool is optional — install it only when you want maui-perf aliases over raw maui profile flags. Both PackageIds publish from the same repo CI.

Restore Plugin.Maui.* from GitHub Packages: Use nuvyntralabs GitHub Packages from a C# project

Register

using Plugin.Maui.Performance;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseMauiPerformance();

        return builder.Build();
    }
}

Registration starts automatic startup, page, navigation, image, and render measurement. On Android it also hooks OnResume; on iOS it hooks OnActivated.

Named traces and the report

using var trace = MauiPerformance.Trace("LoadCustomer");

await MauiPerformance.MeasureAsync("Customer API", () => client.GetStringAsync("/customer"), PerformanceCategory.Api);
MauiPerformance.Measure("SQLite Query", () => db.Query("SELECT * FROM customer"), PerformanceCategory.Database);

Console.WriteLine(MauiPerformance.FormatReport());

Automatic API tracking

builder.Services.AddHttpClient("shop", client =>
{
    client.BaseAddress = new Uri("https://api.shop");
}).AddHttpMessageHandler(() => new PerformanceDelegatingHandler());

Override the metric name per request. Query strings are stripped from stored URLs.

var request = new HttpRequestMessage(HttpMethod.Get, "/customer");
request.Options.Set(PerformanceHttp.NameKey, "Customer API");

Android HTTP tracking needs INTERNET and ACCESS_NETWORK_STATE. iOS needs no extra Info.plist keys.

Stop maui profile from the app

builder.UseMauiPerformance(options =>
{
    options.CliProfile.CompleteOn = CliProfileCompleteOn.FirstFrame;
    // options.CliProfile.CompleteOnScenario = "Checkout";
});

using var checkout = MauiProfile.Scenario("Checkout");
MauiProfile.Mark("CartReady");
// dispose / Complete() records a metric and can stop the CLI session

FirstFrame is the default. Use FirstPage for the App Startup moment, Manual to call StartupComplete() yourself, or CompleteOnScenario to wait for a named flow.

maui-perf at the command line

Install the companion tool, then use short aliases instead of the long official flags. startup always passes Microsoft.Maui.ProfilingHelper / StartupComplete so the trace ends when first frame (or your scenario) fires. screen wraps maui profile manual (press Enter to attach, Enter again to stop).

dotnet tool install -g Plugin.Maui.Performance.Cli

maui-perf startup -f android
maui-perf screen -f ios --speedscope --duration 30s
maui-perf command startup -f android

From a clone of this repo without installing the tool:

dotnet run --project src/Plugin.Maui.Performance.Cli -- startup -f android
OptionMeaning
-f android | iosFramework alias for net10.0-android / net10.0-ios.
--duration 30s | 2m | 1hParsed duration for screen / manual.
--speedscopeShortcut for --format speedscope (also nettrace, mibc).
--no-stop-markerDo not pass StartupComplete stopping events.
--dry-run / commandPrint the maui profile command without running it.

maui-perf is a shorter wrapper. Install the MAUI CLI so the maui command is on PATH. Official maui profile documentation

Options

builder.UseMauiPerformance(options =>
{
    options.AutoMeasureStartup = true;
    options.AutoMeasurePages = true;
    options.AutoMeasureNavigation = true;
    options.AutoMeasureImages = true;
    options.AutoMeasureRendering = true;
    options.SampleMemory = true;
    options.Enabled = true;
});

Without the generic host

var performance = MauiPerformance.Create(new MauiPerformanceOptions
{
    AutoMeasureStartup = true
});

performance.Start();

Compose with siblings

Performance does not reference Diagnostics, LeakAnalyser, or Observability. Wire them yourself when the host already uses those plugins. Treat a slow page as a metric, not a crash.

builder
    .UseMauiApp<App>()
    .UseMauiPerformance()
    .UseMauiDiagnostics();

MauiPerformance.Current.MetricRecorded += (_, e) =>
{
    if (e.Metric.Duration >= TimeSpan.FromSeconds(2))
        MauiDiagnostics.TrackEvent($"Slow:{e.Metric.Name}");
};

What not to wire

TemptationWhy not
This package as a leak detectorUse LeakAnalyser for WeakReference liveness after pop.
This package as crash / ANR captureUse Diagnostics.
Microsoft.Maui.ProfilingHelper package referencemaui profile injects the helper; MauiProfile calls Complete() for you.
maui-perf on Windows / Mac Catalystmaui profile supports Android and iOS simulator only.
A hosted APM just to print a scoreboardUse FormatReport() on device.
Package reference Performance → DiagnosticsKeeps the profiler usable without the telemetry suite.

Discussion

Comment on Plugin.Maui.Performance. The thread lives on this component's GitHub repository (nuvyntralabs/Plugin.Maui.Performance). Sign in with GitHub — Giscus uses Discussions, Utterances uses Issues.