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
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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue