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; /// /// Benchmarks for image processing with various configurations /// [MemoryDiagnoser] [Config(typeof(InProcessConfig))] public class ImageProcessingBenchmarks { private string _sourceDirectory; private string _destinationDirectory; private ImageCreationService _imageCreationStuff; private PicSettings _picSettings; private ILogger _logger; private ILogger _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(); _imageCreatorLogger = loggerFactory.CreateLogger(); // 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 ImageCreatorGDI(_picSettings, _imageCreatorLogger); _imageCreationStuff = new ImageCreationService(_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 ImageCreationService.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(); await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None); } [Benchmark(Description = "Process images in parallel without chunking")] public async Task ProcessImagesParallelWithoutChunks() { var options = new ImageCreationService.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(); await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None); } [Benchmark(Description = "Process images linearly")] public async Task ProcessImagesLinear() { var options = new ImageCreationService.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(); await _imageCreationStuff.ProcessImagesParallel(options, results, null, CancellationToken.None); } }