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
+
+
+
+
+
+
+
+
+
+
+
+