From d4a9b6b501b65d3f9bb6838803817bcf752fcce8 Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Fri, 12 Feb 2021 16:43:34 -0800 Subject: [PATCH] Superpmi on Microbenchmarks (#47900) * Superpmi on Microbenchmarks * Fix the mch file path name * distribute the benchmarks in 30 partitions * Set input directory for benchmarks * Some fixes to superpmi_benchmarks Also update the GUID so we don't overwrite the existing collections. * fix the name of partition_index and partition_count * Point the core_root path to the superpmi script * fix python to invoke for setup * Add verbosity and include all benchmarks * Fix the benchmarks invocation * use benchmarks_ci.py script * run all benchmarks * fix the performance source code path * see why dotnet install fails * Comment all jobs except benchmarks * update the right fork * Switch back to doing installing dotnet on azure machine * Put dotnet in script * fix dumpMap, revert change in superpmi.py * Produce artifacts in temp folder - Disable mcs -strip for now - Pass the JitName variable * Experimental: Exit on failure * Revert "Produce artifacts in temp folder" This reverts commit afdfbd4b03a684d780ef06f644dba0dcf0621438. * Use JitName * Use workitem folder instead of correlation * fix typo in WorkItemDirectory * Set the payload directory * print error message before exiting * fix some linux issues * Make dotnet executable * resolve merge conflicts * fix typo from merge conflict * add logging around chmod * fix the is_windows condition * cleanup and disable linux arm/arm64 * remove the unwanted parameter --- eng/pipelines/coreclr/superpmi.yml | 32 ++- .../coreclr/templates/run-superpmi-job.yml | 5 +- src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/scripts/superpmi.proj | 110 +++++++-- src/coreclr/scripts/superpmi.py | 14 +- src/coreclr/scripts/superpmi_benchmarks.py | 271 +++++++++++++++++++++ .../{superpmi-setup.py => superpmi_setup.py} | 165 ++++++++----- 7 files changed, 506 insertions(+), 101 deletions(-) create mode 100644 src/coreclr/scripts/superpmi_benchmarks.py rename src/coreclr/scripts/{superpmi-setup.py => superpmi_setup.py} (76%) diff --git a/eng/pipelines/coreclr/superpmi.yml b/eng/pipelines/coreclr/superpmi.yml index 163c818..5927afe 100644 --- a/eng/pipelines/coreclr/superpmi.yml +++ b/eng/pipelines/coreclr/superpmi.yml @@ -101,6 +101,28 @@ jobs: platforms: # Linux tests are built on the OSX machines. # - OSX_x64 + - Linux_arm + - Linux_arm64 + - Linux_x64 + - windows_x64 + - windows_x86 + - windows_arm64 + - CoreClrTestBuildHost # Either OSX_x64 or Linux_x64 + helixQueueGroup: ci + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + jobParameters: + testGroup: outerloop + liveLibrariesBuildConfig: Release + collectionType: pmi + collectionName: tests + +- template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/superpmi-job.yml + buildConfig: checked + platforms: + # Linux tests are built on the OSX machines. + # - OSX_x64 # TODO: Linux crossgen2 jobs crash during collection, and need to be investigated. # - Linux_arm # - Linux_arm64 @@ -123,8 +145,9 @@ jobs: platforms: # Linux tests are built on the OSX machines. # - OSX_x64 - - Linux_arm - - Linux_arm64 + #TODO: Need special handling of running "benchmark build" from inside TMP folder on helix machine. + # - Linux_arm + # - Linux_arm64 - Linux_x64 - windows_x64 - windows_x86 @@ -135,6 +158,5 @@ jobs: jobParameters: testGroup: outerloop liveLibrariesBuildConfig: Release - collectionType: pmi - collectionName: tests - + collectionType: run + collectionName: benchmarks diff --git a/eng/pipelines/coreclr/templates/run-superpmi-job.yml b/eng/pipelines/coreclr/templates/run-superpmi-job.yml index 7961c30..5478133 100644 --- a/eng/pipelines/coreclr/templates/run-superpmi-job.yml +++ b/eng/pipelines/coreclr/templates/run-superpmi-job.yml @@ -87,6 +87,9 @@ jobs: - ${{ if eq(parameters.collectionName, 'libraries') }}: - name: InputDirectory value: '$(Core_Root_Dir)' + - ${{ if eq(parameters.collectionName, 'benchmarks') }}: + - name: InputDirectory + value: '$(Core_Root_Dir)' - ${{ if eq(parameters.collectionName, 'tests') }}: - name: InputDirectory value: '$(managedTestArtifactRootFolderPath)' @@ -103,7 +106,7 @@ jobs: steps: - ${{ parameters.steps }} - - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi-setup.py -source_directory $(Build.SourcesDirectory) -core_root_directory $(Core_Root_Dir) -arch $(archType) -mch_file_tag $(MchFileTag) -input_directory $(InputDirectory) -collection_name $(CollectionName) -collection_type $(CollectionType) -max_size 50 # size in MB + - script: $(PythonScript) $(Build.SourcesDirectory)/src/coreclr/scripts/superpmi_setup.py -source_directory $(Build.SourcesDirectory) -core_root_directory $(Core_Root_Dir) -arch $(archType) -mch_file_tag $(MchFileTag) -input_directory $(InputDirectory) -collection_name $(CollectionName) -collection_type $(CollectionType) -max_size 50 # size in MB displayName: ${{ format('SuperPMI setup ({0})', parameters.osGroup) }} # Run superpmi collection in helix diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 8cc074b..5cfbb06 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -32,11 +32,11 @@ ////////////////////////////////////////////////////////////////////////////////////////////////////////// // -constexpr GUID JITEEVersionIdentifier = { /* 6ca59d19-13a4-44f7-a184-e9cd1e8f57f8 */ - 0x6ca59d19, - 0x13a4, - 0x44f7, - { 0xa1, 0x84, 0xe9, 0xcd, 0x1e, 0x8f, 0x57, 0xf8 } +constexpr GUID JITEEVersionIdentifier = { /* af37688b-d4e5-4a41-a7ee-701728a470aa */ + 0xaf37688b, + 0xd4e5, + 0x4a41, + {0xa7, 0xee, 0x70, 0x17, 0x28, 0xa4, 0x70, 0xaa} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/scripts/superpmi.proj b/src/coreclr/scripts/superpmi.proj index 5fa51d7..05ad302 100644 --- a/src/coreclr/scripts/superpmi.proj +++ b/src/coreclr/scripts/superpmi.proj @@ -1,5 +1,31 @@ + + + + \ @@ -21,6 +47,10 @@ $(WorkItemDirectory)\pmiAssembliesDirectory %HELIX_WORKITEM_PAYLOAD%\binaries %HELIX_CORRELATION_PAYLOAD%\superpmi + + + %HELIX_WORKITEM_PAYLOAD%\performance + %HELIX_WORKITEM_UPLOAD_ROOT% $(BUILD_SOURCESDIRECTORY)\artifacts\helixresults @@ -31,6 +61,10 @@ $(WorkItemDirectory)/pmiAssembliesDirectory $HELIX_WORKITEM_PAYLOAD/binaries $HELIX_CORRELATION_PAYLOAD/superpmi + + + $HELIX_WORKITEM_PAYLOAD/performance + $HELIX_WORKITEM_UPLOAD_ROOT $(BUILD_SOURCESDIRECTORY)/artifacts/helixresults @@ -41,6 +75,10 @@ $(Python) $(WorkItemCommand) -assemblies $(PmiAssembliesDirectory) -arch $(Architecture) -build_type $(BuildConfig) -core_root $(SuperPMIDirectory) + + $(Python) $(SuperPMIDirectory)/superpmi_benchmarks.py -performance_directory $(PerformanceDirectory) -superpmi_directory $(SuperPMIDirectory) -core_root $(SuperPMIDirectory) -arch $(Architecture) + + false false @@ -68,12 +106,48 @@ - + + + 30 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + $(CollectionName).$(CollectionType).%(HelixWorkItem.PartitionId).$(MchFileTag) $(PmiAssembliesPayload)$(FileSeparatorChar)$(CollectionName)$(FileSeparatorChar)%(HelixWorkItem.PmiAssemblies) @@ -82,30 +156,14 @@ %(OutputFileName).mch;%(OutputFileName).mch.mct;%(OutputFileName).log - - - + + + $(CollectionName).$(CollectionType).%(HelixWorkItem.Index).$(MchFileTag) + $(WorkItemDirectory) + $(WorkItemCommand) -partition_count $(PartitionCount) -partition_index %(HelixWorkItem.Index) -output_mch_path $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).mch -log_file $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).log + $(WorkItemTimeout) + %(OutputFileName).mch;%(OutputFileName).mch.mct;%(OutputFileName).log + + diff --git a/src/coreclr/scripts/superpmi.py b/src/coreclr/scripts/superpmi.py index e9917d0..5ed0196 100755 --- a/src/coreclr/scripts/superpmi.py +++ b/src/coreclr/scripts/superpmi.py @@ -543,12 +543,13 @@ class TempDir: Use with: "with TempDir() as temp_dir" to change to that directory and then automatically change back to the original working directory afterwards and remove the temporary - directory and its contents (if args.skip_cleanup is False). + directory and its contents (if skip_cleanup is False). """ - def __init__(self, path=None): + def __init__(self, path=None, skip_cleanup=False): self.mydir = tempfile.mkdtemp() if path is None else path self.cwd = None + self._skip_cleanup = skip_cleanup def __enter__(self): self.cwd = os.getcwd() @@ -557,10 +558,7 @@ class TempDir: def __exit__(self, exc_type, exc_val, exc_tb): os.chdir(self.cwd) - # Note: we are using the global `args`, not coreclr_args. This works because - # the `skip_cleanup` argument is not processed by CoreclrArguments, but is - # just copied there. - if not args.skip_cleanup: + if not self._skip_cleanup: shutil.rmtree(self.mydir) @@ -758,7 +756,7 @@ class SuperPMICollect: passed = False try: - with TempDir(self.coreclr_args.temp_dir) as temp_location: + with TempDir(self.coreclr_args.temp_dir, self.coreclr_args.skip_cleanup) as temp_location: # Setup all of the temp locations self.base_fail_mcl_file = os.path.join(temp_location, "basefail.mcl") self.base_mch_file = os.path.join(temp_location, "base.mch") @@ -1573,7 +1571,7 @@ class SuperPMIReplayAsmDiffs: files_with_asm_diffs = [] files_with_replay_failures = [] - with TempDir(self.coreclr_args.temp_dir) as temp_location: + with TempDir(self.coreclr_args.temp_dir, self.coreclr_args.skip_cleanup) as temp_location: logging.debug("") logging.debug("Temp Location: %s", temp_location) logging.debug("") diff --git a/src/coreclr/scripts/superpmi_benchmarks.py b/src/coreclr/scripts/superpmi_benchmarks.py new file mode 100644 index 0000000..5f9725f --- /dev/null +++ b/src/coreclr/scripts/superpmi_benchmarks.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python3 +# +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. +# +# +# Title: superpmi_benchmarks.py +# +# Notes: +# +# Script to perform the superpmi collection while executing the Microbenchmarks present +# in https://github.com/dotnet/performance/tree/master/src/benchmarks/micro. + +import argparse +import re +import sys + +import stat +from os import path +from os.path import isfile +from shutil import copyfile +from coreclr_arguments import * +from superpmi import ChangeDir, TempDir +from superpmi_setup import run_command + +# Start of parser object creation. +is_windows = platform.system() == "Windows" +parser = argparse.ArgumentParser(description="description") + +parser.add_argument("-performance_directory", help="Path to performance directory") +parser.add_argument("-superpmi_directory", help="Path to superpmi directory") +parser.add_argument("-core_root", help="Path to Core_Root directory") +parser.add_argument("-output_mch_path", help="Absolute path to the mch file to produce") +parser.add_argument("-log_file", help="Name of the log file") +parser.add_argument("-partition_count", help="Total number of partitions") +parser.add_argument("-partition_index", help="Partition index to do the collection for") +parser.add_argument("-arch", help="Architecture") + + +def setup_args(args): + """ Setup the args for SuperPMI to use. + + Args: + args (ArgParse): args parsed by arg parser + + Returns: + args (CoreclrArguments) + + """ + coreclr_args = CoreclrArguments(args, require_built_core_root=False, require_built_product_dir=False, + require_built_test_dir=False, default_build_type="Checked") + + coreclr_args.verify(args, + "performance_directory", + lambda performance_directory: os.path.isdir(performance_directory), + "performance_directory doesn't exist") + + coreclr_args.verify(args, + "superpmi_directory", + lambda superpmi_directory: os.path.isdir(superpmi_directory), + "superpmi_directory doesn't exist") + + coreclr_args.verify(args, + "output_mch_path", + lambda output_mch_path: not os.path.isfile(output_mch_path), + "output_mch_path already exist") + + coreclr_args.verify(args, + "log_file", + lambda log_file: True, # not os.path.isfile(log_file), + "log_file already exist") + + coreclr_args.verify(args, + "core_root", + lambda core_root: os.path.isdir(core_root), + "core_root doesn't exist") + + coreclr_args.verify(args, + "partition_count", + lambda partition_count: partition_count.isnumeric(), + "Unable to set partition_count") + + coreclr_args.verify(args, + "partition_index", + lambda partition_index: partition_index.isnumeric(), + "Unable to set partition_index") + + coreclr_args.verify(args, + "arch", + lambda arch: arch.lower() in ["x86", "x64", "arm", "arm64"], + "Unable to set arch") + + return coreclr_args + + +def make_executable(file_name): + """Make file executable by changing the permission + + Args: + file_name (string): file to execute + """ + if is_windows: + return + + print("Inside make_executable") + run_command(["ls", "-l", file_name]) + os.chmod(file_name, + # read+execute for owner + (stat.S_IRUSR | stat.S_IXUSR) | + # read+execute for group + (stat.S_IRGRP | stat.S_IXGRP) | + # read+execute for other + (stat.S_IROTH | stat.S_IXOTH)) + run_command(["ls", "-l", file_name]) + + +def build_and_run(coreclr_args, output_mch_name): + """Build the microbenchmarks and run them under "superpmi collect" + + Args: + coreclr_args (CoreClrArguments): Arguments use to drive + output_mch_name (string): Name of output mch file name + """ + arch = coreclr_args.arch + python_path = sys.executable + core_root = coreclr_args.core_root + superpmi_directory = coreclr_args.superpmi_directory + performance_directory = coreclr_args.performance_directory + log_file = coreclr_args.log_file + partition_count = coreclr_args.partition_count + partition_index = coreclr_args.partition_index + dotnet_directory = os.path.join(performance_directory, "tools", "dotnet", arch) + dotnet_exe = os.path.join(dotnet_directory, "dotnet") + + artifacts_directory = os.path.join(performance_directory, "artifacts") + artifacts_packages_directory = os.path.join(artifacts_directory, "packages") + project_file = path.join(performance_directory, "src", "benchmarks", "micro", "MicroBenchmarks.csproj") + benchmarks_dll = path.join(artifacts_directory, "MicroBenchmarks.dll") + + if is_windows: + shim_name = "%JitName%" + corerun_exe = "CoreRun.exe" + script_name = "run_microbenchmarks.bat" + else: + shim_name = "$JitName" + corerun_exe = "corerun" + script_name = "run_microbenchmarks.sh" + + make_executable(dotnet_exe) + + run_command( + [dotnet_exe, "restore", project_file, "--packages", + artifacts_packages_directory], _exit_on_fail=True) + + run_command( + [dotnet_exe, "build", project_file, "--configuration", "Release", + "--framework", "net6.0", "--no-restore", "/p:NuGetPackageRoot=" + artifacts_packages_directory, + "-o", artifacts_directory], _exit_on_fail=True) + + collection_command = f"{dotnet_exe} {benchmarks_dll} --filter \"*\" --corerun {path.join(core_root, corerun_exe)} --partition-count {partition_count} " \ + f"--partition-index {partition_index} --envVars COMPlus_JitName:{shim_name} " \ + "--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart" + + # Generate the execution script in Temp location + with TempDir() as temp_location: + script_name = path.join(temp_location, script_name) + + contents = [] + # Unset the JitName so dotnet process will not fail + if is_windows: + contents.append("set JitName=%COMPlus_JitName%") + contents.append("set COMPlus_JitName=") + else: + contents.append("#!/bin/bash") + contents.append("export JitName=$COMPlus_JitName") + contents.append("unset COMPlus_JitName") + contents.append(f"pushd {performance_directory}") + contents.append(collection_command) + + with open(script_name, "w") as collection_script: + collection_script.write(os.linesep.join(contents)) + + print() + print(f"{script_name} contents:") + print("******************************************") + print(os.linesep.join(contents)) + print("******************************************") + + make_executable(script_name) + + run_command([ + python_path, path.join(superpmi_directory, "superpmi.py"), "collect", "-core_root", core_root, + # Disable ReadyToRun so we always JIT R2R methods and collect them + "--use_zapdisable", + "-output_mch_path", output_mch_name, "-log_file", log_file, "-log_level", "debug", + script_name], _exit_on_fail=True) + + +def strip_unrelated_mc(coreclr_args, old_mch_filename, new_mch_filename): + """Perform the post processing of produced .mch file by stripping the method contexts + that are specific to BenchmarkDotnet boilerplate code and hard + + Args: + coreclr_args (CoreclrArguments): Arguments + old_mch_filename (string): Name of source .mch file + new_mch_filename (string): Name of new .mch file to produce post-processing. + """ + performance_directory = coreclr_args.performance_directory + core_root = coreclr_args.core_root + methods_to_strip_list = path.join(performance_directory, "methods_to_strip.mcl") + + mcs_exe = path.join(core_root, "mcs") + mcs_command = [mcs_exe, "-dumpMap", old_mch_filename] + + # Gather method list to strip + (mcs_out, _, return_code) = run_command(mcs_command) + if return_code != 0: + # If strip command fails, then just copy the old_mch to new_mch + print(f"-dumpMap failed. Copying {old_mch_filename} to {new_mch_filename}.") + copyfile(old_mch_filename, new_mch_filename) + copyfile(old_mch_filename + ".mct", new_mch_filename + ".mct") + return + + method_context_list = mcs_out.decode("utf-8").split(os.linesep) + filtered_context_list = [] + + match_pattern = re.compile('^(\\d+),(BenchmarkDotNet|Perfolizer)') + print("Method indices to strip:") + for mc_entry in method_context_list: + matched = match_pattern.match(mc_entry) + if matched: + print(matched.group(1)) + filtered_context_list.append(matched.group(1)) + print(f"Total {len(filtered_context_list)} methods.") + + with open(methods_to_strip_list, "w") as f: + f.write('\n'.join(filtered_context_list)) + + # Strip and produce new .mcs file + if run_command([mcs_exe, "-strip", methods_to_strip_list, old_mch_filename, new_mch_filename])[2] != 0: + # If strip command fails, then just copy the old_mch to new_mch + print(f"-strip failed. Copying {old_mch_filename} to {new_mch_filename}.") + copyfile(old_mch_filename, new_mch_filename) + copyfile(old_mch_filename + ".mct", new_mch_filename + ".mct") + return + + # Create toc file + run_command([mcs_exe, "-toc", new_mch_filename]) + + +def main(main_args): + """ Main entry point + + Args: + main_args ([type]): Arguments to the script + """ + coreclr_args = setup_args(main_args) + + all_output_mch_name = path.join(coreclr_args.output_mch_path + "_all.mch") + build_and_run(coreclr_args, all_output_mch_name) + if os.path.isfile(all_output_mch_name): + pass + else: + print("No mch file generated.") + + strip_unrelated_mc(coreclr_args, all_output_mch_name, coreclr_args.output_mch_path) + + +if __name__ == "__main__": + args = parser.parse_args() + sys.exit(main(args)) diff --git a/src/coreclr/scripts/superpmi-setup.py b/src/coreclr/scripts/superpmi_setup.py similarity index 76% rename from src/coreclr/scripts/superpmi-setup.py rename to src/coreclr/scripts/superpmi_setup.py index 58c4d25..21f51da 100644 --- a/src/coreclr/scripts/superpmi-setup.py +++ b/src/coreclr/scripts/superpmi_setup.py @@ -1,10 +1,10 @@ #!/usr/bin/env python3 # -## Licensed to the .NET Foundation under one or more agreements. -## The .NET Foundation licenses this file to you under the MIT license. +# Licensed to the .NET Foundation under one or more agreements. +# The .NET Foundation licenses this file to you under the MIT license. # ## -# Title : superpmi-setup.py +# Title : superpmi_setup.py # # Notes: # @@ -41,6 +41,7 @@ import tempfile from os import linesep, listdir, path, walk from os.path import isfile, join, getsize from coreclr_arguments import * +from superpmi import ChangeDir # Start of parser object creation. @@ -116,6 +117,7 @@ native_binaries_to_ignore = [ MAX_FILES_COUNT = 1500 + def setup_args(args): """ Setup the args for SuperPMI to use. @@ -236,7 +238,7 @@ def first_fit(sorted_by_size, max_size): if file_size < max_size: for p_index in partitions: total_in_curr_par = sum(n for _, n in partitions[p_index]) - if (((total_in_curr_par + file_size) < max_size) and (len(partitions[p_index]) < MAX_FILES_COUNT)): + if ((total_in_curr_par + file_size) < max_size) and (len(partitions[p_index]) < MAX_FILES_COUNT): partitions[p_index].append(curr_file) found_bucket = True break @@ -254,20 +256,31 @@ def first_fit(sorted_by_size, max_size): return partitions -def run_command(command_to_run, _cwd=None): +def run_command(command_to_run, _exit_on_fail=False): """ Runs the command. Args: command_to_run ([string]): Command to run along with arguments. - _cmd (string): Current working directory. + _exit_on_fail (bool): If it should exit on failure. + Returns: + (string, string): Returns a tuple of stdout and stderr """ print("Running: " + " ".join(command_to_run)) - with subprocess.Popen(command_to_run, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=_cwd) as proc: - stdout, stderr = proc.communicate() - if len(stdout) > 0: - print(stdout.decode("utf-8")) - if len(stderr) > 0: - print(stderr.decode("utf-8")) + command_stdout = "" + command_stderr = "" + return_code = 1 + with subprocess.Popen(command_to_run, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc: + command_stdout, command_stderr = proc.communicate() + return_code = proc.returncode + + if len(command_stdout) > 0: + print(command_stdout.decode("utf-8")) + if len(command_stderr) > 0: + print(command_stderr.decode("utf-8")) + if _exit_on_fail and return_code != 0: + print("Command failed. Exiting.") + sys.exit(1) + return command_stdout, command_stderr, return_code def copy_directory(src_path, dst_path, verbose_output=True, match_func=lambda path: True): @@ -322,7 +335,8 @@ def copy_files(src_path, dst_path, file_names): shutil.copy2(f, dst_path_of_file) -def partition_files(src_directory, dst_directory, max_size, exclude_directories=[], exclude_files=native_binaries_to_ignore): +def partition_files(src_directory, dst_directory, max_size, exclude_directories=[], + exclude_files=native_binaries_to_ignore): """ Copy bucketized files based on size to destination folder. Args: @@ -345,6 +359,41 @@ def partition_files(src_directory, dst_directory, max_size, exclude_directories= index += 1 +def setup_microbenchmark(workitem_directory, arch): + """ Perform setup of microbenchmarks + + Args: + workitem_directory (string): Path to work + arch (string): Architecture for which dotnet will be installed + """ + performance_directory = path.join(workitem_directory, "performance") + + run_command( + ["git", "clone", "--quiet", "--depth", "1", "https://github.com/dotnet/performance", performance_directory]) + + with ChangeDir(performance_directory): + dotnet_directory = os.path.join(performance_directory, "tools", "dotnet", arch) + dotnet_install_script = os.path.join(performance_directory, "scripts", "dotnet.py") + + if not isfile(dotnet_install_script): + print("Missing " + dotnet_install_script) + return + + run_command( + get_python_name() + [dotnet_install_script, "install", "--architecture", arch, "--install-dir", dotnet_directory, "--verbose"]) + +def get_python_name(): + """Gets the python name + + Returns: + string: Returns the appropriate python name depending on the OS. + """ + if is_windows: + return ["py", "-3"] + else: + return ["python3"] + + def set_pipeline_variable(name, value): """ This method sets pipeline variable. @@ -353,8 +402,8 @@ def set_pipeline_variable(name, value): value (string): Value of the variable. """ define_variable_format = "##vso[task.setvariable variable={0}]{1}" - print("{0} -> {1}".format(name, value)) # logging - print(define_variable_format.format(name, value)) # set variable + print("{0} -> {1}".format(name, value)) # logging + print(define_variable_format.format(name, value)) # set variable def main(main_args): @@ -397,55 +446,59 @@ def main(main_args): print('Copying {} -> {}'.format(coreclr_args.core_root_directory, superpmi_dst_directory)) copy_directory(coreclr_args.core_root_directory, superpmi_dst_directory, match_func=acceptable_copy) - # Clone and build jitutils - try: - with tempfile.TemporaryDirectory() as jitutils_directory: - run_command( - ["git", "clone", "--quiet", "--depth", "1", "https://github.com/dotnet/jitutils", jitutils_directory]) - # Set dotnet path to run bootstrap - os.environ["PATH"] = path.join(source_directory, ".dotnet") + os.pathsep + os.environ["PATH"] - bootstrap_file = "bootstrap.cmd" if is_windows else "bootstrap.sh" - run_command([path.join(jitutils_directory, bootstrap_file)], jitutils_directory) - - copy_files(path.join(jitutils_directory, "bin"), superpmi_dst_directory, [path.join(jitutils_directory, "bin", "pmi.dll")]) - except PermissionError as pe_error: - # Details: https://bugs.python.org/issue26660 - print('Ignoring PermissionError: {0}'.format(pe_error)) - # Workitem directories workitem_directory = path.join(source_directory, "workitem") - pmiassemblies_directory = path.join(workitem_directory, "pmiAssembliesDirectory") - - # NOTE: we can't use the build machine ".dotnet" to run on all platforms. E.g., the Windows x86 build uses a - # Windows x64 .dotnet\dotnet.exe that can't load a 32-bit shim. Thus, we always use corerun from Core_Root to invoke crossgen2. - # The following will copy .dotnet to the correlation payload in case we change our mind, and need or want to use it for some scenarios. - - # # Copy ".dotnet" to correlation_payload_directory for crossgen2 job; it is needed to invoke crossgen2.dll - # if coreclr_args.collection_type == "crossgen2": - # dotnet_src_directory = path.join(source_directory, ".dotnet") - # dotnet_dst_directory = path.join(correlation_payload_directory, ".dotnet") - # print('Copying {} -> {}'.format(dotnet_src_directory, dotnet_dst_directory)) - # copy_directory(dotnet_src_directory, dotnet_dst_directory, verbose_output=False) - - # payload - input_artifacts = path.join(pmiassemblies_directory, coreclr_args.collection_name) - exclude_directory = ['Core_Root'] if coreclr_args.collection_name == "tests" else [] - exclude_files = native_binaries_to_ignore - if coreclr_args.collection_type == "crossgen2": - print('Adding exclusions for crossgen2') - # Currently, trying to crossgen2 R2RTest\Microsoft.Build.dll causes a pop-up failure, so exclude it. - exclude_files += [ "Microsoft.Build.dll" ] - partition_files(coreclr_args.input_directory, input_artifacts, coreclr_args.max_size, exclude_directory, exclude_files) + input_artifacts = "" + + if coreclr_args.collection_name == "benchmarks": + # Setup microbenchmarks + setup_microbenchmark(workitem_directory, arch) + else: + # Setup for pmi/crossgen runs + + # Clone and build jitutils + try: + with tempfile.TemporaryDirectory() as jitutils_directory: + run_command( + ["git", "clone", "--quiet", "--depth", "1", "https://github.com/dotnet/jitutils", jitutils_directory]) + # Set dotnet path to run bootstrap + os.environ["PATH"] = path.join(source_directory, ".dotnet") + os.pathsep + os.environ["PATH"] + bootstrap_file = "bootstrap.cmd" if is_windows else "bootstrap.sh" + run_command([path.join(jitutils_directory, bootstrap_file)], jitutils_directory) + + copy_files(path.join(jitutils_directory, "bin"), superpmi_dst_directory, [path.join(jitutils_directory, "bin", "pmi.dll")]) + except PermissionError as pe_error: + # Details: https://bugs.python.org/issue26660 + print('Ignoring PermissionError: {0}'.format(pe_error)) + + # NOTE: we can't use the build machine ".dotnet" to run on all platforms. E.g., the Windows x86 build uses a + # Windows x64 .dotnet\dotnet.exe that can't load a 32-bit shim. Thus, we always use corerun from Core_Root to invoke crossgen2. + # The following will copy .dotnet to the correlation payload in case we change our mind, and need or want to use it for some scenarios. + + # # Copy ".dotnet" to correlation_payload_directory for crossgen2 job; it is needed to invoke crossgen2.dll + # if coreclr_args.collection_type == "crossgen2": + # dotnet_src_directory = path.join(source_directory, ".dotnet") + # dotnet_dst_directory = path.join(correlation_payload_directory, ".dotnet") + # print('Copying {} -> {}'.format(dotnet_src_directory, dotnet_dst_directory)) + # copy_directory(dotnet_src_directory, dotnet_dst_directory, verbose_output=False) + + # payload + pmiassemblies_directory = path.join(workitem_directory, "pmiAssembliesDirectory") + input_artifacts = path.join(pmiassemblies_directory, coreclr_args.collection_name) + exclude_directory = ['Core_Root'] if coreclr_args.collection_name == "tests" else [] + exclude_files = native_binaries_to_ignore + if coreclr_args.collection_type == "crossgen2": + print('Adding exclusions for crossgen2') + # Currently, trying to crossgen2 R2RTest\Microsoft.Build.dll causes a pop-up failure, so exclude it. + exclude_files += [ "Microsoft.Build.dll" ] + partition_files(coreclr_args.input_directory, input_artifacts, coreclr_args.max_size, exclude_directory, exclude_files) # Set variables print('Setting pipeline variables:') set_pipeline_variable("CorrelationPayloadDirectory", correlation_payload_directory) set_pipeline_variable("WorkItemDirectory", workitem_directory) set_pipeline_variable("InputArtifacts", input_artifacts) - if is_windows: - set_pipeline_variable("Python", "py -3") - else: - set_pipeline_variable("Python", "python3") + set_pipeline_variable("Python", ' '.join(get_python_name())) set_pipeline_variable("Architecture", arch) set_pipeline_variable("Creator", creator) set_pipeline_variable("Queue", helix_queue) -- 2.7.4