[.NET 10] Add layout performance logging#30130
Conversation
There was a problem hiding this comment.
Pull Request Overview
This PR adds an initial performance monitoring system to .NET MAUI, specifically focusing on layout performance metrics. It introduces a comprehensive profiling infrastructure that tracks measure and arrange pass durations using the System.Diagnostics.Metrics API, allowing developers to monitor layout performance in real-time.
Key changes include:
- Introduction of a new PerformanceProfiler system with layout tracking capabilities
- Integration of performance tracking directly into VisualElement's measure and arrange operations
- Addition of metrics support controlled by runtime feature switches
Reviewed Changes
Copilot reviewed 47 out of 48 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Core/src/PerformanceProfiler/* | New performance profiling infrastructure including tracker interfaces, models, and extension methods |
| src/Core/src/RuntimeFeature.cs | Added IsMetricsSupported feature switch with default true value |
| src/Core/src/Hosting/MauiAppBuilder.cs | Integrated performance configuration into default MAUI app setup |
| src/Controls/src/Core/VisualElement/VisualElement.cs | Added performance tracking to measure and arrange operations |
| src/Core/tests/UnitTests/PerformanceProfilerTests.cs | Comprehensive unit tests for the performance profiling system |
| src/Controls/tests/TestCases.HostApp/Issues/* | Test UI pages demonstrating performance profiling features |
| src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/* | UI test automation for performance profiling validation |
| src/Compatibility/Core/src//.cs | Updated existing Performance references to use Internals.Performance namespace |
| docs/design/FeatureSwitches.md | Documentation for the new MetricsSupport feature switch |
Comments suppressed due to low confidence (1)
| builder.Services.AddSingleton<ILayoutPerformanceTracker, LayoutPerformanceTracker>(); | ||
|
|
||
| // Initialize the PerformanceProfiler | ||
| using (var serviceProvider = builder.Services.BuildServiceProvider()) |
There was a problem hiding this comment.
Building a service provider during configuration can be expensive and is generally discouraged. Consider registering the initialization as a hosted service or using a factory pattern instead of building the service provider here.
There was a problem hiding this comment.
Is this the only way to get it ? I wonder if it bring side effects if theres a lot of things registered, like user viewModels etc.. DO we have an internal service provider? I remember we had one in the past for our internal stuff.
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28091SubscribeToUpdates.cs
Outdated
Show resolved
Hide resolved
src/Controls/tests/TestCases.Shared.Tests/Tests/Issues/Issue28091GetHistory.cs
Outdated
Show resolved
Hide resolved
rmarinho
left a comment
There was a problem hiding this comment.
Some comments, and it seems is leaking elements as some device tests are failing,
| builder.Services.AddSingleton<ILayoutPerformanceTracker, LayoutPerformanceTracker>(); | ||
|
|
||
| // Initialize the PerformanceProfiler | ||
| using (var serviceProvider = builder.Services.BuildServiceProvider()) |
There was a problem hiding this comment.
Is this the only way to get it ? I wonder if it bring side effects if theres a lot of things registered, like user viewModels etc.. DO we have an internal service provider? I remember we had one in the past for our internal stuff.
src/Core/src/PerformanceProfiler/Models/MauiPerformanceMeter.cs
Outdated
Show resolved
Hide resolved
| _measureDurationHistogram = mauiPerformanceMeter.Meter.CreateHistogram<double>( | ||
| "maui.layout.measure.duration", | ||
| unit: "ms", | ||
| description: "Duration of layout measure passes"); |
There was a problem hiding this comment.
This should be using Resources so it can be localized for the developer no?
| break; | ||
|
|
||
| default: | ||
| Debug.WriteLine($"[Performance Profiler] {_category} took {elapsed:0.00} ms."); |
There was a problem hiding this comment.
Should we use the logger here ?
| /// </summary> | ||
| /// <param name="duration">The duration of the arrange pass in milliseconds.</param> | ||
| /// <param name="element">The element being arranged, or null if not specified.</param> | ||
| public void RecordArrangePass(double duration, object? element = null) |
There was a problem hiding this comment.
IN what case can element be null here?
| builder.Services.AddSingleton<MauiPerformanceMeter>(); | ||
|
|
||
| // Register core services | ||
| builder.Services.AddSingleton<ILayoutPerformanceTracker, LayoutPerformanceTracker>(); |
There was a problem hiding this comment.
Can we use the factory method here, so when is created we can Initialize ?
builder.Services.AddSingleton<ILayoutPerformanceTracker>( () =>
{
var tracker = LayoutPerformanceTracker>();
PerformanceProfiler.Initialize(tracker);
return tracker;
});
Description of Change
This PR includes changes to add an initial and basic performance monitoring system for the .NET MAUI framework, focusing on performance layout metrics. The system is integrated directly into the MAUI framework, instruments from the System.Diagnostics.Metrics API.
Based on #29972