diff --git a/src/chocolatey.benchmark/App.config b/src/chocolatey.benchmark/App.config
new file mode 100644
index 0000000000..f8e1309c75
--- /dev/null
+++ b/src/chocolatey.benchmark/App.config
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/chocolatey.benchmark/BenchmarkConfig.cs b/src/chocolatey.benchmark/BenchmarkConfig.cs
new file mode 100644
index 0000000000..7e9f243a7c
--- /dev/null
+++ b/src/chocolatey.benchmark/BenchmarkConfig.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using BenchmarkDotNet.Analysers;
+using BenchmarkDotNet.Columns;
+using BenchmarkDotNet.Configs;
+using BenchmarkDotNet.Diagnosers;
+using BenchmarkDotNet.Environments;
+using BenchmarkDotNet.Exporters;
+using BenchmarkDotNet.Exporters.Csv;
+using BenchmarkDotNet.Jobs;
+using BenchmarkDotNet.Loggers;
+
+namespace chocolatey.benchmark
+{
+ internal static class BenchmarkConfig
+ {
+ public static IConfig Get()
+ {
+ var config = ManualConfig.CreateEmpty();
+
+ foreach (var platform in new[] { Platform.X64/*, Platform.X86*/ })
+ {
+ config = config.AddJob(Job.Default.WithRuntime(ClrRuntime.Net48).WithPlatform(platform).WithJit(Jit.LegacyJit));
+ }
+
+ return config
+ .AddDiagnoser(MemoryDiagnoser.Default)
+ .AddColumnProvider(DefaultColumnProviders.Instance)
+ .AddLogger(ConsoleLogger.Default)
+ .AddExporter(CsvExporter.Default)
+ .AddExporter(HtmlExporter.Default)
+ .AddExporter(MarkdownExporter.Default)
+ .AddExporter(AsciiDocExporter.Default)
+ .AddAnalyser(GetAnalysers().ToArray());
+ }
+
+ private static IEnumerable GetAnalysers()
+ {
+ yield return EnvironmentAnalyser.Default;
+ yield return OutliersAnalyser.Default;
+ yield return MinIterationTimeAnalyser.Default;
+ yield return MultimodalDistributionAnalyzer.Default;
+ yield return RuntimeErrorAnalyser.Default;
+ yield return ZeroMeasurementAnalyser.Default;
+ yield return BaselineCustomAnalyzer.Default;
+ }
+ }
+}
diff --git a/src/chocolatey.benchmark/ParentProcessBenchmarks.cs b/src/chocolatey.benchmark/ParentProcessBenchmarks.cs
new file mode 100644
index 0000000000..21486b8304
--- /dev/null
+++ b/src/chocolatey.benchmark/ParentProcessBenchmarks.cs
@@ -0,0 +1,69 @@
+using System.Runtime.CompilerServices;
+using BenchmarkDotNet.Attributes;
+using chocolatey.benchmark.helpers;
+using chocolatey.infrastructure.information;
+
+namespace chocolatey.benchmark
+{
+ public class ParentProcessBenchmarks
+ {
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public string GetParentProcessDocumentedPinvoke()
+ {
+ return PinvokeProcessHelper.GetDocumentedParent();
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public string GetParentProcessFilteredDocumentedPinvoke()
+ {
+ return PinvokeProcessHelper.GetDocumentedParentFiltered();
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public string GetParentProcessFilteredManaged()
+ {
+ return ManagedProcessHelper.GetParent();
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public string GetParentProcessFilteredUndocumentedPinvoke()
+ {
+ return PinvokeProcessHelper.GetUndocumentedParentFiltered();
+ }
+
+ [Benchmark(Baseline = true), MethodImpl(MethodImplOptions.NoInlining)]
+ public string GetParentProcessManaged()
+ {
+ return ManagedProcessHelper.GetParent();
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public ProcessTree GetParentProcessTreeDocumentedPinvoke()
+ {
+ return PinvokeProcessHelper.GetDocumentedProcessTree();
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public ProcessTree GetParentProcessTreeManaged()
+ {
+ return ManagedProcessHelper.GetProcessTree();
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public ProcessTree GetParentProcessTreeUndocumentedPinvoke()
+ {
+ return PinvokeProcessHelper.GetUndocumentedProcessTree();
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public string GetParentProcessUndocumentedPinvoke()
+ {
+ return PinvokeProcessHelper.GetUndocumentedParent();
+ }
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ public ProcessTree GetParentProcessTreeImplemented()
+ {
+ return ProcessInformation.GetProcessTree();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/chocolatey.benchmark/ProcessTreeBenchmark.cs b/src/chocolatey.benchmark/ProcessTreeBenchmark.cs
new file mode 100644
index 0000000000..b6264324e7
--- /dev/null
+++ b/src/chocolatey.benchmark/ProcessTreeBenchmark.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using BenchmarkDotNet.Attributes;
+using chocolatey.benchmark.helpers;
+using chocolatey.infrastructure.information;
+
+namespace chocolatey.benchmark
+{
+ public class ProcessTreeBenchmark
+ {
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ [ArgumentsSource(nameof(GetProcessTree))]
+ public string GetFirstFilteredProcessName(ProcessTree tree)
+ {
+ return tree.FirstFilteredProcessName;
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ [ArgumentsSource(nameof(GetProcessTree))]
+ public string GetFirstProcessName(ProcessTree tree)
+ {
+ return tree.FirstProcessName;
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ [ArgumentsSource(nameof(GetProcessTree))]
+ public string GetLastFilteredProcessName(ProcessTree tree)
+ {
+ return tree.LastFilteredProcessName;
+ }
+
+ [Benchmark, MethodImpl(MethodImplOptions.NoInlining)]
+ [ArgumentsSource(nameof(GetProcessTree))]
+ public string GetLastProcessName(ProcessTree tree)
+ {
+ return tree.LastProcessName;
+ }
+
+ [Benchmark(Baseline = true), MethodImpl(MethodImplOptions.NoInlining)]
+ [ArgumentsSource(nameof(GetProcessTree))]
+ public LinkedList GetProcessesList(ProcessTree tree)
+ {
+ return tree.Processes;
+ }
+
+ public IEnumerable