Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/benchmarking-workflow-dotnet-runtime.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ recorded in that SDK's `Microsoft.NETCoreSdk.BundledVersions.props`.
`PERFLAB_WASM_PACKAGE_VERSION` should remain unset; that override is reserved
for non-official runtime payloads.

`--wasm-ready-to-run` publishes per-assembly ReadyToRun images. Replace it with
`--wasm-ready-to-run-composite` to compile the benchmark closure into a single
composite image (`PublishReadyToRunComposite=true`, published as
`<entry>.r2r.wasm` and loaded through the boot config's `coreAssembly`
resources). Composite mode requires a WebAssembly SDK with composite support
(dotnet/runtime#134618) and ReadyToRun SDK tasks with wasm output naming
(dotnet/sdk#56395). CI reports the two modes as `R2RType=r2r` and
`R2RType=r2r_composite`.

#### Note about "file ... being used by another process" error

If you are seeing warnings like:
Expand Down
29 changes: 27 additions & 2 deletions eng/pipelines/runtime-wasm-perf-jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ jobs:
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# Run CoreCLR WASM R2R microbenchmarks using the same runtime payload.
# Browser WASM supports per-assembly R2R rather than composite R2R.
# Run CoreCLR WASM per-assembly R2R microbenchmarks using the same runtime payload.
- ${{ if not(startswith(variables['Build.SourceBranch'], 'refs/heads/release')) }}:
- template: /eng/pipelines/common/platform-matrix.yml@${{ parameters.runtimeRepoAlias }}
parameters:
Expand All @@ -179,3 +178,29 @@ jobs:
performanceRepoAlias: ${{ parameters.performanceRepoAlias }}
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# Run CoreCLR WASM composite R2R microbenchmarks using the same runtime payload.
# The whole benchmark closure is compiled into one <entry>.r2r.wasm image (PublishReadyToRunComposite=true)
# and reported as R2RType=r2r_composite, a history separate from per-assembly R2RType=r2r.
- ${{ if not(startswith(variables['Build.SourceBranch'], 'refs/heads/release')) }}:
- template: /eng/pipelines/common/platform-matrix.yml@${{ parameters.runtimeRepoAlias }}
parameters:
jobTemplate: /eng/pipelines/templates/runtime-perf-job.yml@${{ parameters.performanceRepoAlias }}
buildConfig: release
runtimeFlavor: coreclr
platforms:
- linux_x64
jobParameters:
liveLibrariesBuildConfig: Release
runtimeType: wasm_coreclr
codeGenType: 'wasm'
r2rRunType: 'r2r_composite'
runKind: micro
logicalMachine: 'perfviper'
javascriptEngine: 'v8'
additionalJobIdentifier: coreclr_r2r_composite_v8
downloadSpecificBuild: ${{ parameters.downloadSpecificBuild }}
runtimeRepoAlias: ${{ parameters.runtimeRepoAlias }}
performanceRepoAlias: ${{ parameters.performanceRepoAlias }}
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}
4 changes: 2 additions & 2 deletions eng/pipelines/templates/run-performance-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ parameters:
isCompare: false # optional -- If the job is comparing two configurations
onlySanityCheck: false # optional -- Whether to only run a sanity check for pipeline validation, not performance testing
pgoRunType: '' # optional -- PGO run type (e.g. nodynamicpgo)
r2rRunType: '' # optional -- R2R run type (e.g. nor2r)
r2rRunType: '' # optional -- R2R run type (e.g. nor2r, r2r, r2r_composite)
experimentName: '' # optional -- Name of the experiment
javascriptEngine: '' # optional -- JavaScript engine to use
iOSLlvmBuild: false # optional -- Whether to build iOS with LLVM
Expand Down Expand Up @@ -242,7 +242,7 @@ jobs:
- '--cross-build'
- ${{ if ne(parameters.additionalSetupParameters, '') }}:
- '${{ parameters.additionalSetupParameters }}'
- ${{ if and(ne(parameters.wasmWorkloadSource, ''), eq(parameters.runtimeType, 'wasm_coreclr'), eq(parameters.r2rRunType, 'r2r')) }}:
- ${{ if and(ne(parameters.wasmWorkloadSource, ''), eq(parameters.runtimeType, 'wasm_coreclr'), in(parameters.r2rRunType, 'r2r', 'r2r_composite')) }}:
- '--wasm-workload-source "${{ parameters.wasmWorkloadSource }}"'
- template: /eng/pipelines/templates/send-to-helix-step.yml
parameters:
Expand Down
5 changes: 3 additions & 2 deletions scripts/benchmarks_ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,11 @@ def main(argv: list[str]):
if args.wasm_workload_source and not (
args.wasm
and args.wasm_runtime_flavor == 'CoreCLR'
and args.wasm_ready_to_run):
and micro_benchmarks.is_wasm_ready_to_run(args)):
raise ValueError(
'--wasm-workload-source requires --wasm '
'--wasm-runtime-flavor CoreCLR --wasm-ready-to-run')
'--wasm-runtime-flavor CoreCLR --wasm-ready-to-run '
'(or --wasm-ready-to-run-composite)')

# Acquire necessary tools (dotnet)
if not args.dotnet_path:
Expand Down
33 changes: 29 additions & 4 deletions scripts/micro_benchmarks.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,17 @@ def __get_bdn_arguments(user_input: str) -> list[str]:
required=False,
default=False,
action='store_true',
help='Publish CoreCLR WASM benchmarks as ReadyToRun'
help='Publish CoreCLR WASM benchmarks as per-assembly ReadyToRun'
)

parser.add_argument(
'--wasm-ready-to-run-composite',
dest='wasm_ready_to_run_composite',
required=False,
default=False,
action='store_true',
help='Publish CoreCLR WASM benchmarks as a single composite '
'ReadyToRun image (implies ReadyToRun)'
)

parser.add_argument(
Expand Down Expand Up @@ -252,9 +262,21 @@ def __process_arguments(args: list[str]):
return parsed_args


def is_wasm_ready_to_run_composite(args: Any) -> bool:
return bool(getattr(args, 'wasm_ready_to_run_composite', False))


def is_wasm_ready_to_run(args: Any) -> bool:
'''True for either per-assembly or composite CoreCLR WASM ReadyToRun.'''
return bool(args.wasm_ready_to_run) or is_wasm_ready_to_run_composite(args)


def validate_wasm_ready_to_run(args: Any) -> None:
if args.wasm_ready_to_run and (not args.wasm or args.wasm_runtime_flavor != 'CoreCLR'):
raise ArgumentTypeError('--wasm-ready-to-run requires --wasm --wasm-runtime-flavor CoreCLR')
if not args.wasm or args.wasm_runtime_flavor != 'CoreCLR':
if is_wasm_ready_to_run_composite(args):
raise ArgumentTypeError('--wasm-ready-to-run-composite requires --wasm --wasm-runtime-flavor CoreCLR')
if args.wasm_ready_to_run:
raise ArgumentTypeError('--wasm-ready-to-run requires --wasm --wasm-runtime-flavor CoreCLR')


def configure_wasm_ready_to_run(args: Any) -> None:
Expand All @@ -263,7 +285,10 @@ def configure_wasm_ready_to_run(args: Any) -> None:
# BenchmarkDotNet builds generated projects in child processes. MSBuild
# imports environment variables as properties, which lets the generated
# WASM project opt into R2R without requiring a new BDN command-line option.
environ['PERFLAB_WASM_READY_TO_RUN'] = str(args.wasm_ready_to_run).lower()
# Both variables are always written so a stale value from the parent
# environment cannot select a different mode.
environ['PERFLAB_WASM_READY_TO_RUN'] = str(is_wasm_ready_to_run(args)).lower()
environ['PERFLAB_WASM_READY_TO_RUN_COMPOSITE'] = str(is_wasm_ready_to_run_composite(args)).lower()


def __get_benchmarkdotnet_arguments(framework: str, args: Any) -> list[str]:
Expand Down
19 changes: 14 additions & 5 deletions scripts/run_performance_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,6 +697,9 @@ def get_run_configurations(
configurations["R2RType"] = "nor2r"
elif r2r_run_type == "r2r":
configurations["R2RType"] = "r2r"
elif r2r_run_type == "r2r_composite":
# CoreCLR WASM composite R2R gets its own PerfLab history, distinct from per-assembly r2r.
configurations["R2RType"] = "r2r_composite"

if runtime_type == "coreclr_r2r_interpreter":
configurations["R2RType"] = "r2r_interpreter"
Expand Down Expand Up @@ -754,7 +757,8 @@ def get_work_item_command(
wasm_coreclr: bool = False,
wasm_ready_to_run: bool = False,
only_sanity_check: bool = False,
wasm_workload_source: Optional[str] = None):
wasm_workload_source: Optional[str] = None,
wasm_ready_to_run_composite: bool = False):
if os_group == "windows":
work_item_command = [
"python",
Expand Down Expand Up @@ -793,9 +797,11 @@ def get_work_item_command(
]
if wasm_coreclr:
work_item_command += ["--wasm-runtime-flavor", "CoreCLR"]
if wasm_ready_to_run:
if wasm_ready_to_run_composite:
work_item_command += ["--wasm-ready-to-run-composite"]
elif wasm_ready_to_run:
work_item_command += ["--wasm-ready-to-run"]
if wasm_ready_to_run and wasm_workload_source:
if (wasm_ready_to_run or wasm_ready_to_run_composite) and wasm_workload_source:
work_item_command += [
"--wasm-workload-source",
wasm_workload_source,
Expand Down Expand Up @@ -861,6 +867,8 @@ def run_performance_job(args: RunPerformanceJobArgs):
wasm_coreclr = args.runtime_type == "wasm_coreclr"
wasm = args.runtime_type == "wasm" or wasm_coreclr # wasm_coreclr also uses wasm infrastructure
wasm_aot = wasm and is_aot and not wasm_coreclr
if args.r2r_run_type == "r2r_composite" and not wasm_coreclr:
raise Exception("r2r_composite R2R run type is only supported for the wasm_coreclr runtime type")

working_dir = os.path.join(args.performance_repo_dir, "CorrelationStaging") # folder in which the payload and workitem directories will be made
work_item_dir = os.path.join(working_dir, "workitem", "") # Folder in which the work item commands will be run in
Expand Down Expand Up @@ -1025,7 +1033,7 @@ def run_performance_job(args: RunPerformanceJobArgs):
args.wasm_workload_source)
wasm_sdk_cohort = (
wasm_coreclr
and args.r2r_run_type == "r2r"
and args.r2r_run_type in ("r2r", "r2r_composite")
and wasm_workload_source is not None)
helix_wasm_workload_source = (
wasm_workload_source if wasm_sdk_cohort else None)
Expand Down Expand Up @@ -1497,7 +1505,8 @@ def get_work_item_command_for_artifact_dir(artifact_dir: str):
wasm_coreclr,
wasm_coreclr and args.r2r_run_type == "r2r",
args.only_sanity_check,
helix_wasm_workload_source)
helix_wasm_workload_source,
wasm_coreclr and args.r2r_run_type == "r2r_composite")

work_item_command = get_work_item_command_for_artifact_dir(bdn_artifacts_directory)
baseline_work_item_command = get_work_item_command_for_artifact_dir(bdn_baseline_artifacts_dir)
Expand Down
Loading
Loading