mirror of https://github.com/SixLabors/ImageSharp
7 changed files with 140 additions and 38 deletions
@ -0,0 +1,88 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Six Labors Split License.
|
||||
|
|
||||
|
using CommandLine; |
||||
|
using CommandLine.Text; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.ProfilingSandbox; |
||||
|
|
||||
|
public partial class ParallelProcessingStress |
||||
|
{ |
||||
|
public static void RunExperiment(string[] args) |
||||
|
{ |
||||
|
ExperimentOptions options = null; |
||||
|
using Parser parser = new(settings => settings.CaseInsensitiveEnumValues = true); |
||||
|
ParserResult<ExperimentOptions> result = parser.ParseArguments<ExperimentOptions>(args).WithParsed(o => options = o); |
||||
|
if (options == null) |
||||
|
{ |
||||
|
Console.WriteLine(HelpText.RenderUsageText(result)); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
RunExperiment(options.Method, options.Seconds, options.IterationCount); |
||||
|
} |
||||
|
|
||||
|
public static void RunExperiment(Method method, int seconds = 5, int times = 5) |
||||
|
{ |
||||
|
// Warmup
|
||||
|
Console.WriteLine("Warming up..."); |
||||
|
CommandLineOptions warmupOptions = new() { Method = method, Seconds = 1 }; |
||||
|
warmupOptions.Normalize(); |
||||
|
new ParallelProcessingStress(warmupOptions).Run(); |
||||
|
|
||||
|
// Outer loop: run inner loop for each parallelism level
|
||||
|
List<(int Parallelism, double AvgMpxPerSecPerCpu)> results = new(); |
||||
|
|
||||
|
foreach (int parallelism in ParallelismLevels()) |
||||
|
{ |
||||
|
Console.WriteLine($"\nRunning {method} with ProcessorParallelism={parallelism} ({times}x {seconds}s)..."); |
||||
|
|
||||
|
double totalMpxPerSecPerCpu = 0; |
||||
|
for (int i = 0; i < times; i++) |
||||
|
{ |
||||
|
CommandLineOptions options = new() { Method = method, ProcessorParallelism = parallelism, Seconds = seconds }; |
||||
|
options.Normalize(); |
||||
|
Stats stats = new ParallelProcessingStress(options).Run(); |
||||
|
totalMpxPerSecPerCpu += stats.MegapixelsPerSecPerCpu; |
||||
|
} |
||||
|
|
||||
|
results.Add((parallelism, totalMpxPerSecPerCpu / times)); |
||||
|
} |
||||
|
|
||||
|
// Print results as markdown table
|
||||
|
Console.WriteLine(); |
||||
|
Console.WriteLine("| ProcessorParallelism | MegapixelsPerSecPerCpu |"); |
||||
|
Console.WriteLine("|---------------------:|-----------------------:|"); |
||||
|
foreach ((int parallelism, double avg) in results) |
||||
|
{ |
||||
|
Console.WriteLine($"| {parallelism,20} | {avg,22:f3} |"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private sealed class ExperimentOptions |
||||
|
{ |
||||
|
[Option('m', "method", Required = false, Default = Method.Edges, HelpText = "The stress test method to run (Edges, Crop)")] |
||||
|
public Method Method { get; set; } = Method.Edges; |
||||
|
|
||||
|
[Option('s', "seconds", Required = false, Default = 5, HelpText = "Duration of each run in seconds")] |
||||
|
public int Seconds { get; set; } = 5; |
||||
|
|
||||
|
[Option('i', "iterations", Required = false, Default = 5, HelpText = "Number of runs per parallelism level")] |
||||
|
public int IterationCount { get; set; } = 5; |
||||
|
} |
||||
|
|
||||
|
private static IEnumerable<int> ParallelismLevels() |
||||
|
{ |
||||
|
int cpuCount = Environment.ProcessorCount; |
||||
|
for (int p = 1; p <= cpuCount; p *= 2) |
||||
|
{ |
||||
|
yield return p; |
||||
|
} |
||||
|
|
||||
|
// When cpuCount is not a power of two, append it as the final step
|
||||
|
if ((cpuCount & (cpuCount - 1)) != 0) |
||||
|
{ |
||||
|
yield return cpuCount; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue