Add image processing benchmarks and UI folder open buttons
- Added MaddoShared.Benchmarks project with BenchmarkDotNet for comprehensive image processing performance tests (parallel, chunk, size, stress). - Included helper for generating test images and custom configs to ensure InProcess toolchain for .NET Windows compatibility. - Added cross-platform scripts to run benchmarks easily. - Updated .gitignore for benchmark artifacts and temp files. - Exposed GetFilesToProcessPublic in ImageCreationStuff for testability. - Added file name sanitization in ImageCreatorSharp to prevent IO errors. - Enhanced WinForms UI: added "Open" buttons for source/destination folders, handled folder opening in Explorer, and improved user messaging and layout. - Updated solution file to include new benchmark project.
This commit is contained in:
parent
39b0904a72
commit
c2fd4bf780
17 changed files with 1608 additions and 301 deletions
16
Catalog.sln
16
Catalog.sln
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 18
|
# Visual Studio Version 18
|
||||||
VisualStudioVersion = 18.2.11415.280 d18.0
|
VisualStudioVersion = 18.2.11415.280
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageCatalog 2", "imagecatalog\ImageCatalog 2.csproj", "{3F1E23DB-435E-0590-1EF5-735E898DBA3C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageCatalog 2", "imagecatalog\ImageCatalog 2.csproj", "{3F1E23DB-435E-0590-1EF5-735E898DBA3C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -13,6 +13,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{5F0BEF23
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaddoShared.Tests", "MaddoShared.Tests\MaddoShared.Tests.csproj", "{59952BE8-20B4-4BF2-9367-705F41395265}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaddoShared.Tests", "MaddoShared.Tests\MaddoShared.Tests.csproj", "{59952BE8-20B4-4BF2-9367-705F41395265}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MaddoShared.Benchmarks", "MaddoShared.Benchmarks\MaddoShared.Benchmarks.csproj", "{07499348-8C15-4DCC-8316-4AD121A43C38}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -59,6 +61,18 @@ Global
|
||||||
{59952BE8-20B4-4BF2-9367-705F41395265}.Release|x64.Build.0 = Release|Any CPU
|
{59952BE8-20B4-4BF2-9367-705F41395265}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{59952BE8-20B4-4BF2-9367-705F41395265}.Release|x86.ActiveCfg = Release|Any CPU
|
{59952BE8-20B4-4BF2-9367-705F41395265}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{59952BE8-20B4-4BF2-9367-705F41395265}.Release|x86.Build.0 = Release|Any CPU
|
{59952BE8-20B4-4BF2-9367-705F41395265}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{07499348-8C15-4DCC-8316-4AD121A43C38}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
||||||
25
MaddoShared.Benchmarks/.gitignore
vendored
Normal file
25
MaddoShared.Benchmarks/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# BenchmarkDotNet artifacts
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# Test images generated during benchmarks
|
||||||
|
TestImages/
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# Results and logs
|
||||||
|
*.log
|
||||||
|
*.html
|
||||||
|
*.csv
|
||||||
|
results/
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
91
MaddoShared.Benchmarks/BenchmarkConfig.cs
Normal file
91
MaddoShared.Benchmarks/BenchmarkConfig.cs
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
using BenchmarkDotNet.Columns;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Diagnosers;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
using BenchmarkDotNet.Exporters;
|
||||||
|
using BenchmarkDotNet.Exporters.Csv;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Loggers;
|
||||||
|
using BenchmarkDotNet.Toolchains.InProcess.Emit;
|
||||||
|
|
||||||
|
namespace MaddoShared.Benchmarks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// InProcess configuration for benchmarks requiring Windows-specific APIs
|
||||||
|
/// This avoids the net10.0-windows vs net10.0 compatibility issue
|
||||||
|
/// </summary>
|
||||||
|
public class InProcessConfig : ManualConfig
|
||||||
|
{
|
||||||
|
public InProcessConfig()
|
||||||
|
{
|
||||||
|
AddLogger(ConsoleLogger.Default);
|
||||||
|
AddExporter(HtmlExporter.Default);
|
||||||
|
AddExporter(MarkdownExporter.GitHub);
|
||||||
|
AddExporter(CsvExporter.Default);
|
||||||
|
AddDiagnoser(MemoryDiagnoser.Default);
|
||||||
|
|
||||||
|
// Add job with InProcess toolchain
|
||||||
|
AddJob(Job.Default
|
||||||
|
.WithToolchain(InProcessEmitToolchain.Instance)
|
||||||
|
.WithWarmupCount(1)
|
||||||
|
.WithIterationCount(3));
|
||||||
|
|
||||||
|
// Configuration options
|
||||||
|
WithOptions(ConfigOptions.DisableOptimizationsValidator);
|
||||||
|
WithOptions(ConfigOptions.KeepBenchmarkFiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Custom configuration for image processing benchmarks
|
||||||
|
/// Uses InProcess toolchain to avoid net10.0-windows compatibility issues
|
||||||
|
/// </summary>
|
||||||
|
public class BenchmarkConfig : ManualConfig
|
||||||
|
{
|
||||||
|
public BenchmarkConfig()
|
||||||
|
{
|
||||||
|
// Add console logger
|
||||||
|
AddLogger(ConsoleLogger.Default);
|
||||||
|
|
||||||
|
// Add exporters for different formats
|
||||||
|
AddExporter(HtmlExporter.Default);
|
||||||
|
AddExporter(MarkdownExporter.GitHub);
|
||||||
|
AddExporter(CsvExporter.Default);
|
||||||
|
AddExporter(RPlotExporter.Default);
|
||||||
|
|
||||||
|
// Add diagnosers
|
||||||
|
AddDiagnoser(MemoryDiagnoser.Default);
|
||||||
|
AddDiagnoser(ThreadingDiagnoser.Default);
|
||||||
|
|
||||||
|
// Add columns
|
||||||
|
AddColumn(StatisticColumn.Mean);
|
||||||
|
AddColumn(StatisticColumn.StdDev);
|
||||||
|
AddColumn(StatisticColumn.Error);
|
||||||
|
AddColumn(StatisticColumn.Min);
|
||||||
|
AddColumn(StatisticColumn.Max);
|
||||||
|
AddColumn(StatisticColumn.Median);
|
||||||
|
AddColumn(BaselineRatioColumn.RatioMean);
|
||||||
|
|
||||||
|
// Customize jobs with InProcess toolchain for Windows compatibility
|
||||||
|
AddJob(Job.Default
|
||||||
|
.WithToolchain(InProcessEmitToolchain.Instance)
|
||||||
|
.WithWarmupCount(1)
|
||||||
|
.WithIterationCount(3)
|
||||||
|
.WithId("Quick"));
|
||||||
|
|
||||||
|
AddJob(Job.Default
|
||||||
|
.WithToolchain(InProcessEmitToolchain.Instance)
|
||||||
|
.WithWarmupCount(2)
|
||||||
|
.WithIterationCount(5)
|
||||||
|
.WithId("Standard"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fast configuration for development and quick tests
|
||||||
|
/// </summary>
|
||||||
|
public static IConfig Fast => new ManualConfig()
|
||||||
|
.AddLogger(ConsoleLogger.Default)
|
||||||
|
.AddExporter(MarkdownExporter.GitHub)
|
||||||
|
.AddDiagnoser(MemoryDiagnoser.Default)
|
||||||
|
.AddJob(Job.Dry.WithToolchain(InProcessEmitToolchain.Instance)); // Very fast, but less accurate
|
||||||
|
}
|
||||||
130
MaddoShared.Benchmarks/ChunkSizeBenchmarks.cs
Normal file
130
MaddoShared.Benchmarks/ChunkSizeBenchmarks.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Toolchains.InProcess.Emit;
|
||||||
|
using MaddoShared.Benchmarks.Helpers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace MaddoShared.Benchmarks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Benchmarks focused on different chunk sizes for parallel processing
|
||||||
|
/// </summary>
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
[Config(typeof(InProcessConfig))]
|
||||||
|
public class ChunkSizeBenchmarks
|
||||||
|
{
|
||||||
|
private string _sourceDirectory;
|
||||||
|
private string _destinationDirectory;
|
||||||
|
private ImageCreationStuff _imageCreationStuff;
|
||||||
|
private PicSettings _picSettings;
|
||||||
|
|
||||||
|
[Params(100)]
|
||||||
|
public int ImageCount { get; set; }
|
||||||
|
|
||||||
|
[Params(0, 5, 10, 20, 50)]
|
||||||
|
public int ChunkSize { get; set; }
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
var tempBase = Path.Combine(Path.GetTempPath(), "ChunkBenchmarks", Guid.NewGuid().ToString());
|
||||||
|
_sourceDirectory = Path.Combine(tempBase, "Source");
|
||||||
|
_destinationDirectory = Path.Combine(tempBase, "Destination");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(_sourceDirectory);
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
|
||||||
|
Console.WriteLine($"Generating {ImageCount} test images for chunk size testing...");
|
||||||
|
TestImageGenerator.GenerateTestImages(_sourceDirectory, ImageCount, width: 2000, height: 1500);
|
||||||
|
|
||||||
|
var loggerFactory = LoggerFactory.Create(builder =>
|
||||||
|
{
|
||||||
|
builder.SetMinimumLevel(LogLevel.Warning);
|
||||||
|
});
|
||||||
|
|
||||||
|
var logger = loggerFactory.CreateLogger<ImageCreationStuff>();
|
||||||
|
var imageCreatorLogger = loggerFactory.CreateLogger<ImageCreatorSharp>();
|
||||||
|
|
||||||
|
_picSettings = new PicSettings
|
||||||
|
{
|
||||||
|
DirectorySorgente = _sourceDirectory,
|
||||||
|
DirectoryDestinazione = _destinationDirectory,
|
||||||
|
DimStandard = 800,
|
||||||
|
DimStandardMiniatura = 200,
|
||||||
|
LarghezzaBig = 1024,
|
||||||
|
AltezzaBig = 768,
|
||||||
|
LarghezzaSmall = 200,
|
||||||
|
AltezzaSmall = 150,
|
||||||
|
CreaMiniature = true,
|
||||||
|
AggiungiScritteMiniature = false,
|
||||||
|
UsaForzaJpg = true,
|
||||||
|
UsaRotazioneAutomatica = true,
|
||||||
|
LogoAggiungi = false,
|
||||||
|
FotoGrandeDimOrigina = false,
|
||||||
|
TestoNome = false,
|
||||||
|
NomeData = false,
|
||||||
|
Suffisso = "_small",
|
||||||
|
Margine = 10,
|
||||||
|
Trasparenza = 100
|
||||||
|
};
|
||||||
|
|
||||||
|
var imageCreatorService = new ImageCreatorSharp(_picSettings, imageCreatorLogger);
|
||||||
|
_imageCreationStuff = new ImageCreationStuff(logger, _picSettings, imageCreatorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GlobalCleanup]
|
||||||
|
public void Cleanup()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tempBase = Path.GetDirectoryName(_sourceDirectory);
|
||||||
|
if (Directory.Exists(tempBase))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempBase, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Cleanup error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IterationSetup]
|
||||||
|
public void IterationSetup()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(_destinationDirectory))
|
||||||
|
{
|
||||||
|
Directory.Delete(_destinationDirectory, recursive: true);
|
||||||
|
}
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public async Task ProcessWithVariableChunkSize()
|
||||||
|
{
|
||||||
|
var options = new ImageCreationStuff.Options
|
||||||
|
{
|
||||||
|
SourcePath = _sourceDirectory,
|
||||||
|
DestinationPath = _destinationDirectory,
|
||||||
|
MaxThreads = Environment.ProcessorCount,
|
||||||
|
ChunksSize = ChunkSize,
|
||||||
|
LinearExecution = false,
|
||||||
|
AggiornaSottodirectory = false,
|
||||||
|
CreaSottocartelle = false,
|
||||||
|
FilePerCartella = 100,
|
||||||
|
SuffissoCartelle = "",
|
||||||
|
CifreContatore = 4,
|
||||||
|
NumerazioneType = NumerazioneType.Progressiva
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = new ConcurrentBag<string>();
|
||||||
|
await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
107
MaddoShared.Benchmarks/Helpers/TestImageGenerator.cs
Normal file
107
MaddoShared.Benchmarks/Helpers/TestImageGenerator.cs
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace MaddoShared.Benchmarks.Helpers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper class to generate test images for benchmarking
|
||||||
|
/// </summary>
|
||||||
|
[SuppressMessage("Interoperability", "CA1416:Validate platform compatibility")]
|
||||||
|
public static class TestImageGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a set of test JPEG images in the specified directory
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="outputDirectory">Directory where images will be created</param>
|
||||||
|
/// <param name="imageCount">Number of images to generate</param>
|
||||||
|
/// <param name="width">Width of each image</param>
|
||||||
|
/// <param name="height">Height of each image</param>
|
||||||
|
/// <param name="includeSubfolders">Whether to create images in subfolders</param>
|
||||||
|
public static void GenerateTestImages(
|
||||||
|
string outputDirectory,
|
||||||
|
int imageCount,
|
||||||
|
int width = 4000,
|
||||||
|
int height = 3000,
|
||||||
|
bool includeSubfolders = false)
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(outputDirectory);
|
||||||
|
|
||||||
|
var random = new Random(42); // Fixed seed for reproducibility
|
||||||
|
|
||||||
|
for (int i = 0; i < imageCount; i++)
|
||||||
|
{
|
||||||
|
var targetDir = outputDirectory;
|
||||||
|
|
||||||
|
if (includeSubfolders && i % 10 == 0)
|
||||||
|
{
|
||||||
|
targetDir = Path.Combine(outputDirectory, $"Subfolder_{i / 10}");
|
||||||
|
Directory.CreateDirectory(targetDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
var filePath = Path.Combine(targetDir, $"test_image_{i:D5}.jpg");
|
||||||
|
|
||||||
|
// Skip if already exists
|
||||||
|
if (File.Exists(filePath))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
using var bitmap = new Bitmap(width, height);
|
||||||
|
using var graphics = Graphics.FromImage(bitmap);
|
||||||
|
|
||||||
|
// Fill with a random color background
|
||||||
|
var bgColor = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256));
|
||||||
|
graphics.Clear(bgColor);
|
||||||
|
|
||||||
|
// Draw some random shapes to make it more realistic
|
||||||
|
for (int j = 0; j < 20; j++)
|
||||||
|
{
|
||||||
|
var color = Color.FromArgb(random.Next(256), random.Next(256), random.Next(256));
|
||||||
|
var brush = new SolidBrush(color);
|
||||||
|
var x = random.Next(width);
|
||||||
|
var y = random.Next(height);
|
||||||
|
var w = random.Next(200, 800);
|
||||||
|
var h = random.Next(200, 800);
|
||||||
|
graphics.FillEllipse(brush, x, y, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add some text
|
||||||
|
using var font = new Font("Arial", 48, FontStyle.Bold);
|
||||||
|
var text = $"Test Image {i}";
|
||||||
|
var textBrush = new SolidBrush(Color.White);
|
||||||
|
graphics.DrawString(text, font, textBrush, new PointF(100, 100));
|
||||||
|
|
||||||
|
// Save as JPEG with standard quality
|
||||||
|
var encoder = GetEncoder(ImageFormat.Jpeg);
|
||||||
|
var encoderParameters = new EncoderParameters(1);
|
||||||
|
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 85L);
|
||||||
|
|
||||||
|
bitmap.Save(filePath, encoder, encoderParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cleans up generated test images
|
||||||
|
/// </summary>
|
||||||
|
public static void CleanupTestImages(string directory)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(directory))
|
||||||
|
{
|
||||||
|
Directory.Delete(directory, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImageCodecInfo GetEncoder(ImageFormat format)
|
||||||
|
{
|
||||||
|
var codecs = ImageCodecInfo.GetImageEncoders();
|
||||||
|
foreach (var codec in codecs)
|
||||||
|
{
|
||||||
|
if (codec.FormatID == format.Guid)
|
||||||
|
{
|
||||||
|
return codec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
182
MaddoShared.Benchmarks/ImageProcessingBenchmarks.cs
Normal file
182
MaddoShared.Benchmarks/ImageProcessingBenchmarks.cs
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Toolchains.InProcess.Emit;
|
||||||
|
using MaddoShared.Benchmarks.Helpers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace MaddoShared.Benchmarks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Benchmarks for image processing with various configurations
|
||||||
|
/// </summary>
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
[Config(typeof(InProcessConfig))]
|
||||||
|
public class ImageProcessingBenchmarks
|
||||||
|
{
|
||||||
|
private string _sourceDirectory;
|
||||||
|
private string _destinationDirectory;
|
||||||
|
private ImageCreationStuff _imageCreationStuff;
|
||||||
|
private PicSettings _picSettings;
|
||||||
|
private ILogger<ImageCreationStuff> _logger;
|
||||||
|
private ILogger<ImageCreatorSharp> _imageCreatorLogger;
|
||||||
|
|
||||||
|
[Params(10, 50, 100)]
|
||||||
|
public int ImageCount { get; set; }
|
||||||
|
|
||||||
|
[Params(1, 2, 4, 8)]
|
||||||
|
public int MaxThreads { get; set; }
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
// Create temp directories
|
||||||
|
var tempBase = Path.Combine(Path.GetTempPath(), "ImageBenchmarks", Guid.NewGuid().ToString());
|
||||||
|
_sourceDirectory = Path.Combine(tempBase, "Source");
|
||||||
|
_destinationDirectory = Path.Combine(tempBase, "Destination");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(_sourceDirectory);
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
|
||||||
|
// Generate test images
|
||||||
|
Console.WriteLine($"Generating {ImageCount} test images...");
|
||||||
|
TestImageGenerator.GenerateTestImages(_sourceDirectory, ImageCount, width: 2000, height: 1500);
|
||||||
|
|
||||||
|
// Setup logging
|
||||||
|
var loggerFactory = LoggerFactory.Create(builder =>
|
||||||
|
{
|
||||||
|
builder.SetMinimumLevel(LogLevel.Warning); // Reduce noise during benchmarks
|
||||||
|
});
|
||||||
|
|
||||||
|
_logger = loggerFactory.CreateLogger<ImageCreationStuff>();
|
||||||
|
_imageCreatorLogger = loggerFactory.CreateLogger<ImageCreatorSharp>();
|
||||||
|
|
||||||
|
// Setup PicSettings with default values
|
||||||
|
_picSettings = new PicSettings
|
||||||
|
{
|
||||||
|
DirectorySorgente = _sourceDirectory,
|
||||||
|
DirectoryDestinazione = _destinationDirectory,
|
||||||
|
DimStandard = 800,
|
||||||
|
DimStandardMiniatura = 200,
|
||||||
|
LarghezzaBig = 1024,
|
||||||
|
AltezzaBig = 768,
|
||||||
|
LarghezzaSmall = 200,
|
||||||
|
AltezzaSmall = 150,
|
||||||
|
CreaMiniature = true,
|
||||||
|
AggiungiScritteMiniature = false,
|
||||||
|
UsaForzaJpg = true,
|
||||||
|
UsaRotazioneAutomatica = true,
|
||||||
|
LogoAggiungi = false,
|
||||||
|
FotoGrandeDimOrigina = false,
|
||||||
|
TestoNome = false,
|
||||||
|
NomeData = false,
|
||||||
|
Suffisso = "_small",
|
||||||
|
Margine = 10,
|
||||||
|
Trasparenza = 100
|
||||||
|
};
|
||||||
|
|
||||||
|
var imageCreatorService = new ImageCreatorSharp(_picSettings, _imageCreatorLogger);
|
||||||
|
_imageCreationStuff = new ImageCreationStuff(_logger, _picSettings, imageCreatorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
[GlobalCleanup]
|
||||||
|
public void Cleanup()
|
||||||
|
{
|
||||||
|
// Clean up temp directories
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tempBase = Path.GetDirectoryName(_sourceDirectory);
|
||||||
|
if (Directory.Exists(tempBase))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempBase, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Cleanup error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IterationSetup]
|
||||||
|
public void IterationSetup()
|
||||||
|
{
|
||||||
|
// Clean destination directory before each iteration
|
||||||
|
if (Directory.Exists(_destinationDirectory))
|
||||||
|
{
|
||||||
|
Directory.Delete(_destinationDirectory, recursive: true);
|
||||||
|
}
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Process images in parallel with chunking")]
|
||||||
|
public async Task ProcessImagesParallelWithChunks()
|
||||||
|
{
|
||||||
|
var options = new ImageCreationStuff.Options
|
||||||
|
{
|
||||||
|
SourcePath = _sourceDirectory,
|
||||||
|
DestinationPath = _destinationDirectory,
|
||||||
|
MaxThreads = MaxThreads,
|
||||||
|
ChunksSize = 10,
|
||||||
|
LinearExecution = false,
|
||||||
|
AggiornaSottodirectory = false,
|
||||||
|
CreaSottocartelle = false,
|
||||||
|
FilePerCartella = 100,
|
||||||
|
SuffissoCartelle = "",
|
||||||
|
CifreContatore = 4,
|
||||||
|
NumerazioneType = NumerazioneType.Progressiva
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = new ConcurrentBag<string>();
|
||||||
|
await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Process images in parallel without chunking")]
|
||||||
|
public async Task ProcessImagesParallelWithoutChunks()
|
||||||
|
{
|
||||||
|
var options = new ImageCreationStuff.Options
|
||||||
|
{
|
||||||
|
SourcePath = _sourceDirectory,
|
||||||
|
DestinationPath = _destinationDirectory,
|
||||||
|
MaxThreads = MaxThreads,
|
||||||
|
ChunksSize = 0, // No chunking
|
||||||
|
LinearExecution = false,
|
||||||
|
AggiornaSottodirectory = false,
|
||||||
|
CreaSottocartelle = false,
|
||||||
|
FilePerCartella = 100,
|
||||||
|
SuffissoCartelle = "",
|
||||||
|
CifreContatore = 4,
|
||||||
|
NumerazioneType = NumerazioneType.Progressiva
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = new ConcurrentBag<string>();
|
||||||
|
await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Process images linearly")]
|
||||||
|
public async Task ProcessImagesLinear()
|
||||||
|
{
|
||||||
|
var options = new ImageCreationStuff.Options
|
||||||
|
{
|
||||||
|
SourcePath = _sourceDirectory,
|
||||||
|
DestinationPath = _destinationDirectory,
|
||||||
|
MaxThreads = MaxThreads,
|
||||||
|
ChunksSize = 0,
|
||||||
|
LinearExecution = true,
|
||||||
|
AggiornaSottodirectory = false,
|
||||||
|
CreaSottocartelle = false,
|
||||||
|
FilePerCartella = 100,
|
||||||
|
SuffissoCartelle = "",
|
||||||
|
CifreContatore = 4,
|
||||||
|
NumerazioneType = NumerazioneType.Progressiva
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = new ConcurrentBag<string>();
|
||||||
|
await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
151
MaddoShared.Benchmarks/ImageSizeBenchmarks.cs
Normal file
151
MaddoShared.Benchmarks/ImageSizeBenchmarks.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Engines;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Toolchains.InProcess.Emit;
|
||||||
|
using MaddoShared.Benchmarks.Helpers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace MaddoShared.Benchmarks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Benchmarks for comparing performance with different image sizes
|
||||||
|
/// </summary>
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
[Config(typeof(InProcessConfig))]
|
||||||
|
public class ImageSizeBenchmarks
|
||||||
|
{
|
||||||
|
private string _sourceDirectory;
|
||||||
|
private string _destinationDirectory;
|
||||||
|
private ImageCreationStuff _imageCreationStuff;
|
||||||
|
private PicSettings _picSettings;
|
||||||
|
|
||||||
|
[Params(50)]
|
||||||
|
public int ImageCount { get; set; }
|
||||||
|
|
||||||
|
public enum ImageSize
|
||||||
|
{
|
||||||
|
Small, // 1280x960
|
||||||
|
Medium, // 2560x1920
|
||||||
|
Large, // 4000x3000
|
||||||
|
ExtraLarge // 6000x4000
|
||||||
|
}
|
||||||
|
|
||||||
|
[ParamsAllValues]
|
||||||
|
public ImageSize Size { get; set; }
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
var tempBase = Path.Combine(Path.GetTempPath(), "SizeBenchmarks", Guid.NewGuid().ToString());
|
||||||
|
_sourceDirectory = Path.Combine(tempBase, "Source");
|
||||||
|
_destinationDirectory = Path.Combine(tempBase, "Destination");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(_sourceDirectory);
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
|
||||||
|
var (width, height) = GetDimensions(Size);
|
||||||
|
Console.WriteLine($"Generating {ImageCount} test images at {width}x{height}...");
|
||||||
|
TestImageGenerator.GenerateTestImages(_sourceDirectory, ImageCount, width, height);
|
||||||
|
|
||||||
|
var loggerFactory = LoggerFactory.Create(builder =>
|
||||||
|
{
|
||||||
|
builder.SetMinimumLevel(LogLevel.Warning);
|
||||||
|
});
|
||||||
|
|
||||||
|
var logger = loggerFactory.CreateLogger<ImageCreationStuff>();
|
||||||
|
var imageCreatorLogger = loggerFactory.CreateLogger<ImageCreatorSharp>();
|
||||||
|
|
||||||
|
_picSettings = new PicSettings
|
||||||
|
{
|
||||||
|
DirectorySorgente = _sourceDirectory,
|
||||||
|
DirectoryDestinazione = _destinationDirectory,
|
||||||
|
DimStandard = 800,
|
||||||
|
DimStandardMiniatura = 200,
|
||||||
|
LarghezzaBig = 1024,
|
||||||
|
AltezzaBig = 768,
|
||||||
|
LarghezzaSmall = 200,
|
||||||
|
AltezzaSmall = 150,
|
||||||
|
CreaMiniature = true,
|
||||||
|
AggiungiScritteMiniature = false,
|
||||||
|
UsaForzaJpg = true,
|
||||||
|
UsaRotazioneAutomatica = true,
|
||||||
|
LogoAggiungi = false,
|
||||||
|
FotoGrandeDimOrigina = false,
|
||||||
|
TestoNome = false,
|
||||||
|
NomeData = false,
|
||||||
|
Suffisso = "_small",
|
||||||
|
Margine = 10,
|
||||||
|
Trasparenza = 100
|
||||||
|
};
|
||||||
|
|
||||||
|
var imageCreatorService = new ImageCreatorSharp(_picSettings, imageCreatorLogger);
|
||||||
|
_imageCreationStuff = new ImageCreationStuff(logger, _picSettings, imageCreatorService);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (int width, int height) GetDimensions(ImageSize size)
|
||||||
|
{
|
||||||
|
return size switch
|
||||||
|
{
|
||||||
|
ImageSize.Small => (1280, 960),
|
||||||
|
ImageSize.Medium => (2560, 1920),
|
||||||
|
ImageSize.Large => (4000, 3000),
|
||||||
|
ImageSize.ExtraLarge => (6000, 4000),
|
||||||
|
_ => throw new ArgumentException($"Unknown size: {size}")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[GlobalCleanup]
|
||||||
|
public void Cleanup()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tempBase = Path.GetDirectoryName(_sourceDirectory);
|
||||||
|
if (Directory.Exists(tempBase))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempBase, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Cleanup error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IterationSetup]
|
||||||
|
public void IterationSetup()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(_destinationDirectory))
|
||||||
|
{
|
||||||
|
Directory.Delete(_destinationDirectory, recursive: true);
|
||||||
|
}
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public async Task ProcessDifferentImageSizes()
|
||||||
|
{
|
||||||
|
var options = new ImageCreationStuff.Options
|
||||||
|
{
|
||||||
|
SourcePath = _sourceDirectory,
|
||||||
|
DestinationPath = _destinationDirectory,
|
||||||
|
MaxThreads = Environment.ProcessorCount,
|
||||||
|
ChunksSize = 10,
|
||||||
|
LinearExecution = false,
|
||||||
|
AggiornaSottodirectory = false,
|
||||||
|
CreaSottocartelle = false,
|
||||||
|
FilePerCartella = 100,
|
||||||
|
SuffissoCartelle = "",
|
||||||
|
CifreContatore = 4,
|
||||||
|
NumerazioneType = NumerazioneType.Progressiva
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = new ConcurrentBag<string>();
|
||||||
|
await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
|
||||||
|
}
|
||||||
|
}
|
||||||
21
MaddoShared.Benchmarks/MaddoShared.Benchmarks.csproj
Normal file
21
MaddoShared.Benchmarks/MaddoShared.Benchmarks.csproj
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net10.0-windows</TargetFramework>
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="10.0.2" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\MaddoShared\MaddoShared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
35
MaddoShared.Benchmarks/Program.cs
Normal file
35
MaddoShared.Benchmarks/Program.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Running;
|
||||||
|
using BenchmarkDotNet.Toolchains.InProcess.Emit;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace MaddoShared.Benchmarks;
|
||||||
|
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// Check if --job argument is provided
|
||||||
|
bool hasJobArg = args.Any(a => a.Contains("--job"));
|
||||||
|
|
||||||
|
if (hasJobArg)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Note: Overriding --job argument to use InProcess toolchain");
|
||||||
|
Console.WriteLine("This is required to avoid net10.0 vs net10.0-windows compatibility issues.");
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
// Remove --job arguments and add our own InProcess config
|
||||||
|
args = args.Where(a => !a.StartsWith("--job") && a != "dry" && a != "short").ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create configuration that always uses InProcess toolchain
|
||||||
|
var config = DefaultConfig.Instance
|
||||||
|
.WithOptions(ConfigOptions.DisableOptimizationsValidator)
|
||||||
|
.WithOptions(ConfigOptions.KeepBenchmarkFiles);
|
||||||
|
|
||||||
|
// Run benchmarks - each class has [Config(typeof(InProcessConfig))] which provides InProcess toolchain
|
||||||
|
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
172
MaddoShared.Benchmarks/StressTestBenchmark.cs
Normal file
172
MaddoShared.Benchmarks/StressTestBenchmark.cs
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using BenchmarkDotNet.Configs;
|
||||||
|
using BenchmarkDotNet.Jobs;
|
||||||
|
using BenchmarkDotNet.Toolchains.InProcess.Emit;
|
||||||
|
using MaddoShared.Benchmarks.Helpers;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace MaddoShared.Benchmarks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stress test benchmark for large-scale image processing
|
||||||
|
/// WARNING: This will generate a large number of images and may take significant time and disk space
|
||||||
|
/// </summary>
|
||||||
|
[MemoryDiagnoser]
|
||||||
|
[Config(typeof(InProcessConfig))]
|
||||||
|
public class StressTestBenchmark
|
||||||
|
{
|
||||||
|
private string _sourceDirectory;
|
||||||
|
private string _destinationDirectory;
|
||||||
|
private ImageCreationStuff _imageCreationStuff;
|
||||||
|
private PicSettings _picSettings;
|
||||||
|
|
||||||
|
[Params(500, 1000)]
|
||||||
|
public int ImageCount { get; set; }
|
||||||
|
|
||||||
|
[GlobalSetup]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
var tempBase = Path.Combine(Path.GetTempPath(), "StressTestBenchmarks", Guid.NewGuid().ToString());
|
||||||
|
_sourceDirectory = Path.Combine(tempBase, "Source");
|
||||||
|
_destinationDirectory = Path.Combine(tempBase, "Destination");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(_sourceDirectory);
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
|
||||||
|
Console.WriteLine($"[STRESS TEST] Generating {ImageCount} test images...");
|
||||||
|
Console.WriteLine("This may take several minutes depending on your hardware.");
|
||||||
|
|
||||||
|
// Use smaller images for stress test to save space and time
|
||||||
|
TestImageGenerator.GenerateTestImages(_sourceDirectory, ImageCount, width: 1920, height: 1080);
|
||||||
|
|
||||||
|
var loggerFactory = LoggerFactory.Create(builder =>
|
||||||
|
{
|
||||||
|
builder.SetMinimumLevel(LogLevel.Warning);
|
||||||
|
});
|
||||||
|
|
||||||
|
var logger = loggerFactory.CreateLogger<ImageCreationStuff>();
|
||||||
|
var imageCreatorLogger = loggerFactory.CreateLogger<ImageCreatorSharp>();
|
||||||
|
|
||||||
|
_picSettings = new PicSettings
|
||||||
|
{
|
||||||
|
DirectorySorgente = _sourceDirectory,
|
||||||
|
DirectoryDestinazione = _destinationDirectory,
|
||||||
|
DimStandard = 800,
|
||||||
|
DimStandardMiniatura = 200,
|
||||||
|
LarghezzaBig = 1024,
|
||||||
|
AltezzaBig = 768,
|
||||||
|
LarghezzaSmall = 200,
|
||||||
|
AltezzaSmall = 150,
|
||||||
|
CreaMiniature = true,
|
||||||
|
AggiungiScritteMiniature = false,
|
||||||
|
UsaForzaJpg = true,
|
||||||
|
UsaRotazioneAutomatica = true,
|
||||||
|
LogoAggiungi = false,
|
||||||
|
FotoGrandeDimOrigina = false,
|
||||||
|
TestoNome = false,
|
||||||
|
NomeData = false,
|
||||||
|
Suffisso = "_small",
|
||||||
|
Margine = 10,
|
||||||
|
Trasparenza = 100
|
||||||
|
};
|
||||||
|
|
||||||
|
var imageCreatorService = new ImageCreatorSharp(_picSettings, imageCreatorLogger);
|
||||||
|
_imageCreationStuff = new ImageCreationStuff(logger, _picSettings, imageCreatorService);
|
||||||
|
|
||||||
|
Console.WriteLine($"[STRESS TEST] Setup complete. Ready to process {ImageCount} images.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[GlobalCleanup]
|
||||||
|
public void Cleanup()
|
||||||
|
{
|
||||||
|
Console.WriteLine("[STRESS TEST] Cleaning up test data...");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var tempBase = Path.GetDirectoryName(_sourceDirectory);
|
||||||
|
if (Directory.Exists(tempBase))
|
||||||
|
{
|
||||||
|
Directory.Delete(tempBase, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Cleanup error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[IterationSetup]
|
||||||
|
public void IterationSetup()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(_destinationDirectory))
|
||||||
|
{
|
||||||
|
Directory.Delete(_destinationDirectory, recursive: true);
|
||||||
|
}
|
||||||
|
Directory.CreateDirectory(_destinationDirectory);
|
||||||
|
GC.Collect(GC.MaxGeneration, GCCollectionMode.Aggressive, blocking: true, compacting: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Stress test with optimal settings")]
|
||||||
|
public async Task StressTestOptimalSettings()
|
||||||
|
{
|
||||||
|
var options = new ImageCreationStuff.Options
|
||||||
|
{
|
||||||
|
SourcePath = _sourceDirectory,
|
||||||
|
DestinationPath = _destinationDirectory,
|
||||||
|
MaxThreads = Environment.ProcessorCount,
|
||||||
|
ChunksSize = 25, // Process in chunks to manage memory
|
||||||
|
LinearExecution = false,
|
||||||
|
AggiornaSottodirectory = false,
|
||||||
|
CreaSottocartelle = false,
|
||||||
|
FilePerCartella = 100,
|
||||||
|
SuffissoCartelle = "",
|
||||||
|
CifreContatore = 4,
|
||||||
|
NumerazioneType = NumerazioneType.Progressiva
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = new ConcurrentBag<string>();
|
||||||
|
var startTime = DateTime.Now;
|
||||||
|
|
||||||
|
await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
|
||||||
|
|
||||||
|
var duration = DateTime.Now - startTime;
|
||||||
|
var throughput = ImageCount / duration.TotalSeconds;
|
||||||
|
|
||||||
|
Console.WriteLine($"[STRESS TEST] Processed {results.Count}/{ImageCount} images in {duration.TotalSeconds:F2}s");
|
||||||
|
Console.WriteLine($"[STRESS TEST] Throughput: {throughput:F2} images/second");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark(Description = "Stress test with aggressive memory management")]
|
||||||
|
public async Task StressTestAggressiveMemoryManagement()
|
||||||
|
{
|
||||||
|
var options = new ImageCreationStuff.Options
|
||||||
|
{
|
||||||
|
SourcePath = _sourceDirectory,
|
||||||
|
DestinationPath = _destinationDirectory,
|
||||||
|
MaxThreads = Environment.ProcessorCount / 2, // Reduce threads to save memory
|
||||||
|
ChunksSize = 10, // Smaller chunks for more frequent GC
|
||||||
|
LinearExecution = false,
|
||||||
|
AggiornaSottodirectory = false,
|
||||||
|
CreaSottocartelle = false,
|
||||||
|
FilePerCartella = 100,
|
||||||
|
SuffissoCartelle = "",
|
||||||
|
CifreContatore = 4,
|
||||||
|
NumerazioneType = NumerazioneType.Progressiva
|
||||||
|
};
|
||||||
|
|
||||||
|
var results = new ConcurrentBag<string>();
|
||||||
|
var startTime = DateTime.Now;
|
||||||
|
|
||||||
|
await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None);
|
||||||
|
|
||||||
|
var duration = DateTime.Now - startTime;
|
||||||
|
var throughput = ImageCount / duration.TotalSeconds;
|
||||||
|
|
||||||
|
Console.WriteLine($"[STRESS TEST] Processed {results.Count}/{ImageCount} images in {duration.TotalSeconds:F2}s");
|
||||||
|
Console.WriteLine($"[STRESS TEST] Throughput: {throughput:F2} images/second");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -52,6 +52,15 @@ namespace MaddoShared
|
||||||
$"{stopwatch.Elapsed.Hours}h {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s ({stopwatch.Elapsed.TotalSeconds}s)";
|
$"{stopwatch.Elapsed.Hours}h {stopwatch.Elapsed.Minutes}m {stopwatch.Elapsed.Seconds}s ({stopwatch.Elapsed.TotalSeconds}s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the list of files that will be processed based on the provided options.
|
||||||
|
/// Useful for benchmarking and testing to understand the scope of work.
|
||||||
|
/// </summary>
|
||||||
|
public List<FileData> GetFilesToProcessPublic(Options options)
|
||||||
|
{
|
||||||
|
return GetFilesToProcess(options);
|
||||||
|
}
|
||||||
|
|
||||||
public async Task ProcessImagesParallel(
|
public async Task ProcessImagesParallel(
|
||||||
Options options,
|
Options options,
|
||||||
ConcurrentBag<string> results,
|
ConcurrentBag<string> results,
|
||||||
|
|
|
||||||
|
|
@ -194,6 +194,21 @@ public class ImageCreatorSharp(PicSettings picSettings, ILogger<ImageCreatorShar
|
||||||
// nomeFileBig = NomeFileChild
|
// nomeFileBig = NomeFileChild
|
||||||
imgState.NomeFileSmall = picSettings.Suffisso + imgState.WorkFile.Name;
|
imgState.NomeFileSmall = picSettings.Suffisso + imgState.WorkFile.Name;
|
||||||
imgState.NomeFileBig = imgState.WorkFile.Name;
|
imgState.NomeFileBig = imgState.WorkFile.Name;
|
||||||
|
// Sanitize file names to avoid invalid characters causing IO errors
|
||||||
|
imgState.NomeFileSmall = SanitizeFileName(imgState.NomeFileSmall);
|
||||||
|
imgState.NomeFileBig = SanitizeFileName(imgState.NomeFileBig);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string SanitizeFileName(string fileName)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(fileName)) return fileName;
|
||||||
|
var invalid = Path.GetInvalidFileNameChars();
|
||||||
|
var sb = new System.Text.StringBuilder(fileName.Length);
|
||||||
|
foreach (var ch in fileName)
|
||||||
|
{
|
||||||
|
sb.Append(Array.IndexOf(invalid, ch) >= 0 ? '_' : ch);
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PrepareThumbnailSize(Image g, ImageState imgState)
|
private void PrepareThumbnailSize(Image g, ImageState imgState)
|
||||||
|
|
|
||||||
|
|
@ -1010,6 +1010,8 @@ namespace ImageCatalog_2
|
||||||
public event EventHandler<string> SaveSettingsRequested;
|
public event EventHandler<string> SaveSettingsRequested;
|
||||||
public event EventHandler<string> LoadSettingsRequested;
|
public event EventHandler<string> LoadSettingsRequested;
|
||||||
public event EventHandler SelectColorRequested;
|
public event EventHandler SelectColorRequested;
|
||||||
|
// Request that the View shows a message to the user (message, caption, icon)
|
||||||
|
public event EventHandler<Tuple<string, string, MessageBoxIcon>> ShowMessageRequested;
|
||||||
|
|
||||||
private void SelectSourceFolder(object parameter)
|
private void SelectSourceFolder(object parameter)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
628
imagecatalog/MainForm.Designer.cs
generated
628
imagecatalog/MainForm.Designer.cs
generated
File diff suppressed because it is too large
Load diff
|
|
@ -7,6 +7,7 @@ using System.Drawing.Text;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
@ -47,6 +48,10 @@ public partial class MainForm
|
||||||
|
|
||||||
BindControls();
|
BindControls();
|
||||||
|
|
||||||
|
// Wire up 'Open folder in Explorer' buttons
|
||||||
|
btnOpenSourceFolder.Click += BtnOpenSourceFolder_Click;
|
||||||
|
btnOpenDestFolder.Click += BtnOpenDestFolder_Click;
|
||||||
|
|
||||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
_Label27.Text = $"Version: {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
|
_Label27.Text = $"Version: {version.Major}.{version.Minor}.{version.Build}.{version.Revision}";
|
||||||
}
|
}
|
||||||
|
|
@ -70,6 +75,21 @@ public partial class MainForm
|
||||||
Model.SaveSettingsRequested += OnSaveSettingsRequested;
|
Model.SaveSettingsRequested += OnSaveSettingsRequested;
|
||||||
Model.LoadSettingsRequested += OnLoadSettingsRequested;
|
Model.LoadSettingsRequested += OnLoadSettingsRequested;
|
||||||
Model.SelectColorRequested += OnSelectColorRequested;
|
Model.SelectColorRequested += OnSelectColorRequested;
|
||||||
|
// Show message requests (from ViewModel validation)
|
||||||
|
Model.ShowMessageRequested += OnShowMessageRequested;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnShowMessageRequested(object? sender, Tuple<string, string, MessageBoxIcon> args)
|
||||||
|
{
|
||||||
|
if (args is null) return;
|
||||||
|
// Ensure call on UI thread
|
||||||
|
if (InvokeRequired)
|
||||||
|
{
|
||||||
|
Invoke(new Action(() => OnShowMessageRequested(sender, args)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBox.Show(this, args.Item1, args.Item2, MessageBoxButtons.OK, args.Item3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetDefaults()
|
private void SetDefaults()
|
||||||
|
|
@ -181,6 +201,57 @@ public partial class MainForm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BtnOpenSourceFolder_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
// Prefer the model value but fall back to the textbox if needed
|
||||||
|
var path = string.IsNullOrWhiteSpace(Model.SourcePath) ? txtSorgente.Text : Model.SourcePath;
|
||||||
|
OpenFolder(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BtnOpenDestFolder_Click(object? sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var path = string.IsNullOrWhiteSpace(Model.DestinationPath) ? txtDestinazione.Text : Model.DestinationPath;
|
||||||
|
OpenFolder(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OpenFolder(string? path)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(path))
|
||||||
|
{
|
||||||
|
MessageBox.Show(this, "Folder path is empty.", "Open Folder", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = path.Trim().Trim('"');
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (File.Exists(path))
|
||||||
|
{
|
||||||
|
// If a file was provided, open its folder and select it
|
||||||
|
Process.Start("explorer.exe", $"/select,\"{path}\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = path,
|
||||||
|
UseShellExecute = true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBox.Show(this, $"Folder does not exist: {path}", "Open Folder", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger?.LogError(ex, "Failed to open folder {Path}", path);
|
||||||
|
MessageBox.Show(this, $"Failed to open folder: {ex.Message}", "Open Folder", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnSelectDestinationFolderRequested(object sender, EventArgs e)
|
private void OnSelectDestinationFolderRequested(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
var dialogResult = SelectFolder(Model.DestinationPath);
|
var dialogResult = SelectFolder(Model.DestinationPath);
|
||||||
|
|
|
||||||
124
run-benchmarks.ps1
Normal file
124
run-benchmarks.ps1
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
# Image Processing Benchmark Runner
|
||||||
|
# This script provides easy access to common benchmark scenarios
|
||||||
|
|
||||||
|
param(
|
||||||
|
[Parameter(Position=0)]
|
||||||
|
[ValidateSet("all", "quick", "parallel", "chunks", "sizes", "stress", "help")]
|
||||||
|
[string]$Scenario = "help",
|
||||||
|
|
||||||
|
[switch]$Fast,
|
||||||
|
[switch]$DetailedOutput
|
||||||
|
)
|
||||||
|
|
||||||
|
$projectPath = "MaddoShared.Benchmarks"
|
||||||
|
|
||||||
|
function Show-Help {
|
||||||
|
Write-Host @"
|
||||||
|
Image Processing Benchmark Runner
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Usage: .\run-benchmarks.ps1 [scenario] [-Fast] [-DetailedOutput]
|
||||||
|
|
||||||
|
Scenarios:
|
||||||
|
all - Run all benchmarks (60-120 minutes)
|
||||||
|
quick - Fast test run for development (5-10 minutes)
|
||||||
|
parallel - Test parallel processing strategies (20-30 minutes)
|
||||||
|
chunks - Optimize chunk size (20-30 minutes)
|
||||||
|
sizes - Test different image sizes (45-90 minutes)
|
||||||
|
stress - Large-scale stress test (2-4 hours)
|
||||||
|
help - Show this help message
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-Fast - Use dry run for faster but less accurate results
|
||||||
|
-DetailedOutput - Show detailed output
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
.\run-benchmarks.ps1 quick
|
||||||
|
.\run-benchmarks.ps1 parallel -Fast
|
||||||
|
.\run-benchmarks.ps1 stress -DetailedOutput
|
||||||
|
|
||||||
|
Results will be saved to: MaddoShared.Benchmarks\BenchmarkDotNet.Artifacts\results\
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
function Run-Benchmark {
|
||||||
|
param(
|
||||||
|
[string]$Filter,
|
||||||
|
[string]$Description
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host "`n========================================" -ForegroundColor Cyan
|
||||||
|
Write-Host " $Description" -ForegroundColor Cyan
|
||||||
|
Write-Host "========================================`n" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
$args = @("-c", "Release")
|
||||||
|
|
||||||
|
if ($Filter) {
|
||||||
|
$args += @("--", "--filter", $Filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Note: We don't pass --job arguments anymore because they override
|
||||||
|
# the InProcess toolchain configuration needed for Windows compatibility
|
||||||
|
if ($Fast) {
|
||||||
|
Write-Host "Note: Fast mode (-Fast) requested but not using --job dry" -ForegroundColor Yellow
|
||||||
|
Write-Host "Reason: --job arguments override InProcess toolchain config" -ForegroundColor Yellow
|
||||||
|
Write-Host "The benchmark will run with the default InProcessConfig settings.`n" -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($DetailedOutput) {
|
||||||
|
$args += "--verbosity", "detailed"
|
||||||
|
}
|
||||||
|
|
||||||
|
Push-Location $projectPath
|
||||||
|
try {
|
||||||
|
dotnet run @args
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
Pop-Location
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
switch ($Scenario) {
|
||||||
|
"help" {
|
||||||
|
Show-Help
|
||||||
|
}
|
||||||
|
|
||||||
|
"all" {
|
||||||
|
Write-Host "Running ALL benchmarks..." -ForegroundColor Yellow
|
||||||
|
Write-Host "This will take 60-120 minutes. Press Ctrl+C to cancel.`n" -ForegroundColor Yellow
|
||||||
|
Start-Sleep -Seconds 3
|
||||||
|
Run-Benchmark "" "All Benchmarks"
|
||||||
|
}
|
||||||
|
|
||||||
|
"quick" {
|
||||||
|
Write-Host "Running QUICK test..." -ForegroundColor Green
|
||||||
|
Run-Benchmark "*ImageProcessingBenchmarks*" "Quick Development Test"
|
||||||
|
}
|
||||||
|
|
||||||
|
"parallel" {
|
||||||
|
Write-Host "Running PARALLEL processing benchmarks..." -ForegroundColor Green
|
||||||
|
Run-Benchmark "*ImageProcessingBenchmarks*" "Parallel Processing Strategies"
|
||||||
|
}
|
||||||
|
|
||||||
|
"chunks" {
|
||||||
|
Write-Host "Running CHUNK SIZE optimization..." -ForegroundColor Green
|
||||||
|
Run-Benchmark "*ChunkSizeBenchmarks*" "Chunk Size Optimization"
|
||||||
|
}
|
||||||
|
|
||||||
|
"sizes" {
|
||||||
|
Write-Host "Running IMAGE SIZE comparison..." -ForegroundColor Green
|
||||||
|
Run-Benchmark "*ImageSizeBenchmarks*" "Image Size Impact Analysis"
|
||||||
|
}
|
||||||
|
|
||||||
|
"stress" {
|
||||||
|
Write-Host "Running STRESS TEST..." -ForegroundColor Red
|
||||||
|
Write-Host "WARNING: This will take 2-4 hours and use significant disk space!" -ForegroundColor Red
|
||||||
|
Write-Host "Press Ctrl+C within 5 seconds to cancel...`n" -ForegroundColor Red
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
Run-Benchmark "*StressTestBenchmark*" "Large-Scale Stress Test"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "`nBenchmark execution complete!" -ForegroundColor Green
|
||||||
|
Write-Host "Results saved to: $projectPath\BenchmarkDotNet.Artifacts\results\" -ForegroundColor Green
|
||||||
134
run-benchmarks.sh
Normal file
134
run-benchmarks.sh
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Image Processing Benchmark Runner (Linux/Mac)
|
||||||
|
# This script provides easy access to common benchmark scenarios
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
cat << EOF
|
||||||
|
Image Processing Benchmark Runner
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Usage: ./run-benchmarks.sh [scenario] [--fast] [--verbose]
|
||||||
|
|
||||||
|
Scenarios:
|
||||||
|
all - Run all benchmarks (60-120 minutes)
|
||||||
|
quick - Fast test run for development (5-10 minutes)
|
||||||
|
parallel - Test parallel processing strategies (20-30 minutes)
|
||||||
|
chunks - Optimize chunk size (20-30 minutes)
|
||||||
|
sizes - Test different image sizes (45-90 minutes)
|
||||||
|
stress - Large-scale stress test (2-4 hours)
|
||||||
|
help - Show this help message
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
--fast - Use dry run for faster but less accurate results
|
||||||
|
--verbose - Show detailed output
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
./run-benchmarks.sh quick
|
||||||
|
./run-benchmarks.sh parallel --fast
|
||||||
|
./run-benchmarks.sh stress --verbose
|
||||||
|
|
||||||
|
Results will be saved to: MaddoShared.Benchmarks/BenchmarkDotNet.Artifacts/results/
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
run_benchmark() {
|
||||||
|
local filter=$1
|
||||||
|
local description=$2
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "========================================"
|
||||||
|
echo " $description"
|
||||||
|
echo "========================================"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
local args="-c Release"
|
||||||
|
|
||||||
|
if [ -n "$filter" ]; then
|
||||||
|
args="$args -- --filter \"$filter\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$fast_mode" = true ]; then
|
||||||
|
args="$args --job dry"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$verbose_mode" = true ]; then
|
||||||
|
args="$args --verbose"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd MaddoShared.Benchmarks
|
||||||
|
eval "dotnet run $args"
|
||||||
|
cd ..
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
scenario="${1:-help}"
|
||||||
|
fast_mode=false
|
||||||
|
verbose_mode=false
|
||||||
|
|
||||||
|
shift
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--fast)
|
||||||
|
fast_mode=true
|
||||||
|
;;
|
||||||
|
--verbose)
|
||||||
|
verbose_mode=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
case "$scenario" in
|
||||||
|
help)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
|
||||||
|
all)
|
||||||
|
echo "Running ALL benchmarks..."
|
||||||
|
echo "This will take 60-120 minutes. Press Ctrl+C to cancel."
|
||||||
|
echo ""
|
||||||
|
sleep 3
|
||||||
|
run_benchmark "" "All Benchmarks"
|
||||||
|
;;
|
||||||
|
|
||||||
|
quick)
|
||||||
|
echo "Running QUICK test..."
|
||||||
|
run_benchmark "*ImageProcessingBenchmarks*" "Quick Development Test"
|
||||||
|
;;
|
||||||
|
|
||||||
|
parallel)
|
||||||
|
echo "Running PARALLEL processing benchmarks..."
|
||||||
|
run_benchmark "*ImageProcessingBenchmarks*" "Parallel Processing Strategies"
|
||||||
|
;;
|
||||||
|
|
||||||
|
chunks)
|
||||||
|
echo "Running CHUNK SIZE optimization..."
|
||||||
|
run_benchmark "*ChunkSizeBenchmarks*" "Chunk Size Optimization"
|
||||||
|
;;
|
||||||
|
|
||||||
|
sizes)
|
||||||
|
echo "Running IMAGE SIZE comparison..."
|
||||||
|
run_benchmark "*ImageSizeBenchmarks*" "Image Size Impact Analysis"
|
||||||
|
;;
|
||||||
|
|
||||||
|
stress)
|
||||||
|
echo "Running STRESS TEST..."
|
||||||
|
echo "WARNING: This will take 2-4 hours and use significant disk space!"
|
||||||
|
echo "Press Ctrl+C within 5 seconds to cancel..."
|
||||||
|
echo ""
|
||||||
|
sleep 5
|
||||||
|
run_benchmark "*StressTestBenchmark*" "Large-Scale Stress Test"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown scenario: $scenario"
|
||||||
|
echo "Run './run-benchmarks.sh help' for usage information"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Benchmark execution complete!"
|
||||||
|
echo "Results saved to: MaddoShared.Benchmarks/BenchmarkDotNet.Artifacts/results/"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue