Skip to content

Commit

Permalink
SPMI no ASMDiff between Checked and Release (#61335)
Browse files Browse the repository at this point in the history
* SPMI no ASMDiff between Checked and Release

Created the first file that builds release and checked builds

* SuperPMI asmdiff checked and release
* Added downloading JIT release builds in superpmi-asmdiff-job
* Added dummy 'run-superpmi-asmdiff-job'

* SuperPmi asmdiff checked release
* Added JIT release download
* Added dummy run job that just runs superpmi replay

* SuperPMI asmdiff checked release
* Remove the 4th argument for jobName and displayName

* SuperPMI asmdiff checked release
* In run-superpmi-asmdiff-checked-release-job.yml,
  * Added release_directory and release artifact to the script arguments
  * Added ReleaseCorrelationPayloadDirectory and ReleaseArtifactName to parameters to send-to-helix-step.yml

* In superpmi_asmdiff_checked_release_setup.py
  * Added release_directory and release_artifactname arguments
  * Copied release binaries to source_directory/payload_release

* SuperPMI asmdiffs checked release
* Added superpmi_asmdiffs_checked_release_setup.py to set up Helix directories for checked in base and release in diff directories.
* Use superpmi_asmdiffs.py and superpmi-asmdiffs.proj.
* Renamed files from asmdiff to asmdiffs.

* SuperPMI asmdiffs checked release: resolve merge conflict

* SuperPMI asmdiffs checked release: Fixed to use a proj and a script file that compare with Release

* Superpmi asmdiffs checked release: changed to --diff_with_release as a boolean arg

* SuperPMI asmdiffs checked release: Add dependency to completed Release build

* Superpmi asmdiffs checked release: add diff_with_release back that got removed from merge

* SuperPMI asmdiffs checked release: Do not create asm file for asmdiff check with release

* SuperPMI asmdiffs checked release: Report failure asm diffs (return code 2) if --diff_with_release

* SuperPMI asmdiffs checked release: Handled code review feedback to remove jit-analyze and diff_summary.md

* SuperPMI asmdiffs checked release: Changed to checked_directory instead of base_directory

* SuperPMI asmdiffs checked release: explictly say checked_directory

* SuperPMI asmdiffs checked release: schedule to run on Saturdays and Sundays only.
  • Loading branch information
JulieLeeMSFT committed Mar 2, 2022
1 parent 6f9b9c1 commit 7830fdd
Show file tree
Hide file tree
Showing 7 changed files with 637 additions and 9 deletions.
41 changes: 41 additions & 0 deletions eng/pipelines/coreclr/superpmi-asmdiffs-checked-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
trigger: none

schedules:
- cron: "0 10 * * 6,0"
displayName: Sat and Sun at 2:00 AM (UTC-8:00)
branches:
include:
- main
always: true

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/build-jit-job.yml
buildConfig: release
platforms:
- windows_x64
- windows_x86
jobParameters:
uploadAs: 'pipelineArtifacts'

- template: /eng/pipelines/common/platform-matrix.yml
parameters:
jobTemplate: /eng/pipelines/coreclr/templates/superpmi-asmdiffs-checked-release-job.yml
buildConfig: checked
platforms:
- windows_x64
- windows_x86
helixQueueGroup: ci
helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
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: 320 # 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:

- 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: HelixResultLocation
value: '$(Build.SourcesDirectory)\artifacts\helixresults\'

- ${{ each variable in parameters.variables }}:
- ${{insert}}: ${{ variable }}

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

- script: |
mkdir -p $(SpmiCollectionLocation)
displayName: Create directory for SPMI collection
- script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi_asmdiffs_checked_release_setup.py -source_directory $(Build.SourcesDirectory) -checked_directory $(buildProductRootFolderPath) -release_directory $(releaseProductRootFolderPath) -arch $(archType)
displayName: ${{ format('SuperPMI asmdiffs checked release setup ({0} {1})', parameters.osGroup, parameters.archType) }}

# Run superpmi asmdiffs between checked build and release build 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: 4:00 # 4 hours
WorkItemDirectory: '$(WorkItemDirectory)'
CorrelationPayloadDirectory: '$(CorrelationPayloadDirectory)'
helixProjectArguments: '$(Build.SourcesDirectory)/src/coreclr/scripts/superpmi-asmdiffs-checked-release.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: PublishPipelineArtifact@1
displayName: Publish SuperPMI logs
inputs:
targetPath: $(SpmiLogsLocation)
artifactName: 'SuperPMI_Logs_$(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
@@ -0,0 +1,60 @@
parameters:
buildConfig: '' # required -- build configuration
archType: '' # required -- targeting CPU architecture
osGroup: '' # required -- operating system for the job
osSubgroup: '' # optional -- operating system subgroup
pool: ''
timeoutInMinutes: 320 # build timeout
variables: {}
helixQueues: ''
dependOnEvaluatePaths: false
runJobTemplate: '/eng/pipelines/coreclr/templates/run-superpmi-asmdiffs-checked-release-job.yml'

jobs:
- template: ${{ parameters.runJobTemplate }}
parameters:
jobName: ${{ format('superpmi_asmdiffs_checked_release_{0}{1}_{2}', parameters.osGroup, parameters.osSubgroup, parameters.archType) }}
displayName: ${{ format('SuperPMI asmdiffs checked release {0}{1} {2}', parameters.osGroup, parameters.osSubgroup, parameters.archType) }}
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, 'checked') }}
- ${{ format('coreclr_jit_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, 'release') }}

variables:

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

- name: releaseProductRootFolderPath
value: '$(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).Release'
- name: releaseProductArtifactName
value: 'CoreCLRProduct_${{ parameters.pgoType }}_${{ parameters.runtimeVariant }}_$(osGroup)$(osSubgroup)_$(archType)_release'

steps:

# Download jit checked builds
- template: /eng/pipelines/common/download-artifact-step.yml
parameters:
unpackFolder: $(buildProductRootFolderPath)
artifactFileName: '$(buildProductArtifactName)$(archiveExtension)'
artifactName: '$(buildProductArtifactName)'
displayName: 'JIT checked build'

#Download jit release builds
- template: /eng/pipelines/common/download-artifact-step.yml
parameters:
unpackFolder: $(releaseProductRootFolderPath)
artifactFileName: '$(releaseProductArtifactName)$(archiveExtension)'
artifactName: '$(releaseProductArtifactName)'
displayName: 'JIT release build'
73 changes: 73 additions & 0 deletions src/coreclr/scripts/superpmi-asmdiffs-checked-release.proj
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<Project Sdk="Microsoft.DotNet.Helix.Sdk" DefaultTargets="Test">
<!--
This is useful for local testing to print the produced helix items
To use this when you are changing how items are produced, uncomment the target
and replace the Project item at the top of the file with this:
<Project DefaultTargets="printItems">
Once you've done that you can run this to see the results:
dotnet msbuild .\superpmi-asmdiffs.proj /v:n
-->

<!-- <PropertyGroup>
<HelixTargetQueues>Some_Queue</HelixTargetQueues>
<Platform>Windows</Platform>
<Architecture>x64</Architecture>
</PropertyGroup>
<Target Name="printItems">
<Message Text="@(HelixWorkItem -> 'name: %(HelixWorkItem.Identity)
dir: %(HelixWorkItem.PayloadDirectory)
pre: %(HelixWorkItem.PreCommands)
command: %(HelixWorkItem.Command)
post: %(HelixWorkItem.PostCommands)
timeout: %(HelixWorkItem.Timeout) '"/>
</Target> -->

<PropertyGroup>
<Python>%HELIX_PYTHONPATH%</Python>
<ProductDirectory>%HELIX_CORRELATION_PAYLOAD%</ProductDirectory>
<SuperpmiLogsLocation>%HELIX_WORKITEM_UPLOAD_ROOT%</SuperpmiLogsLocation>
<!-- Workaround until https://github.com/dotnet/arcade/pull/6179 is not available -->
<HelixResultsDestinationDir>$(BUILD_SOURCESDIRECTORY)\artifacts\helixresults</HelixResultsDestinationDir>
<WorkItemCommand>$(Python) $(ProductDirectory)\superpmi_asmdiffs_checked_release.py --diff_with_release -base_jit_directory $(ProductDirectory)\base -diff_jit_directory $(ProductDirectory)\diff -log_directory $(SuperpmiLogsLocation)</WorkItemCommand>
<WorkItemTimeout>1:00</WorkItemTimeout>
</PropertyGroup>

<PropertyGroup>
<EnableAzurePipelinesReporter>false</EnableAzurePipelinesReporter>
<EnableXUnitReporter>false</EnableXUnitReporter>
<Creator>$(_Creator)</Creator>
<HelixAccessToken>$(_HelixAccessToken)</HelixAccessToken>
<HelixBuild>$(_HelixBuild)</HelixBuild>
<HelixSource>$(_HelixSource)</HelixSource>
<HelixTargetQueues>$(_HelixTargetQueues)</HelixTargetQueues>
<HelixType>$(_HelixType)</HelixType>
</PropertyGroup>

<ItemGroup>
<HelixCorrelationPayload Include="$(CorrelationPayloadDirectory)">
<PayloadDirectory>%(Identity)</PayloadDirectory>
</HelixCorrelationPayload>
</ItemGroup>

<ItemGroup Condition="'$(Architecture)' == 'x64'">
<SPMI_Partition Include="win-x64" Platform="windows" Architecture="x64" />
<SPMI_Partition Include="win-arm64" Platform="windows" Architecture="arm64" />
<SPMI_Partition Include="unix-x64" Platform="Linux" Architecture="x64" />
<SPMI_Partition Include="unix-arm64" Platform="Linux" Architecture="arm64" />
</ItemGroup>

<ItemGroup Condition="'$(Architecture)' == 'x86'">
<SPMI_Partition Include="win-x86" Platform="windows" Architecture="x86" />
<SPMI_Partition Include="unix-arm" Platform="Linux" Architecture="arm" />
</ItemGroup>

<ItemGroup>
<HelixWorkItem Include="@(SPMI_Partition)">
<Command>$(WorkItemCommand) -arch %(HelixWorkItem.Architecture) -platform %(HelixWorkItem.Platform)</Command>
<Timeout>$(WorkItemTimeout)</Timeout>
<DownloadFilesFromResults>superpmi_%(HelixWorkItem.Platform)_%(HelixWorkItem.Architecture).log;superpmi_download_%(HelixWorkItem.Platform)_%(HelixWorkItem.Architecture).log</DownloadFilesFromResults>
</HelixWorkItem>
</ItemGroup>
</Project>
26 changes: 17 additions & 9 deletions src/coreclr/scripts/superpmi.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@
asm_diff_parser.add_argument("-tag", help="Specify a word to add to the directory name where the asm diffs will be placed")
asm_diff_parser.add_argument("-metrics", action="append", help="Metrics option to pass to jit-analyze. Can be specified multiple times, or pass comma-separated values.")
asm_diff_parser.add_argument("-retainOnlyTopFiles", action="store_true", help="Retain only top .dasm files with largest improvements or regressions and delete remaining files.")
asm_diff_parser.add_argument("--diff_with_release", action="store_true", help="Specify if this is asmdiff using release binaries.")

# subparser for upload
upload_parser = subparsers.add_parser("upload", description=upload_description, parents=[core_root_parser, target_parser])
Expand Down Expand Up @@ -1492,6 +1493,7 @@ def replay_with_asm_diffs(self):
with ChangeDir(self.coreclr_args.core_root):
command = [self.superpmi_path] + flags + [self.base_jit_path, self.diff_jit_path, mch_file]
return_code = run_and_log(command)
logging.debug("return_code: %s", return_code)

base_metrics = read_csv_metrics(base_metrics_summary_file)
diff_metrics = read_csv_metrics(diff_metrics_summary_file)
Expand All @@ -1501,33 +1503,32 @@ def replay_with_asm_diffs(self):

if return_code != 0:

# Don't report as replay failure asm diffs (return code 2) or missing data (return code 3).
# Don't report as replay failure asm diffs (return code 2) if not checking diffs with Release build or missing data (return code 3).
# Anything else, such as compilation failure (return code 1, typically a JIT assert) will be
# reported as a replay failure.
if return_code != 2 and return_code != 3:
if (return_code != 2 or self.coreclr_args.diff_with_release) and return_code != 3:
result = False
files_with_replay_failures.append(mch_file)

if is_nonzero_length_file(fail_mcl_file):
# Unclean replay. Examine the contents of the fail.mcl file to dig into failures.
if return_code == 0:
logging.warning("Warning: SuperPMI returned a zero exit code, but generated a non-zero-sized mcl file")
print_fail_mcl_file_method_numbers(fail_mcl_file)
repro_base_command_line = "{} {} {}".format(self.superpmi_path, " ".join(altjit_asm_diffs_flags), self.diff_jit_path)
save_repro_mc_files(temp_location, self.coreclr_args, artifacts_base_name, repro_base_command_line)

# This file had asm diffs; keep track of that.
if is_nonzero_length_file(diff_mcl_file):
files_with_asm_diffs.append(mch_file)

# There were diffs. Go through each method that created diffs and
# create a base/diff asm file with diffable asm. In addition, create
# a standalone .mc for easy iteration.
if is_nonzero_length_file(diff_mcl_file):
if is_nonzero_length_file(diff_mcl_file) and not self.coreclr_args.diff_with_release:
# AsmDiffs. Save the contents of the fail.mcl file to dig into failures.

if return_code == 0:
logging.warning("Warning: SuperPMI returned a zero exit code, but generated a non-zero-sized mcl file")

# This file had asm diffs; keep track of that.
files_with_asm_diffs.append(mch_file)

self.diff_mcl_contents = None
with open(diff_mcl_file) as file_handle:
mcl_lines = file_handle.readlines()
Expand Down Expand Up @@ -1711,7 +1712,7 @@ async def create_one_artifact(jit_path: str, location: str, flags) -> str:

# Construct an overall Markdown summary file.

if len(all_md_summary_files) > 0:
if len(all_md_summary_files) > 0 and not self.coreclr_args.diff_with_release:
overall_md_summary_file = create_unique_file_name(self.coreclr_args.spmi_location, "diff_summary", "md")
if not os.path.isdir(self.coreclr_args.spmi_location):
os.makedirs(self.coreclr_args.spmi_location)
Expand Down Expand Up @@ -3310,6 +3311,11 @@ def verify_replay_common_args():
lambda unused: True,
"Unable to set retainOnlyTopFiles.")

coreclr_args.verify(args,
"diff_with_release",
lambda unused: True,
"Unable to set diff_with_release.")

process_base_jit_path_arg(coreclr_args)

jit_in_product_location = False
Expand Down Expand Up @@ -3555,6 +3561,8 @@ def main(args):
base_jit_path = coreclr_args.base_jit_path
diff_jit_path = coreclr_args.diff_jit_path

if coreclr_args.diff_with_release:
logging.info("Diff between Checked and Release.")
logging.info("Base JIT Path: %s", base_jit_path)
logging.info("Diff JIT Path: %s", diff_jit_path)

Expand Down
Loading

0 comments on commit 7830fdd

Please sign in to comment.