Skip to content

Commit

Permalink
Create superpmi-asmdiffs pipeline (#61194)
Browse files Browse the repository at this point in the history
Create a new `runtime-coreclr superpmi-asmdiffs` pipeline that runs SuperPMI asmdiffs for every change in the JIT directory.

The diffs are run on two platforms: Windows x64 and Windows x86. Linux, and Arm64 and Arm32, asm diffs are done using cross-compilers, as follows:

| Platform | Asm diffs |
| -- | -- |
| Windows x64 | win-x64, win-arm64, linux-x64, linux-arm64 |
| Windows x86 | win-x86, linux-arm |

The resulting summary .md files are uploaded into the pipeline artifacts, one .md file per platform (so, one for the Windows x64 runs and one for the Windows x86 runs). The results are also displayed in "Extensions" page of the AzDO pipeline.

The runs take about 50 minutes to complete (assuming not much waiting for machines).

The asm diffs pipeline is similar to the "superpmi-replay" pipeline, except:
1. It determines what an appropriate baseline JIT would be based on the PR commit and how it merges with the `main` branch. Given this, it downloads the matching baseline JITs from the JIT rolling build artifacts in Azure Storage.
2. It clones the `jitutils` repo and builds the `jit-analyze` tool, needed to generate the summary .md file.
3. It downloads and adds to the Helix machine payload a "portable" `git` installation, as `git diff` is used by `jit-analyze` for analyzing the generated .dasm files of the diff.
4. It collects all the various summary.md files into one per platform on which the runs are done, and publishes that to the artifacts and the `Extensions` page.
5. It only does one replay (asmdiffs) run, not one for each of a set of multiple stress modes.

As part of this implementation,
a. The `azdo_pipelines_util.py` was renamed to `jitutil.py`, and a lot of utility functions from superpmi.py were moved over to it. This was mostly to share the code for downloading and uncompressing .zip files. (There is a slight change to the output from the `superpmi.py download` command as a result.) However, I also moved a bunch of simple, more general helpers, for possible future sharing.
b. `jitrollingbuild.py download` can now take no arguments and download a baseline JIT (from the JIT rolling build Azure Storage location), for the current enlistment, to the default location. Previously, it required a specific git_hash and target directory. There is similar logic in superpmi.py, but not quite the same.
c. The `superpmi.py --no_progress` option was made global, and applied in a few more places. This was necessary because `superpmi.py asmdiffs` will download a coredistools binary from the JIT Azure Storage if one isn't found in the Core_Root folder.

Fixes #59445
  • Loading branch information
BruceForstall committed Nov 10, 2021
1 parent 213020c commit 8fe767f
Show file tree
Hide file tree
Showing 21 changed files with 1,770 additions and 714 deletions.
29 changes: 29 additions & 0 deletions eng/pipelines/coreclr/superpmi-asmdiffs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pr:
branches:
include:
- main
paths:
include:
- src/coreclr/jit/*

jobs:

- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/coreclr/templates/build-jit-job.yml
buildConfig: checked
platforms:
- windows_x64
- windows_x86
jobParameters:
uploadAs: 'pipelineArtifacts'

- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/coreclr/templates/superpmi-asmdiffs-job.yml
buildConfig: checked
platforms:
- windows_x64
- windows_x86
helixQueueGroup: ci
helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
137 changes: 137 additions & 0 deletions eng/pipelines/coreclr/templates/run-superpmi-asmdiffs-job.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
parameters:
steps: [] # optional -- any additional steps that need to happen before pulling down the jitutils repo and sending the jitutils to helix (ie building your repo)
variables: [] # optional -- list of additional variables to send to the template
jobName: '' # required -- job name
displayName: '' # optional -- display name for the job. Will use jobName if not passed
pool: '' # required -- name of the Build pool
container: '' # required -- name of the container
buildConfig: '' # required -- build configuration
archType: '' # required -- targeting CPU architecture
osGroup: '' # required -- operating system for the job
osSubgroup: '' # optional -- operating system subgroup
continueOnError: 'false' # optional -- determines whether to continue the build if the step errors
dependsOn: '' # optional -- dependencies of the job
timeoutInMinutes: 120 # optional -- timeout for the job
enableTelemetry: false # optional -- enable for telemetry
liveLibrariesBuildConfig: '' # optional -- live-live libraries configuration to use for the run
helixQueues: '' # required -- Helix queues
dependOnEvaluatePaths: false

jobs:
- template: xplat-pipeline-job.yml
parameters:
dependsOn: ${{ parameters.dependsOn }}
buildConfig: ${{ parameters.buildConfig }}
archType: ${{ parameters.archType }}
osGroup: ${{ parameters.osGroup }}
osSubgroup: ${{ parameters.osSubgroup }}
liveLibrariesBuildConfig: ${{ parameters.liveLibrariesBuildConfig }}
enableTelemetry: ${{ parameters.enableTelemetry }}
enablePublishBuildArtifacts: true
continueOnError: ${{ parameters.continueOnError }}
dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths }}
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}

${{ if ne(parameters.displayName, '') }}:
displayName: '${{ parameters.displayName }}'
${{ if eq(parameters.displayName, '') }}:
displayName: '${{ parameters.jobName }}'

variables:

- ${{ each variable in parameters.variables }}:
- ${{ if ne(variable.name, '') }}:
- name: ${{ variable.name }}
value: ${{ variable.value }}
- ${{ if ne(variable.group, '') }}:
- group: ${{ variable.group }}

- name: PythonScript
value: 'py -3'
- name: PipScript
value: 'py -3 -m pip'
- name: SpmiCollectionLocation
value: '$(Build.SourcesDirectory)\artifacts\spmi\'
- name: SpmiLogsLocation
value: '$(Build.SourcesDirectory)\artifacts\spmi_logs\'
- name: SpmiAsmdiffsLocation
value: '$(Build.SourcesDirectory)\artifacts\spmi_asmdiffs\'
- name: HelixResultLocation
value: '$(Build.SourcesDirectory)\artifacts\helixresults\'

workspace:
clean: all
pool:
${{ parameters.pool }}
container: ${{ parameters.container }}
steps:
- ${{ parameters.steps }}

- script: |
mkdir $(SpmiCollectionLocation)
mkdir $(SpmiLogsLocation)
mkdir $(SpmiAsmdiffsLocation)
displayName: Create directories
- script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi_asmdiffs_setup.py -source_directory $(Build.SourcesDirectory) -product_directory $(buildProductRootFolderPath) -arch $(archType)
displayName: ${{ format('SuperPMI asmdiffs setup ({0})', parameters.archType) }}

# Run superpmi asmdiffs in helix
- template: /eng/pipelines/common/templates/runtimes/send-to-helix-step.yml
parameters:
displayName: 'Send job to Helix'
helixBuild: $(Build.BuildNumber)
helixSource: $(_HelixSource)
helixType: 'build/tests/'
helixQueues: ${{ join(',', parameters.helixQueues) }}
creator: dotnet-bot
WorkItemTimeout: 2:00 # 2 hours
WorkItemDirectory: '$(WorkItemDirectory)'
CorrelationPayloadDirectory: '$(CorrelationPayloadDirectory)'
helixProjectArguments: '$(Build.SourcesDirectory)/src/coreclr/scripts/superpmi-asmdiffs.proj'
BuildConfig: ${{ parameters.buildConfig }}
osGroup: ${{ parameters.osGroup }}
archType: ${{ parameters.archType }}
shouldContinueOnError: true # Run the future step i.e. upload superpmi logs

# Always upload the available logs for diagnostics
- task: CopyFiles@2
displayName: Copying superpmi.log of all partitions
inputs:
sourceFolder: '$(HelixResultLocation)'
contents: '**/superpmi_*.log'
targetFolder: '$(SpmiLogsLocation)'
condition: always()

- task: CopyFiles@2
displayName: Copying superpmi.md of all partitions
inputs:
sourceFolder: '$(HelixResultLocation)'
contents: '**/superpmi_*.md'
targetFolder: '$(SpmiAsmdiffsLocation)'
condition: always()

- script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi_asmdiffs_summarize.py -diff_summary_dir $(SpmiAsmdiffsLocation) -arch $(archType)
displayName: ${{ format('Summarize ({0})', parameters.archType) }}
condition: always()

- task: PublishPipelineArtifact@1
displayName: Publish SuperPMI logs
inputs:
targetPath: $(SpmiLogsLocation)
artifactName: 'SuperPMI_Logs_$(archType)_$(buildConfig)'
condition: always()

- task: PublishPipelineArtifact@1
displayName: Publish SuperPMI asmdiffs files
inputs:
targetPath: $(SpmiAsmdiffsLocation)
artifactName: 'SuperPMI_Asmdiffs_$(archType)_$(buildConfig)'
condition: always()

- task: PublishPipelineArtifact@1
displayName: Publish SuperPMI build logs
inputs:
targetPath: $(Build.SourcesDirectory)/artifacts/log
artifactName: 'SuperPMI_BuildLogs_$(archType)_$(buildConfig)'
condition: always()
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ jobs:
- script: |
mkdir -p $(MergedMchFileLocation)
mkdir -p $(SpmiLogsLocation)
displayName: Create directory for merged collection
displayName: Create directories
- ${{ if eq(parameters.osGroup, 'windows') }}:
- script: |
mkdir $(MergedMchFileLocation)
Expand Down
7 changes: 4 additions & 3 deletions eng/pipelines/coreclr/templates/run-superpmi-replay-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ jobs:
- ${{ parameters.steps }}

- script: |
mkdir -p $(SpmiCollectionLocation)
displayName: Create directory for SPMI collection
mkdir $(SpmiCollectionLocation)
mkdir $(SpmiLogsLocation)
displayName: Create directories
- script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi_replay_setup.py -source_directory $(Build.SourcesDirectory) -product_directory $(buildProductRootFolderPath) -arch $(archType)
displayName: ${{ format('SuperPMI replay setup ({0} {1})', parameters.osGroup, parameters.archType) }}
displayName: ${{ format('SuperPMI replay setup ({0})', parameters.archType) }}

# Run superpmi replay in helix
- template: /eng/pipelines/common/templates/runtimes/send-to-helix-step.yml
Expand Down
39 changes: 39 additions & 0 deletions eng/pipelines/coreclr/templates/superpmi-asmdiffs-job.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
parameters:
buildConfig: '' # required -- build configuration
archType: '' # required -- targeting CPU architecture
osGroup: '' # required -- operating system for the job
osSubgroup: '' # optional -- operating system subgroup
pool: ''
timeoutInMinutes: 120 # build timeout
variables: {}
helixQueues: ''
dependOnEvaluatePaths: false
runJobTemplate: '/eng/pipelines/coreclr/templates/run-superpmi-asmdiffs-job.yml'

jobs:
- template: ${{ parameters.runJobTemplate }}
parameters:
jobName: ${{ format('superpmi_asmdiffs_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
displayName: ${{ format('SuperPMI asmdiffs {0}{1} {2} {3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}
pool: ${{ parameters.pool }}
buildConfig: ${{ parameters.buildConfig }}
archType: ${{ parameters.archType }}
osGroup: ${{ parameters.osGroup }}
osSubgroup: ${{ parameters.osSubgroup }}
dependOnEvaluatePaths: ${{ parameters.dependOnEvaluatePaths }}
timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
helixQueues: ${{ parameters.helixQueues }}
dependsOn:
- ${{ format('coreclr_jit_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }}

variables: ${{ parameters.variables }}

steps:

# Download jit builds
- template: /eng/pipelines/common/download-artifact-step.yml
parameters:
unpackFolder: $(buildProductRootFolderPath)
artifactFileName: '$(buildProductArtifactName)$(archiveExtension)'
artifactName: '$(buildProductArtifactName)'
displayName: 'JIT product build'
2 changes: 1 addition & 1 deletion src/coreclr/scripts/antigen_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from os.path import getsize
import os
from coreclr_arguments import *
from azdo_pipelines_util import run_command, TempDir
from jitutil import run_command, TempDir

parser = argparse.ArgumentParser(description="description")

Expand Down
Loading

0 comments on commit 8fe767f

Please sign in to comment.