diff --git a/src/code/PowerShellGet.csproj b/src/code/PowerShellGet.csproj index dbd51ee95..e9d2e9a88 100644 --- a/src/code/PowerShellGet.csproj +++ b/src/code/PowerShellGet.csproj @@ -27,6 +27,10 @@ + + + + diff --git a/test/perf/benchmarks/BenchmarksV2LocalRepo.cs b/test/perf/benchmarks/BenchmarksV2LocalRepo.cs new file mode 100644 index 000000000..966db9c5b --- /dev/null +++ b/test/perf/benchmarks/BenchmarksV2LocalRepo.cs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using BenchmarkDotNet; +using BenchmarkDotNet.Attributes; +using Microsoft.PowerShell; +using System; +using System.Collections.ObjectModel; +using System.Management.Automation; + +namespace Benchmarks +{ + public class BenchmarksV2LocalRepo + { + System.Management.Automation.PowerShell pwsh; + + [GlobalSetup] + public void GlobalSetup() + { + // Setting up the PowerShell runspace + var defaultSS = System.Management.Automation.Runspaces.InitialSessionState.CreateDefault2(); + defaultSS.ExecutionPolicy = ExecutionPolicy.Unrestricted; + pwsh = System.Management.Automation.PowerShell.Create(defaultSS); + + // Using PSGet v3 in order to save the Az modules and its dependencies + pwsh.AddScript("Import-Module PowerShellGet -RequiredVersion 3.0.14 -Force"); + pwsh.AddScript("New-Item TestRepo -ItemType Directory"); + pwsh.AddScript("Save-PSResource -Name Az -Repository PSGallery -AsNupkg -TrustRepository -Path .\\TestRepo"); + + // Now import the PSGet module version we want to test and register a local repo + pwsh.AddScript("Import-Module PowerShellGet -RequiredVersion 2.2.5 -Force"); + pwsh.AddScript("Register-PSRepository -Name LocalRepo -SourceLocation .\\TestRepo"); + + pwsh.Invoke(); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + pwsh.Dispose(); + } + + [Benchmark] + public void FindAzModuleV2() + + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-Module -Name Az -Repository LocalRepo"); + pwsh.Invoke(); + } + + [Benchmark] + public void FindAzModuleAndDependenciesV2() + + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-Module -Name Az -IncludeDependencies -Repository LocalRepo"); + pwsh.Invoke(); + } + + [Benchmark] + public void InstallAzModuleAndDependenciesV2() + + { + pwsh.Commands.Clear(); + pwsh.AddScript("Install-Module -Name Az -Repository LocalRepo -Force"); + pwsh.Invoke(); + } + } +} diff --git a/test/perf/benchmarks/BenchmarksV2RemoteRepo.cs b/test/perf/benchmarks/BenchmarksV2RemoteRepo.cs new file mode 100644 index 000000000..cfa0cf88c --- /dev/null +++ b/test/perf/benchmarks/BenchmarksV2RemoteRepo.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using BenchmarkDotNet; +using BenchmarkDotNet.Attributes; +using Microsoft.PowerShell; +using System; +using System.Collections.ObjectModel; +using System.Management.Automation; + +namespace Benchmarks +{ + public class BenchmarksV2RemoteRepo + { + System.Management.Automation.PowerShell pwsh; + + [GlobalSetup] + public void GlobalSetup() + { + // Setting up the PowerShell runspace + var defaultSS = System.Management.Automation.Runspaces.InitialSessionState.CreateDefault2(); + defaultSS.ExecutionPolicy = ExecutionPolicy.Unrestricted; + pwsh = System.Management.Automation.PowerShell.Create(defaultSS); + + // Import the PSGet version we want to test + pwsh.AddScript("Import-Module PowerShellGet -RequiredVersion 2.2.5 -Force"); + pwsh.Invoke(); + } + + [GloblaCleanup] + public void IterationCleanup() + { + pwsh.Dispose(); + } + + [Benchmark] + public void FindAzModuleV2() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-Module -Name Az -Repository PSGallery"); + pwsh.Invoke(); + } + + [Benchmark] + public void FindAzModuleAndDependenciesV2() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-Module -Name Az -IncludeDependencies -Repository PSGallery"); + pwsh.Invoke(); + } + + [Benchmark] + public void InstallAzModuleAndDependenciesV2() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Install-Module -Name Az -Repository PSGallery -Force"); + pwsh.Invoke(); + } + } +} diff --git a/test/perf/benchmarks/BenchmarksV3LocalRepo.cs b/test/perf/benchmarks/BenchmarksV3LocalRepo.cs new file mode 100644 index 000000000..f3cfe6044 --- /dev/null +++ b/test/perf/benchmarks/BenchmarksV3LocalRepo.cs @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using BenchmarkDotNet; +using BenchmarkDotNet.Attributes; +using Microsoft.PowerShell; +using System; +using System.Collections.ObjectModel; +using System.Management.Automation; + +namespace Benchmarks +{ + public class BenchmarksV3LocalRepo + { + System.Management.Automation.PowerShell pwsh; + + [GlobalSetup] + public void GlobalSetup() + { + // Setting up the PowerShell runspace + var defaultSS = System.Management.Automation.Runspaces.InitialSessionState.CreateDefault2(); + defaultSS.ExecutionPolicy = ExecutionPolicy.Unrestricted; + pwsh = System.Management.Automation.PowerShell.Create(defaultSS); + + // Import the PSGet module version we want to test, register a local repo, and save the Az modules and its dependencies + pwsh.AddScript("Import-Module PowerShellGet -RequiredVersion 3.0.14 -Force"); + pwsh.AddScript("New-Item TestRepo -ItemType Directory"); + pwsh.AddScript("Register-PSResourceRepository -Name LocalRepo -Uri .\\TestRepo"); + pwsh.AddScript("Save-PSResource -Name Az -Repository PSGallery -AsNupkg -TrustRepository -Path .\\TestRepo"); + + pwsh.Invoke(); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + pwsh.Dispose(); + } + + [Benchmark] + public void FindAzModuleV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-PSResource -Name Az -Repository LocalRepo"); + pwsh.Invoke(); + } + + [Benchmark] + public void FindAzModuleAndDependenciesV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-PSResource -Name Az -IncludeDependencies -Repository LocalRepo"); + pwsh.Invoke(); + } + + [Benchmark] + public void InstallAzModuleV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Install-PSResource -Name Az -Repository LocalRepo -TrustRepository -SkipDependencyCheck -Reinstall"); + pwsh.Invoke(); + } + + [Benchmark] + public void InstallAzModuleAndDependenciesV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Install-PSResource -Name Az -Repository LocalRepo -TrustRepository -Reinstall"); + pwsh.Invoke(); + } + } +} diff --git a/test/perf/benchmarks/BenchmarksV3RemoteRepo.cs b/test/perf/benchmarks/BenchmarksV3RemoteRepo.cs new file mode 100644 index 000000000..278dd7535 --- /dev/null +++ b/test/perf/benchmarks/BenchmarksV3RemoteRepo.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using BenchmarkDotNet; +using BenchmarkDotNet.Attributes; +using Microsoft.PowerShell; +using System; +using System.Collections.ObjectModel; +using System.Management.Automation; + +namespace Benchmarks +{ + public class BenchmarksV3RemoteRepo + { + System.Management.Automation.PowerShell pwsh; + + [GlobalSetup] + public void GlobalSetup() + { + // Setting up the PowerShell runspace + var defaultSS = System.Management.Automation.Runspaces.InitialSessionState.CreateDefault2(); + defaultSS.ExecutionPolicy = ExecutionPolicy.Unrestricted; + pwsh = System.Management.Automation.PowerShell.Create(defaultSS); + + // Import the PSGet version we want to test + pwsh.AddScript("Import-Module PowerShellGet -RequiredVersion 3.0.14 -Force"); + pwsh.Invoke(); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + pwsh.Dispose(); + } + + [Benchmark] + public void FindAzModuleV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-PSResource -Name Az -Repository PSGallery"); + pwsh.Invoke(); + } + + [Benchmark] + public void FindAzModuleAndDependenciesV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Find-PSResource -Name Az -IncludeDependencies -Repository PSGallery"); + pwsh.Invoke(); + } + + [Benchmark] + public void InstallAzModuleV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Install-PSResource -Name Az -Repository PSGallery -TrustRepository -SkipDependencyCheck -Reinstall"); + pwsh.Invoke(); + } + + [Benchmark] + public void InstallAzModuleAndDependenciesV3() + { + pwsh.Commands.Clear(); + pwsh.AddScript("Install-PSResource -Name Az -Repository PSGallery -TrustRepository -Reinstall"); + pwsh.Invoke(); + } + } +} diff --git a/test/perf/benchmarks/Program.cs b/test/perf/benchmarks/Program.cs new file mode 100644 index 000000000..a6e6ac316 --- /dev/null +++ b/test/perf/benchmarks/Program.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using BenchmarkDotNet.Running; + +namespace Benchmarks +{ + public sealed class Program + { + public static void Main(string[] args) + { + var summaryV2Remote = BenchmarkRunner.Run(); + var summaryV3Remote = BenchmarkRunner.Run(); + var summaryV2Local = BenchmarkRunner.Run(); + var summaryV3Local = BenchmarkRunner.Run(); + } + } +} diff --git a/test/perf/benchmarks/README.md b/test/perf/benchmarks/README.md new file mode 100644 index 000000000..127b164a7 --- /dev/null +++ b/test/perf/benchmarks/README.md @@ -0,0 +1,32 @@ +## Micro Benchmarks + +This folder contains micro benchmarks that test the performance of PowerShellGet. + +### Quick Start + +You can run the benchmarks directly using `dotnet run` in this directory: +1. To run the benchmarks in Interactive Mode, where you will be asked which benchmark(s) to run: + ``` + dotnet run -c Release -f net6.0 + ``` + +2. To list all available benchmarks ([read more](https://github.com/dotnet/performance/blob/main/docs/benchmarkdotnet.md#Listing-the-Benchmarks)): + ``` + dotnet run -c Release -f net6.0 --list [flat/tree] + ``` + +3. To filter the benchmarks using a glob pattern applied to `namespace.typeName.methodName` ([read more](https://github.com/dotnet/performance/blob/main/docs/benchmarkdotnet.md#Filtering-the-Benchmarks)]): + ``` + dotnet run -c Release -f net6.0 --filter *script* --list flat + ``` + +4. To profile the benchmarked code and produce an ETW Trace file ([read more](https://github.com/dotnet/performance/blob/main/docs/benchmarkdotnet.md#Profiling)) + ``` + dotnet run -c Release -f net6.0 --filter *script* --profiler ETW + ``` + +## References + +- [Getting started with BenchmarkDotNet](https://benchmarkdotnet.org/articles/guides/getting-started.html) +- [Micro-benchmark Design Guidelines](https://github.com/dotnet/performance/blob/main/docs/microbenchmark-design-guidelines.md) +- [Adam SITNIK: Powerful benchmarking in .NET](https://www.youtube.com/watch?v=pdcrSG4tOLI&t=351s) \ No newline at end of file diff --git a/test/perf/benchmarks/benchmarks.csproj b/test/perf/benchmarks/benchmarks.csproj new file mode 100644 index 000000000..3ea7e4fe8 --- /dev/null +++ b/test/perf/benchmarks/benchmarks.csproj @@ -0,0 +1,25 @@ + + + net6.0 + Exe + + + AnyCPU + pdbonly + true + true + true + Release + false + + + + + + + + + + + +