using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using System.Text; using AdvChkSys; using AdvChkSys.Chunk; using AdvChkSys.Manager; using AdvChkSys.Constraints; using AdvChkSys.Diagnostics; namespace ChunkMark { public static class Program { private static readonly ConsoleColor _headerColor = ConsoleColor.Cyan; private static readonly ConsoleColor _resultColor = ConsoleColor.Green; private static readonly ConsoleColor _memoryColor = ConsoleColor.Yellow; private static readonly ConsoleColor _errorColor = ConsoleColor.Red; private static readonly ConsoleColor _infoColor = ConsoleColor.Gray; private static List _results = new List(); private static bool _verboseMode = false; public static void Main(string[] args) { int cpuCount = Environment.ProcessorCount; int num2DChunks = 10000; int chunk2DSize = 32; int num3DChunks = 500; int chunk3DWidth = 16, chunk3DHeight = 16, chunk3DDepth = 16; int maxLoaded = 100000; bool run2D = true, run3D = true; bool runMemoryTest = false; bool runStressTest = false; // Parse args foreach (var arg in args) { if (arg.StartsWith("--cpus=")) cpuCount = int.Parse(arg.Substring(7)); if (arg.StartsWith("--2d-chunks=")) num2DChunks = int.Parse(arg.Substring(12)); if (arg.StartsWith("--2d-size=")) chunk2DSize = int.Parse(arg.Substring(10)); if (arg.StartsWith("--3d-chunks=")) num3DChunks = int.Parse(arg.Substring(12)); if (arg.StartsWith("--3d-width=")) chunk3DWidth = int.Parse(arg.Substring(11)); if (arg.StartsWith("--3d-height=")) chunk3DHeight = int.Parse(arg.Substring(12)); if (arg.StartsWith("--3d-depth=")) chunk3DDepth = int.Parse(arg.Substring(11)); if (arg.StartsWith("--3d-size=")) { int val = int.Parse(arg.Substring(10)); chunk3DWidth = chunk3DHeight = chunk3DDepth = val; } if (arg.StartsWith("--max-loaded=")) maxLoaded = int.Parse(arg.Substring(13)); if (arg == "--2d-only") { run3D = false; } if (arg == "--3d-only") { run2D = false; } if (arg == "--memory-test") { runMemoryTest = true; } if (arg == "--stress-test") { runStressTest = true; } if (arg == "--verbose") { _verboseMode = true; } } PrintHeader(); if (run2D) Benchmark2D(cpuCount, num2DChunks, chunk2DSize, maxLoaded); if (run3D) { while (true) { if (!CanAllocateChunks(num3DChunks, chunk3DWidth, chunk3DHeight, chunk3DDepth, 0.82)) { long bytesPerChunk = (long)chunk3DWidth * chunk3DHeight * chunk3DDepth; long totalBytes = bytesPerChunk * num3DChunks; long available = GetAvailableMemoryBytes(); long safeLimit = (long)(available * 0.82); Console.ForegroundColor = _errorColor; Console.WriteLine($"ERROR: Requested 3D chunks would use {totalBytes / (1024 * 1024):N0} MB, but only {safeLimit / (1024 * 1024):N0} MB is safely available."); Console.WriteLine("Please input new values for 3D chunks and size within your system's memory capacity."); Console.ResetColor(); Console.ForegroundColor = _infoColor; // Using _infoColor here Console.Write("Enter number of 3D chunks (or blank to exit): "); Console.ResetColor(); var chunksInput = Console.ReadLine(); if (string.IsNullOrWhiteSpace(chunksInput)) { Console.WriteLine("Exiting benchmark."); break; } if (!int.TryParse(chunksInput, out num3DChunks) || num3DChunks <= 0) { Console.WriteLine("Invalid input. Exiting."); break; } Console.ForegroundColor = _infoColor; // Using _infoColor here Console.Write("Enter 3D chunk width: "); Console.ResetColor(); var widthInput = Console.ReadLine(); if (string.IsNullOrWhiteSpace(widthInput) || !int.TryParse(widthInput, out chunk3DWidth) || chunk3DWidth <= 0) { Console.WriteLine("Invalid input. Exiting."); break; } Console.ForegroundColor = _infoColor; // Using _infoColor here Console.Write("Enter 3D chunk height: "); Console.ResetColor(); var heightInput = Console.ReadLine(); if (string.IsNullOrWhiteSpace(heightInput) || !int.TryParse(heightInput, out chunk3DHeight) || chunk3DHeight <= 0) { Console.WriteLine("Invalid input. Exiting."); break; } Console.ForegroundColor = _infoColor; // Using _infoColor here Console.Write("Enter 3D chunk depth: "); Console.ResetColor(); var depthInput = Console.ReadLine(); if (string.IsNullOrWhiteSpace(depthInput) || !int.TryParse(depthInput, out chunk3DDepth) || chunk3DDepth <= 0) { Console.WriteLine("Invalid input. Exiting."); break; } Console.WriteLine(); // Loop will re-check with new values } else { try { Benchmark3D(cpuCount, num3DChunks, chunk3DWidth, chunk3DHeight, chunk3DDepth, maxLoaded); } catch (OutOfMemoryException) { Console.ForegroundColor = _errorColor; Console.WriteLine("ERROR: Out of memory during 3D chunk allocation. Reduce chunk size or count."); Console.ResetColor(); } break; } } } if (runMemoryTest) { RunMemoryTest(cpuCount, chunk2DSize, chunk3DWidth, chunk3DHeight, chunk3DDepth); } if (runStressTest) { RunStressTest(cpuCount, chunk2DSize, chunk3DWidth, chunk3DHeight, chunk3DDepth); } PrintSummary(); Console.ForegroundColor = _infoColor; // Using _infoColor here Console.WriteLine("\nDone. Press any key to exit."); Console.ResetColor(); Console.ReadKey(); } private static void PrintHeader() { Console.ForegroundColor = _headerColor; Console.WriteLine("╔═══════════════════════════════════════════════════════════════╗"); Console.WriteLine("║ ChunkMark: AdvChkSys Benchmark ║"); Console.WriteLine("╚═══════════════════════════════════════════════════════════════╝"); Console.ResetColor(); Console.WriteLine($"Library version: {AdvChkSys.AdvChkSys.Version}"); Console.WriteLine($"CPU threads: {Environment.ProcessorCount}"); Console.WriteLine($"System memory: {FormatByteSize(AdvChkSys.AdvChkSys.GetMemoryUsage().TotalSystemMemoryBytes)}"); Console.WriteLine($"Available memory: {FormatByteSize(AdvChkSys.AdvChkSys.GetMemoryUsage().AvailableSystemMemoryBytes)}"); Console.WriteLine(); } private static void PrintSummary() { Console.WriteLine(); Console.ForegroundColor = _headerColor; Console.WriteLine("╔═══════════════════════════════════════════════════════════════╗"); Console.WriteLine("║ Benchmark Summary ║"); Console.WriteLine("╚═══════════════════════════════════════════════════════════════╝"); Console.ResetColor(); if (_results.Count == 0) { Console.WriteLine("No benchmark results to display."); return; } var table = new StringBuilder(); table.AppendLine("┌────────────────┬─────────────┬────────────┬────────────┬────────────┐"); table.AppendLine("│ Test │ Chunks │ Create │ Access │ Unload │"); table.AppendLine("├────────────────┼─────────────┼────────────┼────────────┼────────────┤"); foreach (var result in _results) { string testName = result.TestName.PadRight(14).Substring(0, 14); string chunkInfo = result.ChunkCount.ToString("N0").PadRight(11).Substring(0, 11); string createTime = $"{result.CreateTime:F3} s".PadRight(10).Substring(0, 10); string accessTime = $"{result.AccessTime:F3} s".PadRight(10).Substring(0, 10); string unloadTime = $"{result.UnloadTime:F3} s".PadRight(10).Substring(0, 10); table.AppendLine($"│ {testName} │ {chunkInfo} │ {createTime} │ {accessTime} │ {unloadTime} │"); } table.AppendLine("└────────────────┴─────────────┴────────────┴────────────┴────────────┘"); Console.WriteLine(table.ToString()); // Calculate and display performance metrics if (_results.Count > 0) { Console.ForegroundColor = _resultColor; Console.WriteLine("Performance Metrics:"); Console.ResetColor(); var create2DRate = _results.Where(r => r.TestName.Contains("2D")).Select(r => r.ChunkCount / r.CreateTime).FirstOrDefault(); var create3DRate = _results.Where(r => r.TestName.Contains("3D")).Select(r => r.ChunkCount / r.CreateTime).FirstOrDefault(); if (create2DRate > 0) Console.WriteLine($"2D Chunk Creation Rate: {create2DRate:N0} chunks/second"); if (create3DRate > 0) Console.WriteLine($"3D Chunk Creation Rate: {create3DRate:N0} chunks/second"); } } private static void Benchmark2D(int cpuCount, int numChunks, int chunkSize, int maxLoaded) { Console.ForegroundColor = _headerColor; Console.WriteLine($"[2D] {numChunks:N0} chunks of size {chunkSize}x{chunkSize}, maxLoaded={maxLoaded:N0}"); Console.ResetColor(); var constraints = new WorldConstraints { MinChunkX = 0, MaxChunkX = 9999, MinChunkY = 0, MaxChunkY = 9999, MaxLoadedChunks = maxLoaded }; var manager = new ChunkManager2D(constraints, maxLoaded); // Memory before test var memoryBefore = AdvChkSys.AdvChkSys.GetMemoryUsage(); if (_verboseMode) { Console.ForegroundColor = _memoryColor; Console.WriteLine($" Memory before: {FormatByteSize(memoryBefore.EstimatedChunkMemoryBytes)}"); Console.ResetColor(); } // Create and fill var sw = Stopwatch.StartNew(); Parallel.For(0, numChunks, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, i => { int x = i % 1000, y = i / 1000; var chunk = manager.LoadOrCreateChunk(x, y, chunkSize, chunkSize); for (int cx = 0; cx < chunkSize; cx++) for (int cy = 0; cy < chunkSize; cy++) chunk[cx, cy] = (byte)((cx + cy) % 256); }); sw.Stop(); double createTime = sw.Elapsed.TotalSeconds; Console.WriteLine($" Created and filled {numChunks:N0} chunks in {createTime:F3} s"); // Memory after creation var memoryAfterCreate = AdvChkSys.AdvChkSys.GetMemoryUsage(); if (_verboseMode) { Console.ForegroundColor = _memoryColor; Console.WriteLine($" Memory after creation: {FormatByteSize(memoryAfterCreate.EstimatedChunkMemoryBytes)} " + $"(+{FormatByteSize(memoryAfterCreate.EstimatedChunkMemoryBytes - memoryBefore.EstimatedChunkMemoryBytes)})"); Console.ResetColor(); } // Access (sum all cells) sw.Restart(); long total = 0; Parallel.For(0, numChunks, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, () => 0L, (i, state, localSum) => { int x = i % 1000, y = i / 1000; var chunk = manager.GetChunk(x, y); if (chunk != null) { for (int cx = 0; cx < chunkSize; cx++) for (int cy = 0; cy < chunkSize; cy++) localSum += chunk[cx, cy]; } return localSum; }, localSum => Interlocked.Add(ref total, localSum) ); sw.Stop(); double accessTime = sw.Elapsed.TotalSeconds; Console.WriteLine($" Accessed {numChunks:N0} chunks in {accessTime:F3} s (sum: {total:N0})"); // Unload sw.Restart(); Parallel.For(0, numChunks, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, i => { int x = i % 1000, y = i / 1000; manager.UnloadChunk(x, y); }); sw.Stop(); double unloadTime = sw.Elapsed.TotalSeconds; Console.WriteLine($" Unloaded {numChunks:N0} chunks in {unloadTime:F3} s"); // Memory after test var memoryAfter = AdvChkSys.AdvChkSys.GetMemoryUsage(); if (_verboseMode) { Console.ForegroundColor = _memoryColor; Console.WriteLine($" Memory after unload: {FormatByteSize(memoryAfter.EstimatedChunkMemoryBytes)} " + $"(change: {FormatByteSize(memoryAfter.EstimatedChunkMemoryBytes - memoryBefore.EstimatedChunkMemoryBytes)})"); Console.ResetColor(); } // Store results _results.Add(new BenchmarkResult { TestName = "2D Chunks", ChunkCount = numChunks, ChunkSize = $"{chunkSize}x{chunkSize}", CreateTime = createTime, AccessTime = accessTime, UnloadTime = unloadTime, MemoryUsed = memoryAfterCreate.EstimatedChunkMemoryBytes - memoryBefore.EstimatedChunkMemoryBytes }); // Force GC to clean up GC.Collect(); GC.WaitForPendingFinalizers(); } private static void Benchmark3D(int cpuCount, int numChunks, int width, int height, int depth, int maxLoaded) { Console.ForegroundColor = _headerColor; Console.WriteLine($"[3D] {numChunks:N0} chunks of size {width}x{height}x{depth}, maxLoaded={maxLoaded:N0}"); Console.ResetColor(); var constraints = new WorldConstraints { MinChunkX = 0, MaxChunkX = 9999, MinChunkY = 0, MaxChunkY = 9999, MaxLoadedChunks = maxLoaded }; var manager = new ChunkManager3D(constraints, maxLoaded); // Memory before test var memoryBefore = AdvChkSys.AdvChkSys.GetMemoryUsage(); if (_verboseMode) { Console.ForegroundColor = _memoryColor; Console.WriteLine($" Memory before: {FormatByteSize(memoryBefore.EstimatedChunkMemoryBytes)}"); Console.ResetColor(); } // Create and fill var sw = Stopwatch.StartNew(); Parallel.For(0, numChunks, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, i => { int x = i % 100, y = i / 100 % 100, z = i / 10000; var chunk = manager.LoadOrCreateChunk(x, y, z, width, height, depth); for (int cx = 0; cx < width; cx++) for (int cy = 0; cy < height; cy++) for (int cz = 0; cz < depth; cz++) chunk[cx, cy, cz] = (byte)((cx + cy + cz) % 256); }); sw.Stop(); double createTime = sw.Elapsed.TotalSeconds; Console.WriteLine($" Created and filled {numChunks:N0} chunks in {createTime:F3} s"); // Memory after creation var memoryAfterCreate = AdvChkSys.AdvChkSys.GetMemoryUsage(); if (_verboseMode) { Console.ForegroundColor = _memoryColor; Console.WriteLine($" Memory after creation: {FormatByteSize(memoryAfterCreate.EstimatedChunkMemoryBytes)} " + $"(+{FormatByteSize(memoryAfterCreate.EstimatedChunkMemoryBytes - memoryBefore.EstimatedChunkMemoryBytes)})"); Console.ResetColor(); } // Access (sum all cells) sw.Restart(); long total = 0; Parallel.For(0, numChunks, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, () => 0L, (i, state, localSum) => { int x = i % 100, y = i / 100 % 100, z = i / 10000; var chunk = manager.GetChunk(x, y, z); if (chunk != null) { for (int cx = 0; cx < width; cx++) for (int cy = 0; cy < height; cy++) for (int cz = 0; cz < depth; cz++) localSum += chunk[cx, cy, cz]; } return localSum; }, localSum => Interlocked.Add(ref total, localSum) ); sw.Stop(); double accessTime = sw.Elapsed.TotalSeconds; Console.WriteLine($" Accessed {numChunks:N0} chunks in {accessTime:F3} s (sum: {total:N0})"); // Unload sw.Restart(); Parallel.For(0, numChunks, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, i => { int x = i % 100, y = i / 100 % 100, z = i / 10000; manager.UnloadChunk(x, y, z); }); sw.Stop(); double unloadTime = sw.Elapsed.TotalSeconds; Console.WriteLine($" Unloaded {numChunks:N0} chunks in {unloadTime:F3} s"); // Memory after test var memoryAfter = AdvChkSys.AdvChkSys.GetMemoryUsage(); if (_verboseMode) { Console.ForegroundColor = _memoryColor; Console.WriteLine($" Memory after unload: {FormatByteSize(memoryAfter.EstimatedChunkMemoryBytes)} " + $"(change: {FormatByteSize(memoryAfter.EstimatedChunkMemoryBytes - memoryBefore.EstimatedChunkMemoryBytes)})"); Console.ResetColor(); } // Store results _results.Add(new BenchmarkResult { TestName = "3D Chunks", ChunkCount = numChunks, ChunkSize = $"{width}x{height}x{depth}", CreateTime = createTime, AccessTime = accessTime, UnloadTime = unloadTime, MemoryUsed = memoryAfterCreate.EstimatedChunkMemoryBytes - memoryBefore.EstimatedChunkMemoryBytes }); // Force GC to clean up GC.Collect(); GC.WaitForPendingFinalizers(); } private static void RunMemoryTest(int cpuCount, int chunk2DSize, int chunk3DWidth, int chunk3DHeight, int chunk3DDepth) { Console.ForegroundColor = _headerColor; Console.WriteLine("╔═══════════════════════════════════════════════════════════════╗"); Console.WriteLine("║ Memory Usage Test ║"); Console.WriteLine("╚═══════════════════════════════════════════════════════════════╝"); Console.ResetColor(); // Initial memory state var initialMemory = AdvChkSys.AdvChkSys.GetMemoryUsage(); Console.WriteLine($"Initial memory state: {FormatByteSize(initialMemory.EstimatedChunkMemoryBytes)}"); // Test 2D memory scaling Console.ForegroundColor = _headerColor; Console.WriteLine("\n[2D Memory Scaling Test]"); Console.ResetColor(); var manager2D = new ChunkManager2D(null, 1000000); var memoryPoints2D = new List<(int chunkCount, ulong memoryUsed)>(); for (int i = 1; i <= 10; i++) { int chunkCount = i * 1000; Console.WriteLine($" Loading {chunkCount:N0} 2D chunks..."); for (int j = (i - 1) * 1000; j < i * 1000; j++) { int x = j % 1000, y = j / 1000; var chunk = manager2D.LoadOrCreateChunk(x, y, chunk2DSize, chunk2DSize); // Fill with some data for (int cx = 0; cx < chunk2DSize; cx++) for (int cy = 0; cy < chunk2DSize; cy++) chunk[cx, cy] = (byte)((cx + cy) % 256); } var memoryReport = AdvChkSys.AdvChkSys.GetMemoryUsage(); memoryPoints2D.Add((chunkCount, memoryReport.EstimatedChunkMemoryBytes)); Console.WriteLine($" Memory used: {FormatByteSize(memoryReport.EstimatedChunkMemoryBytes)}"); } // Clean up 2D chunks manager2D = null; GC.Collect(); GC.WaitForPendingFinalizers(); // Test 3D memory scaling Console.ForegroundColor = _headerColor; Console.WriteLine("\n[3D Memory Scaling Test]"); Console.ResetColor(); var manager3D = new ChunkManager3D(null, 1000000); var memoryPoints3D = new List<(int chunkCount, ulong memoryUsed)>(); for (int i = 1; i <= 5; i++) { int chunkCount = i * 10; Console.WriteLine($" Loading {chunkCount:N0} 3D chunks..."); for (int j = (i - 1) * 10; j < i * 10; j++) { int x = j % 10, y = j / 10 % 10, z = j / 100; var chunk = manager3D.LoadOrCreateChunk(x, y, z, chunk3DWidth, chunk3DHeight, chunk3DDepth); // Fill with some data for (int cx = 0; cx < chunk3DWidth; cx++) for (int cy = 0; cy < chunk3DHeight; cy++) for (int cz = 0; cz < chunk3DDepth; cz++) chunk[cx, cy, cz] = (byte)((cx + cy + cz) % 256); } var memoryReport = AdvChkSys.AdvChkSys.GetMemoryUsage(); memoryPoints3D.Add((chunkCount, memoryReport.EstimatedChunkMemoryBytes)); Console.WriteLine($" Memory used: {FormatByteSize(memoryReport.EstimatedChunkMemoryBytes)}"); } // Clean up 3D chunks manager3D = null; GC.Collect(); GC.WaitForPendingFinalizers(); // Display memory scaling results Console.ForegroundColor = _headerColor; Console.WriteLine("\n[Memory Scaling Results]"); Console.ResetColor(); Console.WriteLine("2D Memory Scaling:"); for (int i = 0; i < memoryPoints2D.Count; i++) { var point = memoryPoints2D[i]; ulong bytesPerChunk = i > 0 ? (point.memoryUsed - memoryPoints2D[i - 1].memoryUsed) / (ulong)(point.chunkCount - memoryPoints2D[i - 1].chunkCount) : point.memoryUsed / (ulong)point.chunkCount; Console.WriteLine($" {point.chunkCount:N0} chunks: {FormatByteSize(point.memoryUsed)} " + $"(~{FormatByteSize(bytesPerChunk)}/chunk)"); } Console.WriteLine("\n3D Memory Scaling:"); for (int i = 0; i < memoryPoints3D.Count; i++) { var point = memoryPoints3D[i]; ulong bytesPerChunk = i > 0 ? (point.memoryUsed - memoryPoints3D[i - 1].memoryUsed) / (ulong)(point.chunkCount - memoryPoints3D[i - 1].chunkCount) : point.memoryUsed / (ulong)point.chunkCount; Console.WriteLine($" {point.chunkCount:N0} chunks: {FormatByteSize(point.memoryUsed)} " + $"(~{FormatByteSize(bytesPerChunk)}/chunk)"); } // Final memory state var finalMemory = AdvChkSys.AdvChkSys.GetMemoryUsage(); Console.WriteLine($"\nFinal memory state: {FormatByteSize(finalMemory.EstimatedChunkMemoryBytes)}"); Console.WriteLine($"Memory change: {FormatByteSize(finalMemory.EstimatedChunkMemoryBytes - initialMemory.EstimatedChunkMemoryBytes)}"); } private static void RunStressTest(int cpuCount, int chunk2DSize, int chunk3DWidth, int chunk3DHeight, int chunk3DDepth) { Console.ForegroundColor = _headerColor; Console.WriteLine("╔═══════════════════════════════════════════════════════════════╗"); Console.WriteLine("║ Stress Test ║"); Console.WriteLine("╚═══════════════════════════════════════════════════════════════╝"); Console.ResetColor(); // Initial memory state var initialMemory = AdvChkSys.AdvChkSys.GetMemoryUsage(); // Create managers with small cache size to force evictions var manager2D = new ChunkManager2D(null, 100); var manager3D = new ChunkManager3D(null, 50); Console.WriteLine("Running load/unload stress test (rapid chunk cycling)..."); var sw = Stopwatch.StartNew(); int iterations = 5; int chunksPerIteration = 500; for (int iter = 0; iter < iterations; iter++) { Console.WriteLine($" Iteration {iter + 1}/{iterations}..."); // 2D stress Parallel.For(0, chunksPerIteration, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, i => { int x = i % 100, y = i / 100; // Load chunk var chunk = manager2D.LoadOrCreateChunk(x, y, chunk2DSize, chunk2DSize); // Fill with data for (int cx = 0; cx < chunk2DSize; cx++) for (int cy = 0; cy < chunk2DSize; cy++) chunk[cx, cy] = (byte)((cx + cy + i) % 256); // Access chunk long sum = 0; for (int cx = 0; cx < chunk2DSize; cx++) for (int cy = 0; cy < chunk2DSize; cy++) sum += chunk[cx, cy]; // Force some evictions by loading other chunks for (int j = 0; j < 3; j++) { int otherX = (i + j * 200) % 1000; int otherY = (i + j * 200) / 1000; var otherChunk = manager2D.LoadOrCreateChunk(otherX, otherY, chunk2DSize, chunk2DSize); otherChunk[0, 0] = (byte)(i + j); } }); // 3D stress Parallel.For(0, chunksPerIteration / 10, new ParallelOptions { MaxDegreeOfParallelism = cpuCount }, i => { int x = i % 10, y = i / 10 % 10, z = i / 100; // Load chunk var chunk = manager3D.LoadOrCreateChunk(x, y, z, chunk3DWidth, chunk3DHeight, chunk3DDepth); // Fill with data (just a portion to save time) for (int cx = 0; cx < chunk3DWidth; cx++) for (int cy = 0; cy < chunk3DHeight / 4; cy++) for (int cz = 0; cz < chunk3DDepth; cz++) chunk[cx, cy, cz] = (byte)((cx + cy + cz + i) % 256); // Access chunk long sum = 0; for (int cx = 0; cx < chunk3DWidth; cx++) for (int cy = 0; cy < chunk3DHeight / 4; cy++) for (int cz = 0; cz < chunk3DDepth; cz++) sum += chunk[cx, cy, cz]; // Force some evictions by loading other chunks for (int j = 0; j < 2; j++) { int otherX = (i + j * 20) % 30; int otherY = (i + j * 20) / 30 % 30; int otherZ = (i + j * 20) / 900; var otherChunk = manager3D.LoadOrCreateChunk(otherX, otherY, otherZ, chunk3DWidth, chunk3DHeight, chunk3DDepth); otherChunk[0, 0, 0] = (byte)(i + j); } }); // Check memory after each iteration var memoryReport = AdvChkSys.AdvChkSys.GetMemoryUsage(); Console.ForegroundColor = _memoryColor; Console.WriteLine($" Memory: {FormatByteSize(memoryReport.EstimatedChunkMemoryBytes)} " + $"({memoryReport.MemoryUsagePercentage:F2}% of system memory)"); Console.ResetColor(); // Force GC between iterations GC.Collect(); GC.WaitForPendingFinalizers(); } sw.Stop(); Console.WriteLine($"Stress test completed in {sw.Elapsed.TotalSeconds:F2} seconds"); // Final memory state var finalMemory = AdvChkSys.AdvChkSys.GetMemoryUsage(); Console.WriteLine($"Final memory state: {FormatByteSize(finalMemory.EstimatedChunkMemoryBytes)}"); Console.WriteLine($"Memory change: {FormatByteSize(finalMemory.EstimatedChunkMemoryBytes - initialMemory.EstimatedChunkMemoryBytes)}"); // Clean up manager2D = null; manager3D = null; GC.Collect(); GC.WaitForPendingFinalizers(); } private static bool CanAllocateChunks(int numChunks, int width, int height, int depth, double safetyFactor) { long bytesPerChunk = (long)width * height * depth; long totalBytes = bytesPerChunk * numChunks; long available = GetAvailableMemoryBytes(); long safeLimit = (long)(available * safetyFactor); return totalBytes <= safeLimit; } private static long GetAvailableMemoryBytes() { return (long)AdvChkSys.AdvChkSys.GetMemoryUsage().AvailableSystemMemoryBytes; } private static string FormatByteSize(ulong bytes) { string[] sizes = { "B", "KB", "MB", "GB", "TB" }; double formattedSize = bytes; int order = 0; while (formattedSize >= 1024 && order < sizes.Length - 1) { order++; formattedSize /= 1024; } return $"{formattedSize:F2} {sizes[order]}"; } } public class BenchmarkResult { public string TestName { get; set; } = ""; public int ChunkCount { get; set; } public string ChunkSize { get; set; } = ""; public double CreateTime { get; set; } public double AccessTime { get; set; } public double UnloadTime { get; set; } public ulong MemoryUsed { get; set; } } }