diff --git a/eng/Versions.props b/eng/Versions.props
index d29d6703bec..0621a70ae59 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -11,7 +11,7 @@
10.0.0-rc.1.25555.107
10.0.0-rc.1.25555.107
10.0.0-rc.1.25555.107
- 0.16.0-nightly.20260302.459
+ 0.16.0-nightly.20260320.467
10.0.0-rc.1.25555.107
11.0.0-prerelease.26169.1
diff --git a/eng/pipelines/runtime-perf-jobs.yml b/eng/pipelines/runtime-perf-jobs.yml
index 8853fed9636..e0436d26fac 100644
--- a/eng/pipelines/runtime-perf-jobs.yml
+++ b/eng/pipelines/runtime-perf-jobs.yml
@@ -26,6 +26,12 @@ parameters:
configs:
- linux_x64
- windows_x64
+ - name: viperMicroR2RInterpreter
+ type: object
+ default:
+ enabled: true
+ configs:
+ - linux_x64
- name: monoMicro
type: object
default:
@@ -278,6 +284,23 @@ jobs:
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}
+ # CoreCLR Viper microbenchmarks Composite R2R with interpreter fallback — controlled by viperMicroR2RInterpreter toggle.
+ - ${{ if eq(parameters.viperMicroR2RInterpreter.enabled, true) }}:
+ - 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: ${{ parameters.viperMicroR2RInterpreter.configs }}
+ jobParameters:
+ liveLibrariesBuildConfig: Release
+ runtimeType: coreclr_r2r_interpreter
+ runKind: micro
+ logicalMachine: 'perfviper'
+ runtimeRepoAlias: ${{ parameters.runtimeRepoAlias }}
+ performanceRepoAlias: ${{ parameters.performanceRepoAlias }}
+ additionalJobIdentifier: 'R2RInterpreter'
+
# CoreCLR Cobalt SVE microbenchmarks — controlled by cobaltSveMicro toggle.
- ${{ if eq(parameters.cobaltSveMicro.enabled, true) }}:
- template: /eng/pipelines/common/platform-matrix.yml@${{ parameters.runtimeRepoAlias }}
diff --git a/eng/pipelines/templates/runtime-perf-job.yml b/eng/pipelines/templates/runtime-perf-job.yml
index 4ef0e2e0248..282d11b307e 100644
--- a/eng/pipelines/templates/runtime-perf-job.yml
+++ b/eng/pipelines/templates/runtime-perf-job.yml
@@ -36,7 +36,7 @@ jobs:
# Test job depends on the corresponding build job
${{ if eq(parameters.downloadSpecificBuild.buildId, '') }}:
dependsOn:
- - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'AndroidCoreCLR', 'iOSMono', 'iOSCoreCLR', 'iOSNativeAOT', 'wasm', 'wasm_coreclr', 'mono')) }}:
+ - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'AndroidCoreCLR', 'iOSMono', 'iOSCoreCLR', 'iOSNativeAOT', 'wasm', 'wasm_coreclr', 'mono', 'coreclr_r2r_interpreter')) }}:
- ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, 'coreclr') }}
- ${{ if and(eq(parameters.runtimeType, 'mono'), ne(parameters.codeGenType, 'AOT')) }}:
- ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, 'mono') }}
@@ -57,6 +57,8 @@ jobs:
- ${{ 'build_ios_arm64_release_iOSCoreCLR' }}
- ${{ if eq(parameters.runtimeType, 'iOSNativeAOT')}}:
- ${{ 'build_ios_arm64_release_iOSNativeAOT' }}
+ - ${{ if eq(parameters.runtimeType, 'coreclr_r2r_interpreter')}}:
+ - ${{ format('build_{0}{1}_{2}_{3}_{4}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, 'coreclr_r2r_interpreter') }}
variables:
- name: librariesDownloadDir
@@ -141,6 +143,13 @@ jobs:
artifactFileName: 'BuildArtifacts_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_$(buildConfigUpper)_${{ parameters.runtimeType }}$(archiveExtension)'
artifactName: 'BuildArtifacts_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_$(buildConfigUpper)_${{ parameters.runtimeType }}'
displayName: 'Runtime artifacts'
+ - ${{ elseif eq(parameters.runtimeType, 'coreclr_r2r_interpreter') }}:
+ - template: /eng/pipelines/templates/download-artifact-step.yml
+ parameters:
+ unpackFolder: $(librariesDownloadDir)/bin
+ artifactFileName: 'BuildArtifacts_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_$(buildConfigUpper)_coreclr_r2r_interpreter$(archiveExtension)'
+ artifactName: 'BuildArtifacts_${{ parameters.osGroup }}${{ parameters.osSubgroup }}_${{ parameters.archType }}_$(buildConfigUpper)_coreclr_r2r_interpreter'
+ displayName: 'R2R Interpreter Runtime artifacts'
- ${{ elseif or(eq(parameters.runtimeType, 'AndroidMono'), eq(parameters.runtimeType, 'AndroidCoreCLR'))}}:
# Download artifacts for Android Testing
- template: /eng/pipelines/templates/download-artifact-step.yml
diff --git a/scripts/build_runtime_payload.py b/scripts/build_runtime_payload.py
index a7218bca7da..dd8f82175e8 100644
--- a/scripts/build_runtime_payload.py
+++ b/scripts/build_runtime_payload.py
@@ -19,6 +19,7 @@
"build_coreroot_payload_simple",
"build_mono_payload",
"build_monoaot_payload",
+ "build_r2r_interpreter_payload",
"build_wasm_payload",
"build_wasm_coreclr_payload",
]
@@ -371,4 +372,47 @@ def build_wasm_coreclr_payload(
else:
getLogger().warning("Microsoft.NETCore.App.Ref pack not found – cannot determine version")
- _set_permissions_recursive([wasm_dotnet_dir, wasm_built_nugets_dir], mode=0o664)
\ No newline at end of file
+ _set_permissions_recursive([wasm_dotnet_dir, wasm_built_nugets_dir], mode=0o664)
+
+
+def build_r2r_interpreter_payload(
+ artifacts_archive_or_dir: str,
+ payload_dest: str,
+ os_group: str,
+ architecture: str,
+) -> None:
+ """Build a Composite R2R with interpreter fallback payload.
+
+ Stages the runtime pack and crossgen2 tool from a runtime build produced
+ with ``-dynamiccodecompiled false``. The crossgen2 files are placed under
+ a ``tools/`` subdirectory as required by the SDK's
+ ``ResolveReadyToRunCompilers`` target.
+
+ Args:
+ artifacts_archive_or_dir: Path to the build artifacts (archive or directory).
+ payload_dest: Destination root for the payload.
+ os_group: Target OS group (e.g. "linux").
+ architecture: Target architecture (e.g. "x64").
+ """
+ runtimepack_dir = os.path.join(payload_dest, "runtimepack")
+ crossgen2_tools_dir = os.path.join(payload_dest, "crossgen2", "tools")
+ os.makedirs(runtimepack_dir, exist_ok=True)
+ os.makedirs(crossgen2_tools_dir, exist_ok=True)
+
+ extract_archive_or_copy(
+ artifacts_archive_or_dir,
+ runtimepack_dir,
+ prefix=f"microsoft.netcore.app.runtime.{os_group}-{architecture}/Release/",
+ )
+
+ extract_archive_or_copy(
+ artifacts_archive_or_dir,
+ crossgen2_tools_dir,
+ prefix=f"crossgen2_publish/{architecture}/Release/",
+ )
+
+ # Ensure crossgen2 is executable
+ if os_group != "windows":
+ crossgen2_executable = os.path.join(crossgen2_tools_dir, "crossgen2")
+ if os.path.exists(crossgen2_executable):
+ os.chmod(crossgen2_executable, 0o755)
\ No newline at end of file
diff --git a/scripts/run_performance_job.py b/scripts/run_performance_job.py
index 3328415644f..f1e9a7d4673 100644
--- a/scripts/run_performance_job.py
+++ b/scripts/run_performance_job.py
@@ -458,6 +458,20 @@ def get_bdn_arguments(
"--wasmProcessTimeout", "20"
]
+ if runtime_type == "coreclr_r2r_interpreter":
+ if os_group == "windows":
+ bdn_arguments += [
+ "--runtimes", "r2r11_0",
+ "--customruntimepack", "%HELIX_CORRELATION_PAYLOAD%\\r2r_interpreter\\runtimepack",
+ "--aotcompilerpath", "%HELIX_CORRELATION_PAYLOAD%\\r2r_interpreter\\crossgen2",
+ ]
+ else:
+ bdn_arguments += [
+ "--runtimes", "r2r11_0",
+ "--customruntimepack", "$HELIX_CORRELATION_PAYLOAD/r2r_interpreter/runtimepack",
+ "--aotcompilerpath", "$HELIX_CORRELATION_PAYLOAD/r2r_interpreter/crossgen2",
+ ]
+
if category_exclusions:
bdn_arguments += ["--category-exclusion-filter", *set(category_exclusions)]
@@ -901,6 +915,18 @@ def run_performance_job(args: RunPerformanceJobArgs):
getLogger().info("Copying MonoAOT build to payload directory")
build_monoaot_payload(linux_mono_aot_dir, monoaot_dotnet_path, args.architecture)
+ use_r2r_interpreter = False
+ if args.runtime_type == "coreclr_r2r_interpreter":
+ use_r2r_interpreter = True
+ if not args.libraries_download_dir:
+ raise Exception("Libraries not downloaded for R2R interpreter")
+
+ r2r_interpreter_dir = os.path.join(args.libraries_download_dir, "bin")
+ r2r_interpreter_payload = os.path.join(payload_dir, "r2r_interpreter")
+
+ getLogger().info("Copying R2R interpreter build to payload directory")
+ build_r2r_interpreter_payload(r2r_interpreter_dir, r2r_interpreter_payload, args.os_group, args.architecture)
+
use_core_run = False
use_baseline_core_run = False
if not args.performance_repo_ci and args.runtime_type == "coreclr":