|
|
|
@ -8,33 +8,18 @@ using System.IO; |
|
|
|
using System.Linq; |
|
|
|
using System.Numerics; |
|
|
|
using BenchmarkDotNet.Attributes; |
|
|
|
using BenchmarkDotNet.Configs; |
|
|
|
using BenchmarkDotNet.Diagnosers; |
|
|
|
using BenchmarkDotNet.Environments; |
|
|
|
using BenchmarkDotNet.Jobs; |
|
|
|
using SixLabors.ImageSharp.PixelFormats; |
|
|
|
using SixLabors.ImageSharp.Tests; |
|
|
|
using CoreImage = SixLabors.ImageSharp.Image; |
|
|
|
|
|
|
|
namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
{ |
|
|
|
public abstract class MultiImageBenchmarkBase |
|
|
|
{ |
|
|
|
public class Config : ManualConfig |
|
|
|
{ |
|
|
|
public Config() => this.AddDiagnoser(MemoryDiagnoser.Default); |
|
|
|
|
|
|
|
public class ShortClr : Benchmarks.Config |
|
|
|
{ |
|
|
|
public ShortClr() => this.AddJob(Job.Default.WithRuntime(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(1).WithIterationCount(2)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected Dictionary<string, byte[]> FileNamesToBytes { get; set; } = new Dictionary<string, byte[]>(); |
|
|
|
|
|
|
|
protected Dictionary<string, Image<Rgba32>> FileNamesToImageSharpImages { get; set; } = new Dictionary<string, Image<Rgba32>>(); |
|
|
|
|
|
|
|
protected Dictionary<string, Bitmap> FileNamesToSystemDrawingImages { get; set; } = new Dictionary<string, System.Drawing.Bitmap>(); |
|
|
|
protected Dictionary<string, Bitmap> FileNamesToSystemDrawingImages { get; set; } = new Dictionary<string, Bitmap>(); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// The values of this enum separate input files into categories.
|
|
|
|
@ -72,7 +57,8 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
/// <summary>
|
|
|
|
/// Gets folders containing files OR files to be processed by the benchmark.
|
|
|
|
/// </summary>
|
|
|
|
protected IEnumerable<string> AllFoldersOrFiles => this.InputImageSubfoldersOrFiles.Select(f => Path.Combine(this.BaseFolder, f)); |
|
|
|
protected IEnumerable<string> AllFoldersOrFiles |
|
|
|
=> this.InputImageSubfoldersOrFiles.Select(f => Path.Combine(this.BaseFolder, f)); |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the large image threshold.
|
|
|
|
@ -83,19 +69,13 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
protected IEnumerable<KeyValuePair<string, T>> EnumeratePairsByBenchmarkSettings<T>( |
|
|
|
Dictionary<string, T> input, |
|
|
|
Predicate<T> checkIfSmall) |
|
|
|
{ |
|
|
|
switch (this.InputCategory) |
|
|
|
=> this.InputCategory switch |
|
|
|
{ |
|
|
|
case InputImageCategory.AllImages: |
|
|
|
return input; |
|
|
|
case InputImageCategory.SmallImagesOnly: |
|
|
|
return input.Where(kv => checkIfSmall(kv.Value)); |
|
|
|
case InputImageCategory.LargeImagesOnly: |
|
|
|
return input.Where(kv => !checkIfSmall(kv.Value)); |
|
|
|
default: |
|
|
|
throw new ArgumentOutOfRangeException(); |
|
|
|
} |
|
|
|
} |
|
|
|
InputImageCategory.AllImages => input, |
|
|
|
InputImageCategory.SmallImagesOnly => input.Where(kv => checkIfSmall(kv.Value)), |
|
|
|
InputImageCategory.LargeImagesOnly => input.Where(kv => !checkIfSmall(kv.Value)), |
|
|
|
_ => throw new ArgumentOutOfRangeException(), |
|
|
|
}; |
|
|
|
|
|
|
|
protected IEnumerable<KeyValuePair<string, byte[]>> FileNames2Bytes |
|
|
|
=> |
|
|
|
@ -150,17 +130,15 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
{ |
|
|
|
foreach (KeyValuePair<string, byte[]> kv in this.FileNames2Bytes) |
|
|
|
{ |
|
|
|
using (var memoryStream = new MemoryStream(kv.Value)) |
|
|
|
using var memoryStream = new MemoryStream(kv.Value); |
|
|
|
try |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
object obj = operation(memoryStream); |
|
|
|
(obj as IDisposable)?.Dispose(); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
Console.WriteLine($"Operation on {kv.Key} failed with {ex.Message}"); |
|
|
|
} |
|
|
|
object obj = operation(memoryStream); |
|
|
|
(obj as IDisposable)?.Dispose(); |
|
|
|
} |
|
|
|
catch (Exception ex) |
|
|
|
{ |
|
|
|
Console.WriteLine($"Operation on {kv.Key} failed with {ex.Message}"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -178,7 +156,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
|
|
|
|
using (var ms1 = new MemoryStream(bytes)) |
|
|
|
{ |
|
|
|
this.FileNamesToImageSharpImages[fn] = CoreImage.Load<Rgba32>(ms1); |
|
|
|
this.FileNamesToImageSharpImages[fn] = Image.Load<Rgba32>(ms1); |
|
|
|
} |
|
|
|
|
|
|
|
this.FileNamesToSystemDrawingImages[fn] = new Bitmap(new MemoryStream(bytes)); |
|
|
|
@ -191,7 +169,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
this.FileNamesToImageSharpImages, |
|
|
|
img => img.Width * img.Height < this.LargeImageThresholdInPixels); |
|
|
|
|
|
|
|
protected IEnumerable<KeyValuePair<string, System.Drawing.Bitmap>> FileNames2SystemDrawingImages |
|
|
|
protected IEnumerable<KeyValuePair<string, Bitmap>> FileNames2SystemDrawingImages |
|
|
|
=> |
|
|
|
this.EnumeratePairsByBenchmarkSettings( |
|
|
|
this.FileNamesToSystemDrawingImages, |
|
|
|
@ -217,22 +195,20 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
|
|
|
|
protected void ForEachImageSharpImage(Func<Image<Rgba32>, MemoryStream, object> operation) |
|
|
|
{ |
|
|
|
using (var workStream = new MemoryStream()) |
|
|
|
{ |
|
|
|
this.ForEachImageSharpImage( |
|
|
|
img => |
|
|
|
{ |
|
|
|
// ReSharper disable AccessToDisposedClosure
|
|
|
|
object result = operation(img, workStream); |
|
|
|
workStream.Seek(0, SeekOrigin.Begin); |
|
|
|
|
|
|
|
// ReSharper restore AccessToDisposedClosure
|
|
|
|
return result; |
|
|
|
}); |
|
|
|
} |
|
|
|
using var workStream = new MemoryStream(); |
|
|
|
this.ForEachImageSharpImage( |
|
|
|
img => |
|
|
|
{ |
|
|
|
// ReSharper disable AccessToDisposedClosure
|
|
|
|
object result = operation(img, workStream); |
|
|
|
workStream.Seek(0, SeekOrigin.Begin); |
|
|
|
|
|
|
|
// ReSharper restore AccessToDisposedClosure
|
|
|
|
return result; |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
protected void ForEachSystemDrawingImage(Func<System.Drawing.Bitmap, object> operation) |
|
|
|
protected void ForEachSystemDrawingImage(Func<Bitmap, object> operation) |
|
|
|
{ |
|
|
|
foreach (KeyValuePair<string, Bitmap> kv in this.FileNames2SystemDrawingImages) |
|
|
|
{ |
|
|
|
@ -248,21 +224,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
protected void ForEachSystemDrawingImage(Func<System.Drawing.Bitmap, MemoryStream, object> operation) |
|
|
|
protected void ForEachSystemDrawingImage(Func<Bitmap, MemoryStream, object> operation) |
|
|
|
{ |
|
|
|
using (var workStream = new MemoryStream()) |
|
|
|
{ |
|
|
|
this.ForEachSystemDrawingImage( |
|
|
|
img => |
|
|
|
{ |
|
|
|
// ReSharper disable AccessToDisposedClosure
|
|
|
|
object result = operation(img, workStream); |
|
|
|
workStream.Seek(0, SeekOrigin.Begin); |
|
|
|
|
|
|
|
// ReSharper restore AccessToDisposedClosure
|
|
|
|
return result; |
|
|
|
}); |
|
|
|
} |
|
|
|
using var workStream = new MemoryStream(); |
|
|
|
this.ForEachSystemDrawingImage( |
|
|
|
img => |
|
|
|
{ |
|
|
|
// ReSharper disable AccessToDisposedClosure
|
|
|
|
object result = operation(img, workStream); |
|
|
|
workStream.Seek(0, SeekOrigin.Begin); |
|
|
|
|
|
|
|
// ReSharper restore AccessToDisposedClosure
|
|
|
|
return result; |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|