Skip to content
19 changes: 19 additions & 0 deletions eng/performance/maui_desktop_benchmarks.proj
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.DotNet.Helix.Sdk" DefaultTargets="Test">

<Import Project="Scenarios.Common.props" />

<!-- MAUI Desktop BenchmarkDotNet benchmarks
Clones dotnet/maui, builds dependencies, patches in PerfLabExporter,
and runs the Core, XAML, and Graphics BDN benchmark suites. -->

<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<HelixWorkItem Include="MAUI Desktop BDN Benchmarks">
<PayloadDirectory>$(ScenariosDir)mauiDesktopBenchmarks</PayloadDirectory>
<PreCommands>$(Python) pre.py -f $(PERFLAB_Framework)</PreCommands>
<Command>$(Python) test.py --framework $(PERFLAB_Framework) --suite all</Command>
<PostCommands>$(Python) post.py</PostCommands>
</HelixWorkItem>
</ItemGroup>

<Import Project="PreparePayloadWorkItems.targets" />
</Project>
32 changes: 32 additions & 0 deletions eng/pipelines/sdk-perf-jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,22 @@ jobs:
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# MAUI Desktop BenchmarkDotNet benchmarks
- ${{ if false }}:
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
buildMachines:
- win-x64
isPublic: true
jobParameters:
runKind: maui_desktop_benchmarks
projectFileName: maui_desktop_benchmarks.proj
channels:
- main
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# Blazor scenario benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
Expand Down Expand Up @@ -586,6 +602,22 @@ jobs:
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# MAUI Desktop BDN benchmarks (private)
- ${{ if false }}:
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
buildMachines:
- win-x64-viper
isPublic: false
jobParameters:
runKind: maui_desktop_benchmarks
projectFileName: maui_desktop_benchmarks.proj
channels:
- main
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# NativeAOT scenario benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
Expand Down
30 changes: 30 additions & 0 deletions src/scenarios/mauiDesktopBenchmarks/post.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'''
Post-commands for MAUI Desktop BenchmarkDotNet benchmarks.
Cleans up the cloned maui repo and temporary artifacts.
'''
import os
import shutil
from performance.logger import setup_loggers, getLogger

setup_loggers(True)
log = getLogger(__name__)

MAUI_REPO_DIR = 'maui_repo'


def cleanup():
"""Remove the cloned maui repository and any leftover artifacts."""
if os.path.exists(MAUI_REPO_DIR):
log.info(f'Removing cloned MAUI repo: {MAUI_REPO_DIR}')
shutil.rmtree(MAUI_REPO_DIR, ignore_errors=True)

# Clean up combined report if still in working directory
combined = 'combined-perf-lab-report.json'
if os.path.exists(combined):
os.remove(combined)

log.info('Post-commands cleanup complete.')


if __name__ == '__main__':
cleanup()
19 changes: 19 additions & 0 deletions src/scenarios/mauiDesktopBenchmarks/pre.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
'''
Pre-commands for MAUI Desktop BenchmarkDotNet benchmarks.
Kept minimal — all heavy lifting (clone, build, patch, run) is in test.py
to keep the correlation payload small.
'''
import argparse
from performance.logger import setup_loggers, getLogger

setup_loggers(True)
log = getLogger(__name__)

if __name__ == '__main__':
parser = argparse.ArgumentParser(description='MAUI Desktop BDN Benchmarks - Pre-commands')
parser.add_argument('-f', '--framework', default='net11.0',
help='Target .NET framework (determines MAUI branch)')
args = parser.parse_args()
log.info(f'MAUI Desktop BDN Benchmarks pre-commands (framework={args.framework})')
log.info('Setup deferred to test.py to minimize correlation payload.')

135 changes: 135 additions & 0 deletions src/scenarios/mauiDesktopBenchmarks/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
'''
MAUI Desktop BenchmarkDotNet benchmarks.

Handles MAUI-specific setup (clone, branch mapping, dependency build) then
delegates to the shared BDNDesktopHelper for the generic BDN workflow
(patch, build benchmarks, run, collect results).

Usage: test.py --framework net11.0 --suite all
'''
import os
import shutil
import subprocess
from argparse import ArgumentParser
from logging import getLogger
from performance.logger import setup_loggers
from shared.bdndesktop import BDNDesktopHelper

# ── MAUI-specific configuration ─────────────────────────────────────────────

MAUI_REPO_URL = 'https://github.com/dotnet/maui.git'
MAUI_REPO_DIR = 'maui_repo'

MAUI_BENCHMARK_PROJECTS = {
'core': 'src/Core/tests/Benchmarks/Core.Benchmarks.csproj',
'xaml': 'src/Controls/tests/Xaml.Benchmarks/Microsoft.Maui.Controls.Xaml.Benchmarks.csproj',
'graphics': 'src/Graphics/tests/Graphics.Benchmarks/Graphics.Benchmarks.csproj',
}

MAUI_SPARSE_CHECKOUT_DIRS = [
'src/Core', 'src/Controls', 'src/Graphics', 'src/SingleProject',
'src/Workload', 'src/Essentials',
'eng', '.config',
]

MAUI_BUILD_SOLUTION_FILTER = 'Microsoft.Maui.BuildTasks.slnf'

# MSBuild properties to disable non-desktop target frameworks.
# MAUI's Directory.Build.props sets these to true unconditionally at multiple
# points; MauiPlatforms is computed from them. In-place replacement is
# required because appending overrides at the end doesn't work (MSBuild
# evaluates top-to-bottom).
DESKTOP_ONLY_PROPS = {
'IncludeAndroidTargetFrameworks': 'false',
'IncludeIosTargetFrameworks': 'false',
'IncludeMacCatalystTargetFrameworks': 'false',
'IncludeMacOSTargetFrameworks': 'false',
'IncludeTizenTargetFrameworks': 'false',
}


def get_branch(framework: str) -> str:
'''Map framework moniker to MAUI repo branch.'''
if framework and framework.startswith('net'):
return framework # net11.0 -> net11.0, net10.0 -> net10.0
return 'net11.0'


def clone_maui_repo(branch: str, repo_dir: str = MAUI_REPO_DIR):
'''Sparse-clone dotnet/maui at the given branch.'''
log = getLogger()
log.info(f'Cloning dotnet/maui branch {branch} (sparse, depth 1)...')

if os.path.exists(repo_dir):
shutil.rmtree(repo_dir)

subprocess.run([
'git', 'clone',
'-c', 'core.longpaths=true',
'--depth', '1',
'--filter=blob:none',
'--sparse',
'--branch', branch,
MAUI_REPO_URL,
repo_dir
], check=True)

subprocess.run(
['git', 'sparse-checkout', 'set'] + MAUI_SPARSE_CHECKOUT_DIRS,
cwd=repo_dir, check=True)

log.info('Clone complete.')


def build_maui_dependencies(repo_dir: str = MAUI_REPO_DIR):
'''Restore dotnet tools and build MAUI's BuildTasks solution filter.'''
log = getLogger()
log.info('Restoring dotnet tools...')
subprocess.run(['dotnet', 'tool', 'restore'], cwd=repo_dir, check=True)

log.info(f'Building {MAUI_BUILD_SOLUTION_FILTER} (desktop TFMs only)...')
subprocess.run([
'dotnet', 'build',
MAUI_BUILD_SOLUTION_FILTER,
'-c', 'Release',
], cwd=repo_dir, check=True)

log.info('MAUI dependencies built successfully.')


def parse_args():
parser = ArgumentParser(description='Run MAUI desktop BDN benchmarks')
parser.add_argument('--framework', '-f', default='net11.0',
help='Target .NET framework (determines MAUI repo branch)')
parser.add_argument('--suite', choices=['core', 'xaml', 'graphics', 'all'],
default='all', help='Which benchmark suite to run')
parser.add_argument('--bdn-args', nargs='*', default=[],
help='Additional arguments to pass to BenchmarkDotNet')
parser.add_argument('--upload-to-perflab-container', action='store_true',
help='Upload results to perflab container')
return parser.parse_args()


if __name__ == '__main__':
setup_loggers(True)
args = parse_args()

# MAUI-specific: clone repo and build dependencies
branch = get_branch(args.framework)
clone_maui_repo(branch)

# Generic BDN desktop workflow: patch, build benchmarks, run, collect
helper = BDNDesktopHelper(
repo_dir=MAUI_REPO_DIR,
benchmark_projects=MAUI_BENCHMARK_PROJECTS,
disable_props=DESKTOP_ONLY_PROPS,
)

# Patch Directory.Build.props BEFORE any builds (including MAUI deps)
helper.patch_directory_build_props()

# MAUI-specific: build BuildTasks solution filter
build_maui_dependencies()

# Run the generic BDN workflow
helper.runtests(args.suite, args.bdn_args, args.upload_to_perflab_container)
Loading
Loading