Skip to content

Commit 25b3567

Browse files
authored
Benchmark parallelization (#3111)
* add parallel processing benchmarks * introduce RunExperiment and fix warnings in test code * fix benchmarks * proper ProcessorThroughputTest * test additional processors * ProcessorThroughputTest -> ProcessorThroughputBenchmark * add DrawImage to ParallelProcessing benchmark * readonly * Disable BMP tests -- #3112 * revert ImageMagick update * delete CountingUnit * rename field
1 parent d3ca6eb commit 25b3567

File tree

6 files changed

+344
-70
lines changed

6 files changed

+344
-70
lines changed

tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Drawing.Imaging;
77
using System.Runtime.CompilerServices;
88
using System.Runtime.InteropServices;
9+
using System.Runtime.Versioning;
910
using ImageMagick;
1011
using PhotoSauce.MagicScaler;
1112
using SixLabors.ImageSharp.Formats;
@@ -27,6 +28,7 @@ public enum JpegKind
2728
Any = Baseline | Progressive
2829
}
2930

31+
[SupportedOSPlatform("windows")]
3032
public class LoadResizeSaveStressRunner
3133
{
3234
private const int Quality = 75;
@@ -158,7 +160,7 @@ private string OutputPath(string inputPath, [CallerMemberName] string postfix =
158160
this.outputDirectory,
159161
Path.GetFileNameWithoutExtension(inputPath) + "-" + postfix + Path.GetExtension(inputPath));
160162

161-
private (int Width, int Height) ScaledSize(int inWidth, int inHeight, int outSize)
163+
private static (int Width, int Height) ScaledSize(int inWidth, int inHeight, int outSize)
162164
{
163165
int width, height;
164166
if (inWidth > inHeight)
@@ -180,7 +182,7 @@ public void SystemDrawingResize(string input)
180182
using SystemDrawingImage image = SystemDrawingImage.FromFile(input, true);
181183
this.LogImageProcessed(image.Width, image.Height);
182184

183-
(int width, int height) = this.ScaledSize(image.Width, image.Height, this.ThumbnailSize);
185+
(int width, int height) = ScaledSize(image.Width, image.Height, this.ThumbnailSize);
184186
Bitmap resized = new(width, height);
185187
using Graphics graphics = Graphics.FromImage(resized);
186188
using ImageAttributes attributes = new();
@@ -282,7 +284,7 @@ public void SkiaCanvasResize(string input)
282284
{
283285
using SKBitmap original = SKBitmap.Decode(input);
284286
this.LogImageProcessed(original.Width, original.Height);
285-
(int width, int height) = this.ScaledSize(original.Width, original.Height, this.ThumbnailSize);
287+
(int width, int height) = ScaledSize(original.Width, original.Height, this.ThumbnailSize);
286288
using SKSurface surface = SKSurface.Create(new SKImageInfo(width, height, original.ColorType, original.AlphaType));
287289
using SKPaint paint = new() { FilterQuality = SKFilterQuality.High };
288290
SKCanvas canvas = surface.Canvas;
@@ -300,7 +302,7 @@ public void SkiaBitmapResize(string input)
300302
{
301303
using SKBitmap original = SKBitmap.Decode(input);
302304
this.LogImageProcessed(original.Width, original.Height);
303-
(int width, int height) = this.ScaledSize(original.Width, original.Height, this.ThumbnailSize);
305+
(int width, int height) = ScaledSize(original.Width, original.Height, this.ThumbnailSize);
304306
using SKBitmap resized = original.Resize(new SKImageInfo(width, height), SKFilterQuality.High);
305307
if (resized == null)
306308
{
@@ -319,7 +321,7 @@ public void SkiaBitmapDecodeToTargetSize(string input)
319321

320322
SKImageInfo info = codec.Info;
321323
this.LogImageProcessed(info.Width, info.Height);
322-
(int width, int height) = this.ScaledSize(info.Width, info.Height, this.ThumbnailSize);
324+
(int width, int height) = ScaledSize(info.Width, info.Height, this.ThumbnailSize);
323325
SKSizeI supportedScale = codec.GetScaledDimensions((float)width / info.Width);
324326

325327
using SKBitmap original = SKBitmap.Decode(codec, new SKImageInfo(supportedScale.Width, supportedScale.Height));
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Six Labors Split License.
3+
4+
using BenchmarkDotNet.Attributes;
5+
using SixLabors.ImageSharp.PixelFormats;
6+
using SixLabors.ImageSharp.Processing;
7+
using SixLabors.ImageSharp.Tests;
8+
9+
namespace SixLabors.ImageSharp.Benchmarks;
10+
11+
public class ParallelProcessing
12+
{
13+
private Image<Rgba32> image;
14+
private Image<Rgba32> foreground;
15+
private Configuration configuration;
16+
17+
public static IEnumerable<int> MaxDegreeOfParallelismValues()
18+
{
19+
int processorCount = Environment.ProcessorCount;
20+
for (int p = 1; p <= processorCount; p *= 2)
21+
{
22+
yield return p;
23+
}
24+
25+
if ((processorCount & (processorCount - 1)) != 0)
26+
{
27+
yield return processorCount;
28+
}
29+
}
30+
31+
[ParamsSource(nameof(MaxDegreeOfParallelismValues))]
32+
public int MaxDegreeOfParallelism { get; set; }
33+
34+
[GlobalSetup]
35+
public void Setup()
36+
{
37+
this.image = new Image<Rgba32>(2048, 2048);
38+
this.foreground = new Image<Rgba32>(2048, 2048);
39+
this.configuration = Configuration.Default.Clone();
40+
this.configuration.MaxDegreeOfParallelism = this.MaxDegreeOfParallelism;
41+
}
42+
43+
[Benchmark]
44+
public void DetectEdges() => this.image.Mutate(this.configuration, x => x.DetectEdges());
45+
46+
[Benchmark]
47+
public void DrawImage() => this.image.Mutate(this.configuration, x => x.DrawImage(this.foreground, 0.5f));
48+
49+
[Benchmark]
50+
public void Crop()
51+
{
52+
Rectangle bounds = this.image.Bounds;
53+
bounds = new Rectangle(1, 1, bounds.Width - 2, bounds.Height - 2);
54+
this.image
55+
.Clone(this.configuration, x => x.Crop(bounds))
56+
.Dispose();
57+
}
58+
59+
[GlobalCleanup]
60+
public void Cleanup()
61+
{
62+
this.image.Dispose();
63+
this.foreground.Dispose();
64+
}
65+
}

tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<Prefer32Bit>false</Prefer32Bit>
99
<RootNamespace>SixLabors.ImageSharp.Tests.ProfilingSandbox</RootNamespace>
1010
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
11-
<StartupObject>SixLabors.ImageSharp.Tests.ProfilingSandbox.Program</StartupObject>
1211
<!--Used to hide test project from dotnet test-->
1312
<IsTestProject>false</IsTestProject>
1413
<EnsureNETCoreAppRuntime>false</EnsureNETCoreAppRuntime>

tests/ImageSharp.Tests.ProfilingSandbox/LoadResizeSaveParallelMemoryStress.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Diagnostics;
55
using System.Globalization;
6+
using System.Runtime.Versioning;
67
using System.Text;
78
using CommandLine;
89
using CommandLine.Text;
@@ -13,7 +14,8 @@
1314
namespace SixLabors.ImageSharp.Tests.ProfilingSandbox;
1415

1516
// See ImageSharp.Benchmarks/LoadResizeSave/README.md
16-
internal class LoadResizeSaveParallelMemoryStress
17+
[SupportedOSPlatform("windows")]
18+
internal sealed class LoadResizeSaveParallelMemoryStress
1719
{
1820
private LoadResizeSaveParallelMemoryStress()
1921
{
@@ -206,14 +208,15 @@ public string GetMarkdown()
206208
StringBuilder bld = new();
207209
bld.AppendLine($"| {nameof(this.TotalSeconds)} | {nameof(this.MegapixelsPerSec)} | {nameof(this.MegapixelsPerSecPerCpu)} |");
208210
bld.AppendLine(
211+
CultureInfo.InvariantCulture,
209212
$"| {L(nameof(this.TotalSeconds))} | {L(nameof(this.MegapixelsPerSec))} | {L(nameof(this.MegapixelsPerSecPerCpu))} |");
210213

211214
bld.Append("| ");
212-
bld.AppendFormat(F(nameof(this.TotalSeconds)), this.TotalSeconds);
215+
bld.AppendFormat(CultureInfo.InvariantCulture, F(nameof(this.TotalSeconds)), this.TotalSeconds);
213216
bld.Append(" | ");
214-
bld.AppendFormat(F(nameof(this.MegapixelsPerSec)), this.MegapixelsPerSec);
217+
bld.AppendFormat(CultureInfo.InvariantCulture, F(nameof(this.MegapixelsPerSec)), this.MegapixelsPerSec);
215218
bld.Append(" | ");
216-
bld.AppendFormat(F(nameof(this.MegapixelsPerSecPerCpu)), this.MegapixelsPerSecPerCpu);
219+
bld.AppendFormat(CultureInfo.InvariantCulture, F(nameof(this.MegapixelsPerSecPerCpu)), this.MegapixelsPerSecPerCpu);
217220
bld.AppendLine(" |");
218221

219222
return bld.ToString();
@@ -223,7 +226,7 @@ public string GetMarkdown()
223226
}
224227
}
225228

226-
private class CommandLineOptions
229+
private sealed class CommandLineOptions
227230
{
228231
[Option('a', "async-imagesharp", Required = false, Default = false, HelpText = "Async ImageSharp without benchmark switching")]
229232
public bool AsyncImageSharp { get; set; }

0 commit comments

Comments
 (0)