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; /// /// 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 /// [MemoryDiagnoser] [Config(typeof(InProcessConfig))] public class StressTestBenchmark { private string _sourceDirectory; private string _destinationDirectory; private ImageCreationService _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(); var imageCreatorLogger = loggerFactory.CreateLogger(); _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 ImageCreatorImageSharp(_picSettings, imageCreatorLogger); _imageCreationStuff = new ImageCreationService(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 ImageCreationService.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(); 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 ImageCreationService.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(); 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"); } }